Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable specifying arbitrary yaml files as alternatives of _output.yml #1634

Merged
merged 12 commits into from
Aug 31, 2019
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ rmarkdown 1.16

- It is now possible to add pagebreak in html, word, latex and odt documents using `\newpage` or `\pagebreak` command in a Rmd file. This is possible thanks to [_pandoc's pagebreak lua filter_](https://github.com/pandoc/lua-filters/tree/master/pagebreak). See `vignette("pagebreak", package = "rmarkdown")`

- Output formats can be configured by arbitrary YAML files, which used to be restricted to `_output.yml` or `_output.yaml`. They can be specified via the `output_yaml` argument of `render()` or the `output_yaml` top-level parameter of YAML front matter, and the first existing one will be used. If `output_yaml` is specified both for `render()` and YAML front matter, then `render()` has the priority. If none are found, then `_output.yml` or `_output.yaml` will be used if they exist (thanks, @atusy, #1634).

rmarkdown 1.15
================================================================================
Expand Down
65 changes: 40 additions & 25 deletions R/output_format.R
Original file line number Diff line number Diff line change
Expand Up @@ -353,22 +353,28 @@ smart_extension <- function(smart, extension) {

#' Determine the default output format for an R Markdown document
#'
#' Read the YAML metadata (and any common _output.yml file) for the
#' Read the YAML metadata (and any common output YAML file) for the
#' document and return the output format that will be generated by
#' a call to \code{\link{render}}.
#'
#' This function is useful for front-end tools that require additional
#' knowledge of the output to be produced by \code{\link{render}} (e.g. to
#' customize the preview experience).
#' @param input Input file (Rmd or plain markdown)
#' @param output_yaml Paths to YAML files specifying output formats and their
#' configurations. The first existing one is used. If none are found, then
#' the function searches YAML files specified to the \code{output_yaml} top-level
#' parameter in the YAML front matter, _output.yml or _output.yaml, and then uses
#' the first existing one.
#' @param encoding The encoding of the input file; see \code{\link{file}}
#' @return A named list with a \code{name} value containing the format
#' name and an \code{options} value that is a list containing all the options
#' for the format and their values. An option's default value will be returned
#' if the option isn't set explicitly in the document.
#' @export
default_output_format <- function(input,
encoding = "UTF-8") {
encoding = "UTF-8",
output_yaml = NULL) {

# execute within the input file's directory (this emulates the way
# yaml front matter discovery is done within render)
Expand All @@ -381,7 +387,8 @@ default_output_format <- function(input,

# parse the YAML and front matter and get the explicitly set options
input_lines <- read_utf8(input, encoding)
format <- output_format_from_yaml_front_matter(input_lines, encoding = encoding)
format <- output_format_from_yaml_front_matter(
input_lines, output_yaml = output_yaml, encoding = encoding)

# look up the formals of the output function to get the full option list and
# merge against the explicitly set list
Expand All @@ -394,12 +401,13 @@ default_output_format <- function(input,

#' Resolve the output format for an R Markdown document
#'
#' Read the YAML metadata (and any common _output.yml file) for the
#' Read the YAML metadata (and any common output YAML file) for the
#' document and return an output format object that can be
#' passed to the \code{\link{render}} function.
#'
#' This function is useful for front-end tools that need to modify
#' the default behavior of an output format.
#' @inheritParams default_output_format
#' @param input Input file (Rmd or plain markdown)
#' @param output_format Name of output format (or \code{NULL} to use
#' the default format for the input file).
Expand All @@ -412,6 +420,7 @@ default_output_format <- function(input,
resolve_output_format <- function(input,
output_format = NULL,
output_options = NULL,
output_yaml = NULL,
encoding = "UTF-8") {

# read the input file
Expand All @@ -427,6 +436,7 @@ resolve_output_format <- function(input,
input_lines,
output_options,
output_format,
output_yaml,
encoding = encoding)

# return it
Expand All @@ -436,23 +446,26 @@ resolve_output_format <- function(input,

#' Determine all output formats for an R Markdown document
#'
#' Read the YAML metadata (and any common _output.yml file) for the
#' Read the YAML metadata (and any common output YAML file) for the
#' document and return the output formats that will be generated by
#' a call to \code{\link{render}}.
#'
#' This function is useful for front-end tools that require additional
#' knowledge of the output to be produced by \code{\link{render}} (e.g. to
#' customize the preview experience).
#' @inheritParams default_output_format
#' @param input Input file (Rmd or plain markdown)
#' @param encoding The encoding of the input file; see \code{\link{file}}.
#' @return A character vector with the names of all output formats.
#' @export
all_output_formats <- function(input,
encoding = "UTF-8") {
encoding = "UTF-8",
output_yaml = NULL) {

enumerate_output_formats(
input = input,
envir = parent.frame(),
output_yaml = output_yaml,
encoding = encoding)
}

Expand All @@ -462,6 +475,7 @@ all_output_formats <- function(input,
output_format_from_yaml_front_matter <- function(input_lines,
output_options = NULL,
output_format_name = NULL,
output_yaml = NULL,
encoding = "UTF-8") {

format_name <- output_format_name
Expand All @@ -481,14 +495,12 @@ output_format_from_yaml_front_matter <- function(input_lines,
config <- site_config(".", encoding = encoding)
yaml_site <- config[["output"]]

# parse common _output.yml if we have it
yaml_common <- if (file.exists("_output.yml")) {
yaml_load_file("_output.yml")
} else if (file.exists("_output.yaml")) {
yaml_load_file("_output.yaml")
}
# parse common output yaml file if we have it
output_yaml <- c(output_yaml, yaml_input$output_yaml, "_output.yml", "_output.yaml")
output_yaml <- output_yaml[file.exists(output_yaml)][1L]
yaml_common <- if (!is.na(output_yaml)) yaml_load_file(output_yaml)

# merge _site.yml and _output.yml
# merge _site.yml and output_yaml
yaml_common <- merge_output_options(yaml_site, yaml_common)

# parse output format from front-matter if we have it
Expand All @@ -497,7 +509,7 @@ output_format_from_yaml_front_matter <- function(input_lines,
# alias the output format yaml
yaml_output <- yaml_input[["output"]]

# merge against common _output.yml
# merge against common output yaml
yaml_output <- merge_output_options(yaml_common, yaml_output)

# if a named format was provided then try to find it
Expand Down Expand Up @@ -602,7 +614,8 @@ is_output_format <- function(x) {

enumerate_output_formats <- function(input,
envir,
encoding) {
encoding,
output_yaml = NULL) {

# read the input
input_lines <- read_utf8(input, encoding)
Expand All @@ -622,15 +635,17 @@ enumerate_output_formats <- function(input,
# read the ymal front matter
yaml_front_matter <- parse_yaml_front_matter(input_lines)

# read any _output.yml
output_yml <- file.path(dirname(input), "_output.yml")
output_yaml <- file.path(dirname(input), "_output.yaml")
if (file.exists(output_yml))
common_output_format_yaml <- yaml_load_file(output_yml)
else if (file.exists(output_yaml))
common_output_format_yaml <- yaml_load_file(output_yaml)
else
common_output_format_yaml <- list()
# read any output yaml
output_yaml <- file.path(
dirname(input),
c(output_yaml, yaml_front_matter$output_yaml, "_output.yml", "_output.yaml")
)
output_yaml <- output_yaml[file.exists(output_yaml)][1L]
common_output_format_yaml <- if (is.na(output_yaml)) {
list()
} else {
yaml_load_file(output_yaml)
}

# merge site and common
common_output_format_yaml <- merge_output_options(site_output_format_yaml,
Expand All @@ -643,7 +658,7 @@ enumerate_output_formats <- function(input,
# alias the output format yaml
output_format_yaml <- yaml_front_matter[["output"]]

# merge against common _output.yml
# merge against common output yaml
output_format_yaml <- merge_output_options(common_output_format_yaml,
output_format_yaml)
} else {
Expand Down
3 changes: 3 additions & 0 deletions R/render.R
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ NULL
#' @seealso
#' \link[knitr:knit]{knit}, \link{output_format},
#' \href{http://johnmacfarlane.net/pandoc}{pandoc}
#' @inheritParams default_output_format
#' @param input The input file to be rendered. This can be an R script (.R),
#' an R Markdown document (.Rmd), or a plain markdown document.
#' @param output_format The R Markdown output format to convert to. The option
Expand Down Expand Up @@ -239,6 +240,7 @@ render <- function(input,
output_file = NULL,
output_dir = NULL,
output_options = NULL,
output_yaml = NULL,
intermediates_dir = NULL,
knit_root_dir = NULL,
runtime = c("auto", "static", "shiny", "shiny_prerendered"),
Expand Down Expand Up @@ -459,6 +461,7 @@ render <- function(input,
output_format <- output_format_from_yaml_front_matter(input_lines,
output_options,
output_format,
output_yaml,
encoding = encoding)
output_format <- create_output_format(output_format$name,
output_format$options)
Expand Down
10 changes: 8 additions & 2 deletions man/all_output_formats.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 8 additions & 2 deletions man/default_output_format.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 9 additions & 3 deletions man/render.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 8 additions & 2 deletions man/resolve_output_format.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.