Argument keep_md not inherited by custom output format that extends html_document() · Issue #1558 · rstudio/rmarkdown (original) (raw)

By filing an issue to this repo, I promise that


Note: Sorry for the strange line wrapping below. I used the output formatgithub_document(), but apparently GitHub markdown now respects line breaks. I manually fixed a few of the more egregious breaks below.


I have created a custom output format that extends html_document(). I
noticed that the argument keep_md is not properly inherited.

My first thought was that both the arguments keep_md and df_print
might have issues since they are arguments for both output_format()
and html_document(), but somehow df_print is properly inherited.

intersect(names(formals(rmarkdown::output_format)), names(formals(rmarkdown::html_document)))

## [1] "keep_md"  "df_print"

Here is a minimal example to demonstrate the issue. The function below
is a trivial output format that wraps html_document(), but doesn’t
change anything.

A trivial wrapper for html_document()

html_wrap <- function(...) { rmarkdown::output_format(knitr = rmarkdown::knitr_options(), pandoc = rmarkdown::pandoc_options(to = "html"), base_format = rmarkdown::html_document(...)) }

If a user runs render() on an R Markdown file with the following YAML
header:

---
output: html_wrap
---

then this would result in the following call to
create_output_format():

o1 <- rmarkdown:::create_output_format(name = "html_wrap", options = list())

This inherits the default values from html_document() as expected:

environment(environment(o1[["pre_knit"]])[["overlay"]])[["toc"]]

environment(environment(o1[["pre_knit"]])[["overlay"]])[["keep_md"]]

environment(environment(o1[["pre_knit"]])[["overlay"]])[["df_print"]]

However, if a user runs render() on an R Markdown file with the
following YAML header:

---
output:
  html_wrap:
    toc: true
    keep_md: TRUE
    df_print: "kable"
---

then this would result in the following call to create_output_format() (line 378):

o2 <- rmarkdown:::create_output_format(name = "html_wrap", options = list(toc = TRUE, keep_md = TRUE, df_print = "kable"))

toc is inherited as expected:

environment(environment(o2[["pre_knit"]])[["overlay"]])[["toc"]]

df_print is inherited not only in the environment of the pre_knit()
function, but the value of the output format is also inherited:

environment(environment(o2[["pre_knit"]])[["overlay"]])[["df_print"]]

Unfortunately, keep_md is only updated in the environment of the
pre_knit() function, where it has no effect.

environment(environment(o2[["pre_knit"]])[["overlay"]])[["keep_md"]]

When render() adds rmarkdown.keep_md to knitr::opts_knit, it uses
output_format$keep_md (line 500).
When render() decides to keep the md file, it again uses
output_format$keep_md (line 869).

Potentially related Issues include #842 and #928.

Note that bookdown::html_document2() does not have this issue.

rmarkdown:::create_output_format(name = "bookdown::html_document2", options = list(keep_md = TRUE))$keep_md

But it is unclear to me what part of its code would change the
inheritance of keep_md.

## function (..., number_sections = TRUE, pandoc_args = NULL, base_format = rmarkdown::html_document) 
## {
##     base_format = get_base_format(base_format)
##     config = base_format(..., number_sections = number_sections, 
##         pandoc_args = pandoc_args2(pandoc_args))
##     post = config$post_processor
##     config$post_processor = function(metadata, input, output, 
##         clean, verbose) {
##         if (is.function(post)) 
##             output = post(metadata, input, output, clean, verbose)
##         x = read_utf8(output)
##         x = restore_appendix_html(x, remove = FALSE)
##         x = restore_part_html(x, remove = FALSE)
##         x = resolve_refs_html(x, global = !number_sections)
##         x = clean_pandoc2_highlight_tags(x)
##         write_utf8(x, output)
##         output
##     }
##     config$bookdown_output_format = "html"
##     config = set_opts_knit(config)
##     config
## }
## <bytecode: 0x558e41c8af40>
## <environment: namespace:bookdown>

It appears to be directly editing the base output format instead of
inheriting from it using output_format(base_format = ), which is what
the documentation recommends.

What is the recommended method for passing all arguments provided to a
custom output format to the base output format that it extends?

I realize that I could hard-code a work-around for the custom output
format to handle keep_md, but this is fragile. If a future release of
rmarkdown added a new argument to output_format()/html_document(), I
would have to update my code and also put a restriction on the minimum
version of rmarkdown that is compatible.

html_wrap2 <- function(...) {

opts <- list(...)

if (!is.null(opts$keep_md)) keep_md <- opts$keep_md else keep_md <- FALSE

rmarkdown::output_format(knitr = rmarkdown::knitr_options(), pandoc = rmarkdown::pandoc_options(to = "html"), keep_md = keep_md, base_format = rmarkdown::html_document(...)) } rmarkdown:::create_output_format(name = "html_wrap2", options = list(keep_md = TRUE))$keep_md