diff --git a/DESCRIPTION b/DESCRIPTION index 6bc834f56b..b64a932fa6 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: rmarkdown Type: Package Title: Dynamic Documents for R -Version: 2.8.4 +Version: 2.8.5 Authors@R: c( person("JJ", "Allaire", role = "aut", email = "jj@rstudio.com"), person("Yihui", "Xie", role = c("aut", "cre"), email = "xie@yihui.name", comment = c(ORCID = "0000-0003-0645-5666")), diff --git a/NEWS.md b/NEWS.md index be2b49d110..c32add69b6 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,7 +1,9 @@ rmarkdown 2.9 ================================================================================ -- Fixed an issue with `copy_ressource = TRUE` in `html_document_base` where very long HTML documents were truncated during post processing (thanks, @oliviermeslin, #2145). +- Fix an error thrown with output format using a `file_scope` function (like in **bookdown**) (thanks, @rfaelens, #2149). + +- Fix an issue with `copy_ressource = TRUE` in `html_document_base` where very long HTML documents were truncated during post processing (thanks, @oliviermeslin, #2145). - When rendering a `runtime: shiny` document, an extra temp folder will be used in the output path. With the extra temp random folder in the path, predictable output file names may be used. (#2137) diff --git a/R/render.R b/R/render.R index 3e9331473f..4ea03c0451 100644 --- a/R/render.R +++ b/R/render.R @@ -891,22 +891,15 @@ render <- function(input, # in case the output format turns on the --file-scope flag, run its # file_scope function to split the input into multiple files input_files <- input - if (!is.null(output_format$file_scope) && - length(inputs <- output_format$file_scope(input)) > 1) { - - # add the --file-scope option - pandoc_args <- c(pandoc_args, "--file-scope") - - # write the split content into *.split.md files - input_files <- unlist(lapply(inputs, function(input) { - file <- file_with_meta_ext(input$name, "split", "md") - file <- file.path(dirname(input), file) - write_utf8(input$content, file) - file - })) - - # cleanup the split files after render - on.exit(unlink(input_files), add = TRUE) + if (is.function(output_format$file_scope)) { + input_files <- file_scope_split(input, output_format$file_scope) + # ignore if input_files has not really been splitted + if (length(input_files) > 1) { + # add the --file-scope option + pandoc_args <- c(pandoc_args, "--file-scope") + # cleanup the split files after render + on.exit(unlink(input_files), add = TRUE) + } } # if we don't detect any invalid shell characters in the @@ -1192,3 +1185,21 @@ resolve_df_print <- function(df_print) { #' @keywords NULL #' @export output_metadata = knitr:::new_defaults() + +file_scope_split <- function(input, fun) { + inputs <- fun(input) + + # file_scope_fun should split the input file in several + # do nothing if not and return input file unsplited + if (length(inputs) <= 1) return(input) + + # write the split content into *.split.md files + input_files <- lapply(inputs, function(f) { + file <- file_with_meta_ext(f$name, "split", "md") + file <- file.path(dirname(input), file) + write_utf8(f$content, file) + file + }) + + unlist(input_files) +} diff --git a/tests/testthat/_snaps/render/A.split.md b/tests/testthat/_snaps/render/A.split.md new file mode 100644 index 0000000000..6288805fed --- /dev/null +++ b/tests/testthat/_snaps/render/A.split.md @@ -0,0 +1,2 @@ +# H1 +content1 diff --git a/tests/testthat/_snaps/render/B.split.md b/tests/testthat/_snaps/render/B.split.md new file mode 100644 index 0000000000..b00315d928 --- /dev/null +++ b/tests/testthat/_snaps/render/B.split.md @@ -0,0 +1,2 @@ +# H2 +content2 diff --git a/tests/testthat/test-render.R b/tests/testthat/test-render.R index eae8e797de..b2ad4dddb4 100644 --- a/tests/testthat/test-render.R +++ b/tests/testthat/test-render.R @@ -1,3 +1,6 @@ +# TODO: to remove when switching the package to edition 3 +local_edition(3) + test_that("Metadata is available before pre_knit", { message_pre_knit = 'pre_knit handles metadata' fmt <- md_document() @@ -11,3 +14,20 @@ test_that("Metadata is available before pre_knit", { writeLines('---\nfoo: bar\n---', input_file) expect_message(render(input_file, fmt, quiet = TRUE), message_pre_knit) }) + +test_that("file_scope split correctly input file", { + rmd <- local_rmd_file(c("# H1", "content1", "# H2", "content2")) + file_scope_fun <- function(file) { + x <- xfun::read_utf8(file) + list( + list(name = "A", content = x[1:2]), + list(name = "B", content = x[3:4]) + ) + } + splitted <- file_scope_split(rmd, file_scope_fun) + expect_true(all(file.exists(splitted))) + on.exit(unlink(splitted), add = TRUE, after = FALSE) + expect_match(splitted, "[.]split[.]md$") + expect_snapshot_file(splitted[1]) + expect_snapshot_file(splitted[2]) +})