From c1feb1fe2af355b130a77155858592b6d4d223c4 Mon Sep 17 00:00:00 2001 From: JJ Allaire Date: Wed, 7 Oct 2020 12:33:04 -0400 Subject: [PATCH 1/7] provide files_dir attribute --- NEWS.md | 2 ++ R/render.R | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 501df398a2..3892d02f16 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,6 +5,8 @@ rmarkdown 2.5 - `html_document` gains the `anchor_sections` argument, which is `TRUE` by default, so that readers can get links to section headers easily---when you mouse over a section hader, you will see a hash symbol `#` at the end of the header, which contains the anchor link to this header. You can click on this link and get the URL in the addres bar of your web browser, or right-click on it and copy the URL from the context menu. The hash symbol is defined by the CSS rule `a.anchor-section::before {content: '#';}`. You can customize it by overriding this rule (e.g., via the `css` argument of `html_document`) and use any other symbols or icons, e.g., `content: "\02AD8;"` (thanks, @atusy, #1884). +- Provide `files_dir` as attribute on return from `render()` when `run_pandoc = FALSE`. + rmarkdown 2.4 ================================================================================ diff --git a/R/render.R b/R/render.R index e6be4cb94c..c00dcd1495 100644 --- a/R/render.R +++ b/R/render.R @@ -1011,7 +1011,10 @@ render <- function(input, intermediates <- setdiff(intermediates, c(input, intermediates_fig)) # did not run pandoc; returns the markdown output with attributes of the # knitr meta data and intermediate files - structure(input, knit_meta = knit_meta, intermediates = intermediates) + structure(input, + knit_meta = knit_meta, + files_dir = files_dir, + intermediates = intermediates) } } From d58d57ceec8f4e2f833325de626973fb7b07eda2 Mon Sep 17 00:00:00 2001 From: Yihui Xie Date: Wed, 7 Oct 2020 21:39:15 -0500 Subject: [PATCH 2/7] normalize the path and recheck if it exists (this may fix a weird problem in blogdown on Windows when users click the Knit button) --- DESCRIPTION | 2 +- R/render_site.R | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index f72d45be8c..167ea209c3 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: rmarkdown Type: Package Title: Dynamic Documents for R -Version: 2.4.1 +Version: 2.4.2 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/R/render_site.R b/R/render_site.R index 672cd1a8e0..9a14a49512 100644 --- a/R/render_site.R +++ b/R/render_site.R @@ -625,8 +625,10 @@ input_as_dir <- function(input) { # ensure the input dir exists if (!file.exists(input)) { - stop("The specified directory '", normalize_path(input, mustWork = FALSE), - "' does not exist.", call. = FALSE) + input <- normalize_path(input, mustWork = FALSE) + if (!file.exists(input)) stop( + "The specified directory '", input, "' does not exist.", call. = FALSE + ) } # convert from file to directory if necessary From dc363c95b6fb01ce79dc7d76d0fc8434a7052582 Mon Sep 17 00:00:00 2001 From: Yihui Xie Date: Fri, 9 Oct 2020 15:35:36 -0500 Subject: [PATCH 3/7] use sans_ext() and file_ext() in xfun instead of tools, because we should allow trailing ~ or # in file extensions: https://github.com/yihui/xfun/commit/1f5994223c3079283eac6463672d2335706dc468 --- R/draft.R | 4 ++-- R/html_resource_copy.R | 2 +- R/html_resources.R | 10 +++++----- R/ioslides_presentation.R | 2 +- R/output_format.R | 2 +- R/render.R | 10 +++++----- R/shiny.R | 4 ++-- R/shiny_prerendered.R | 2 +- R/util.R | 16 ++++++++-------- 9 files changed, 26 insertions(+), 26 deletions(-) diff --git a/R/draft.R b/R/draft.R index 9dfbad804a..c18dbc19e7 100644 --- a/R/draft.R +++ b/R/draft.R @@ -92,7 +92,7 @@ draft <- function(file, if (create_dir) { # remove .Rmd extension if necessary - file <- tools::file_path_sans_ext(file) + file <- xfun::sans_ext(file) # create dir (new dir only) if (dir_exists(file)) @@ -104,7 +104,7 @@ draft <- function(file, } # Ensure we have an Rmd extension - if (!identical(tolower(tools::file_ext(file)), "rmd")) + if (!identical(tolower(xfun::file_ext(file)), "rmd")) file <- paste(file, ".Rmd", sep = "") # Ensure the file doesn't already exist diff --git a/R/html_resource_copy.R b/R/html_resource_copy.R index 87576fc6c7..f81b04b9c8 100644 --- a/R/html_resource_copy.R +++ b/R/html_resource_copy.R @@ -13,7 +13,7 @@ copy_html_resources <- function(html_str, lib_dir, output_dir) { # if the resource is a CSS file, perform a similar rewriting of its # content in the library directory res_path <- file.path(output_dir, res_src) - if (identical(tolower(tools::file_ext(res_path)), "css") && + if (identical(tolower(xfun::file_ext(res_path)), "css") && file.exists(res_path)) { css_content <- copy_resources( file_string(res_path), lib_dir, lib_dir, call_css_resource_attrs diff --git a/R/html_resources.R b/R/html_resources.R index f3e8db1a85..22e854a71e 100644 --- a/R/html_resources.R +++ b/R/html_resources.R @@ -53,7 +53,7 @@ find_external_resources <- function(input_file, encoding = 'UTF-8') { # ensure we're working with valid input - ext <- tolower(tools::file_ext(input_file)) + ext <- tolower(xfun::file_ext(input_file)) if (!(ext %in% c("md", "rmd", "html", "htm", "r", "css"))) { stop("Resource discovery is only supported for R Markdown files or HTML files.") } @@ -78,7 +78,7 @@ find_external_resources <- function(input_file, encoding = 'UTF-8') { file.exists(file.path(input_dir, path)))) return(FALSE) - ext <- tolower(tools::file_ext(file.path(input_dir, path))) + ext <- tolower(xfun::file_ext(file.path(input_dir, path))) if (identical(ext, "r")) { # if this is a .R script, look for resources it contains, too @@ -299,7 +299,7 @@ discover_rmd_resources <- function(rmd_file, discover_single_resource) { } # check for knitr child documents in R Markdown documents - if (tolower(tools::file_ext(rmd_file)) == "rmd") { + if (tolower(xfun::file_ext(rmd_file)) == "rmd") { chunk_lines <- gregexpr(knitr::all_patterns$md$chunk.begin, rmd_content, perl = TRUE) for (idx in seq_along(chunk_lines)) { chunk_line <- chunk_lines[idx][[1]] @@ -351,7 +351,7 @@ discover_rmd_resources <- function(rmd_file, discover_single_resource) { discover_html_resources(html_file, discover_single_resource) # if this is an R Markdown file, purl the file to extract just the R code - if (tolower(tools::file_ext(rmd_file)) == "rmd") { + if (tolower(xfun::file_ext(rmd_file)) == "rmd") { r_file <- tempfile(fileext = ".R") # suppress possible try() errors https://github.com/rstudio/rmarkdown/issues/1247 try_file <- tempfile() @@ -443,7 +443,7 @@ discover_css_resources <- function(css_file, discover_single_resource) { # given a filename, return true if the file appears to be a web file is_web_file <- function(filename) { - tolower(tools::file_ext(filename)) %in% c( + tolower(xfun::file_ext(filename)) %in% c( "css", "gif", "htm", "html", "jpeg", "jpg", "js", "mp3", "mp4", "png", "wav" ) } diff --git a/R/ioslides_presentation.R b/R/ioslides_presentation.R index 2d5f2ea5b2..af8bb8264d 100644 --- a/R/ioslides_presentation.R +++ b/R/ioslides_presentation.R @@ -318,7 +318,7 @@ ioslides_presentation <- function(number_sections = FALSE, logo_path <- logo if (!self_contained) { # use same extension as specified logo (default is png if unspecified) - logo_ext <- tools::file_ext(logo) + logo_ext <- xfun::file_ext(logo) if (nchar(logo_ext) < 1) logo_ext <- "png" logo_path <- file.path(files_dir, paste("logo", logo_ext, sep = ".")) diff --git a/R/output_format.R b/R/output_format.R index 0262c69959..9169cf4ec2 100644 --- a/R/output_format.R +++ b/R/output_format.R @@ -612,7 +612,7 @@ enumerate_output_formats <- function(input, envir, encoding, output_yaml = NULL) input_lines <- read_utf8(input) # if this is an R file then spin it - if (identical(tolower(tools::file_ext(input)), "r")) + if (identical(tolower(xfun::file_ext(input)), "r")) input_lines <- knitr::spin(text = input_lines, knit = FALSE) # parse _site.yml output format if we have it diff --git a/R/render.R b/R/render.R index c00dcd1495..f2a1cc584e 100644 --- a/R/render.R +++ b/R/render.R @@ -342,7 +342,7 @@ render <- function(input, } # check whether this document requires a knit - requires_knit <- tolower(tools::file_ext(input)) %in% c("r", "rmd", "rmarkdown") + requires_knit <- tolower(xfun::file_ext(input)) %in% c("r", "rmd", "rmarkdown") # remember the name of the original input document (we overwrite 'input' once # we've knitted) @@ -395,10 +395,10 @@ render <- function(input, intermediates <- c(intermediates, utf8_input) # track whether this was straight markdown input (to prevent keep_md later) - md_input <- identical(tolower(tools::file_ext(input)), "md") + md_input <- identical(tolower(xfun::file_ext(input)), "md") # if this is an R script then spin it first - if (identical(tolower(tools::file_ext(input)), "r")) { + if (identical(tolower(xfun::file_ext(input)), "r")) { # make a copy of the file to spin spin_input <- intermediates_loc(file_with_meta_ext(input, "spin", "R")) file.copy(input, spin_input, overwrite = TRUE) @@ -768,7 +768,7 @@ render <- function(input, # if this isn't html and there are html dependencies then flag an error if (!(is_pandoc_to_html(output_format$pandoc) || - identical(tolower(tools::file_ext(output_file)), "html"))) { + identical(tolower(xfun::file_ext(output_file)), "html"))) { if (has_html_dependencies(knit_meta)) { if (!isTRUE(front_matter$always_allow_html)) { stop("Functions that produce HTML output found in document targeting ", @@ -900,7 +900,7 @@ render <- function(input, # render to temporary file (preserve extension) # this also ensures we don't pass a file path with invalid # characters to our pandoc invocation - file_ext <- tools::file_ext(output) + file_ext <- xfun::file_ext(output) ext <- if (nzchar(file_ext)) paste(".", file_ext, sep = "") else diff --git a/R/shiny.R b/R/shiny.R index b1992ca645..bf67e1ee8b 100644 --- a/R/shiny.R +++ b/R/shiny.R @@ -312,7 +312,7 @@ rmarkdown_shiny_ui <- function(dir, file) { } # request must be for an R Markdown or HTML document - ext <- tolower(tools::file_ext(req_path)) + ext <- tolower(xfun::file_ext(req_path)) if (!(ext %in% c("rmd", "htm", "html"))) return(NULL) # document must exist @@ -378,7 +378,7 @@ rmd_cached_output <- function(input) { resource_folder <- "" # if the file is raw HTML, return it directly - if (tolower(tools::file_ext(input)) %in% c("htm", "html")) { + if (tolower(xfun::file_ext(input)) %in% c("htm", "html")) { return(list( cacheable = TRUE, cached = TRUE, diff --git a/R/shiny_prerendered.R b/R/shiny_prerendered.R index 11b2fd1e1e..ec037833fb 100644 --- a/R/shiny_prerendered.R +++ b/R/shiny_prerendered.R @@ -612,7 +612,7 @@ shiny_prerendered_append_context <- function(con, name, code) { # Prerendred data_dir for a given Rmd input file shiny_prerendered_data_dir <- function(input, create = FALSE) { - data_dir <- paste0(tools::file_path_sans_ext(input), "_data") + data_dir <- paste0(xfun::sans_ext(input), "_data") if (create && !dir_exists(data_dir)) dir.create(data_dir) data_dir diff --git a/R/util.R b/R/util.R index adec7ac7fd..965991b5f3 100644 --- a/R/util.R +++ b/R/util.R @@ -20,7 +20,7 @@ is_osx <- function() { pandoc_output_file <- function(input, pandoc_options) { to <- strsplit(pandoc_options$to, "[+-]")[[1]][[1]] ext <- pandoc_output_ext(pandoc_options$ext, to, input) - output <- paste0(tools::file_path_sans_ext(input), ext) + output <- paste0(xfun::sans_ext(input), ext) basename(output) } @@ -29,7 +29,7 @@ pandoc_output_ext <- function(ext, to, input) { if (to %in% c("latex", "beamer")) return(".pdf") if (to %in% c("html", "html4", "html5", "s5", "slidy", "slideous", "dzslides", "revealjs")) return(".html") - if (to == "markdown" && tolower(tools::file_ext(input)) != "md") return(".md") + if (to == "markdown" && tolower(xfun::file_ext(input)) != "md") return(".md") paste0(".", to) } @@ -148,25 +148,25 @@ dir_exists <- function(x) { } file_with_ext <- function(file, ext) { - paste(tools::file_path_sans_ext(file), ".", ext, sep = "") + paste(xfun::sans_ext(file), ".", ext, sep = "") } -file_with_meta_ext <- function(file, meta_ext, ext = tools::file_ext(file)) { - paste(tools::file_path_sans_ext(file), +file_with_meta_ext <- function(file, meta_ext, ext = xfun::file_ext(file)) { + paste(xfun::sans_ext(file), ".", meta_ext, ".", ext, sep = "") } knitr_files_dir <- function(file) { - paste(tools::file_path_sans_ext(file), "_files", sep = "") + paste(xfun::sans_ext(file), "_files", sep = "") } knitr_root_cache_dir <- function(file) { - paste(tools::file_path_sans_ext(file), "_cache", sep = "") + paste(xfun::sans_ext(file), "_cache", sep = "") } knitr_cache_dir <- function(file, pandoc_to) { - paste(tools::file_path_sans_ext(file), "_cache/", pandoc_to, "/", sep = "") + paste(xfun::sans_ext(file), "_cache/", pandoc_to, "/", sep = "") } get_knitr_hook_list <- function(hook_names = NULL) { From 5d87601f45d057cde2ce3911456d13d35c648969 Mon Sep 17 00:00:00 2001 From: Yihui Xie Date: Fri, 9 Oct 2020 15:43:45 -0500 Subject: [PATCH 4/7] cosmetic --- R/render.R | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/R/render.R b/R/render.R index f2a1cc584e..d406460e7d 100644 --- a/R/render.R +++ b/R/render.R @@ -900,15 +900,12 @@ render <- function(input, # render to temporary file (preserve extension) # this also ensures we don't pass a file path with invalid # characters to our pandoc invocation - file_ext <- xfun::file_ext(output) - ext <- if (nzchar(file_ext)) - paste(".", file_ext, sep = "") - else - "" + ext <- xfun::file_ext(output) + if (ext != '') ext <- paste0('.', ext) # render to a path in the current working directory # (avoid passing invalid characters to shell) - pandoc_output_tmp <- basename(tempfile("pandoc", tmpdir = getwd(), fileext = ext)) + pandoc_output_tmp <- basename(tempfile("pandoc", getwd(), ext)) # clean up temporary file on exit on.exit(unlink(pandoc_output_tmp), add = TRUE) From cd0ca7fc4a0d2179c05dfb0ea0aa46978662b863 Mon Sep 17 00:00:00 2001 From: Yihui Xie Date: Sun, 11 Oct 2020 20:44:05 -0500 Subject: [PATCH 5/7] avoid partial matching of the argument 'stylesheet' --- R/html_dependencies.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/html_dependencies.R b/R/html_dependencies.R index e8dcdf78da..bd08bfc834 100644 --- a/R/html_dependencies.R +++ b/R/html_dependencies.R @@ -131,7 +131,7 @@ html_dependency_anchor_sections <- function() { version = "1.0", src = pkg_file("rmd/h/anchor-sections"), script = "anchor-sections.js", - style = "anchor-sections.css") + stylesheet = "anchor-sections.css") } # analyze navbar html source for icon dependencies From 783771843ddb1cfe944ecb8cf04036e855b7cbdc Mon Sep 17 00:00:00 2001 From: Yihui Xie Date: Sun, 11 Oct 2020 21:06:27 -0500 Subject: [PATCH 6/7] typos --- R/html_dependencies.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/html_dependencies.R b/R/html_dependencies.R index bd08bfc834..4addb61f88 100644 --- a/R/html_dependencies.R +++ b/R/html_dependencies.R @@ -154,8 +154,8 @@ navbar_icon_dependencies <- function(navbar) { html_dependencies_fonts("fa fa" %in% libs, "ion ion" %in% libs) } -# utilty function to return a list of font dependencies based -# whether we are including font_awesome and/or iconicons +# utility function to return a list of font dependencies based +# whether we are including font_awesome and/or ionicons html_dependencies_fonts <- function(font_awesome, ionicons) { deps <- list() if (font_awesome) From e1a3fb67b9d55e7dd8cc6259583301a30dff49a6 Mon Sep 17 00:00:00 2001 From: Yihui Xie Date: Mon, 12 Oct 2020 09:32:58 -0500 Subject: [PATCH 7/7] pkg_file_lua() should have thrown an error if the expected Lua file does not exist, but it didn't because we only checked the existence of the rmarkdown/lua folder, then we used file.path() to construct the paths, which doesn't check for the existence of files --- DESCRIPTION | 2 +- NEWS.md | 2 ++ R/util.R | 11 ++++++++--- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 167ea209c3..c238650e00 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: rmarkdown Type: Package Title: Dynamic Documents for R -Version: 2.4.2 +Version: 2.4.3 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 3892d02f16..afdd13f102 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,6 +5,8 @@ rmarkdown 2.5 - `html_document` gains the `anchor_sections` argument, which is `TRUE` by default, so that readers can get links to section headers easily---when you mouse over a section hader, you will see a hash symbol `#` at the end of the header, which contains the anchor link to this header. You can click on this link and get the URL in the addres bar of your web browser, or right-click on it and copy the URL from the context menu. The hash symbol is defined by the CSS rule `a.anchor-section::before {content: '#';}`. You can customize it by overriding this rule (e.g., via the `css` argument of `html_document`) and use any other symbols or icons, e.g., `content: "\02AD8;"` (thanks, @atusy, #1884). +- `pkg_file_lua()` should have thrown an error if the expected Lua file does not exist. + - Provide `files_dir` as attribute on return from `render()` when `run_pandoc = FALSE`. diff --git a/R/util.R b/R/util.R index 965991b5f3..5fbfbd9c31 100644 --- a/R/util.R +++ b/R/util.R @@ -63,9 +63,14 @@ pkg_file_arg <- function(..., package = "rmarkdown") { #' # get a specific filter #' pkg_file_lua(c("pagebreak.lua", "latex_div.lua")) pkg_file_lua <- function(filters = NULL, package = "rmarkdown") { - lua_folder <- pkg_file("rmarkdown", "lua", package = package, mustWork = TRUE) - if (is.null(filters)) filters <- list.files(lua_folder, "[.]lua$") - pandoc_path_arg(file.path(lua_folder, filters)) + files <- pkg_file( + "rmarkdown", "lua", if (is.null(filters)) '.' else filters, + package = package, mustWork = TRUE + ) + if (is.null(filters)) { + files <- list.files(dirname(files), "[.]lua$", full.names = TRUE) + } + pandoc_path_arg(files) } #' @rdname rmarkdown_format