diff --git a/.Rbuildignore b/.Rbuildignore index f852daacf3..b00c916cf4 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -7,6 +7,8 @@ ^tests/testthat/site/_site/ ^tests/testthat/site/lib/ ^tests/testthat/site/.*_files/ +^tests/testthat/html-uptree-lib_dir/.*\.html$ +^tests/testthat/html-uptree-lib_dir/.*\.gitkeep$ ^tests/manual/ ^\.github$ ^pkgdown$ diff --git a/DESCRIPTION b/DESCRIPTION index 7acf9a1c48..15645e4776 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -47,7 +47,8 @@ Authors@R: c( person(, "Drifty", role = "cph", comment = "Ionicons"), person("Aidan", "Lister", role = c("ctb", "cph"), comment = "jQuery StickyTabs"), person("Benct Philip", "Jonsson", role = c("ctb", "cph"), comment = "pagebreak Lua filter"), - person("Albert", "Krewinkel", role = c("ctb", "cph"), comment = "pagebreak Lua filter") + person("Albert", "Krewinkel", role = c("ctb", "cph"), comment = "pagebreak Lua filter"), + person("Jonathan", "Gilligan", role = "ctb", email = "jonathan.gilligan@gmail.com", comment = c(ORCID = "0000-0003-1375-6686")) ) Description: Convert R Markdown documents into a variety of formats. License: GPL-3 diff --git a/NEWS.md b/NEWS.md index c96252467a..764893882c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,6 +5,14 @@ rmarkdown 2.30 rmarkdown 2.29 ================================================================================ +- `html_document` output allows `lib_dir` to point to a parent of the output + directory if the `allow_uptree_lib_dir` parameter is set to `TRUE`. This used + to throw an error, "The path does not appear to be a descendant of + ". This makes it possible to have a directory structure for HTML output + where there is a shared master library with css, javascript, etc. and separate + child directories with RMarkdown files. #146 and #1859. + (thanks, @jonathan-g, #2199) + - `find_external_resources()` now correctly detects knitr child document provided with option like `child = c("child.Rmd")` (thanks, @rempsyc, #2574). - `knit_params_ask()` uses a `select` input for parameters which allow multiple selected values. Previously, a `radio` input was incorrectly used when the parameter had a small number of choices. diff --git a/R/html_dependencies.R b/R/html_dependencies.R index 63a9fcc945..426c11a00b 100644 --- a/R/html_dependencies.R +++ b/R/html_dependencies.R @@ -311,16 +311,114 @@ html_reference_path <- function(path, lib_dir, output_dir) { relative_to(output_dir, path) } +copy_if_changed <- function(from, to, recursive = FALSE, + overwrite = FALSE, copy.mode = FALSE) { + isdir = dir.exists(from) + if (isdir) { + if (! dir.exists(to)) { + dir.create(to, recursive = TRUE) + } + if (recursive) { + from2 = list.files(from, recursive = FALSE, include.dirs = TRUE, + all.files = TRUE, no.. = TRUE) + mapply(copy_if_changed, from = file.path(from, from2), + to = file.path(to, from2), + MoreArgs = list(recursive = recursive, overwrite = overwrite, + copy.mode = copy.mode)) + } + } else { + digests <- tools::md5sum(c(from, to)) + if (!isTRUE(digests[1] == digests[2])) { + file.copy(from, to, overwrite = TRUE, copy.mode = FALSE) + } + } +} + +# This is an almost exact copy of htmltools::copyDependencyToDir, except that +# it only copies files if necessary. +# +# Sometimes, a process (e.g., web server) will be accessing an HTML dependency +# file when RMarkdown tries to overwrite it, and R throws an error reporting +# insufficient privilege to delete or overwrite the file or directory. +# +# This function reduces that by only copying if the file has changed. +# +copy_html_dependency <- function(dependency, outputDir, mustWork = TRUE) { + dir <- dependency$src$file + if (is.null(dir)) { + if (mustWork) { + stop("Dependency ", dependency$name, " ", + dependency$version, " is not disk-based") + } + else { + return(dependency) + } + } + if (!is.null(dependency$package)) + dir <- system.file(dir, package = dependency$package) + if (length(outputDir) != 1 || outputDir %in% c("", + "/")) + stop("outputDir must be of length 1 and cannot be \"\" or \"/\"") + target_dir <- if (getOption("htmltools.dir.version", + TRUE)) { + paste(dependency$name, dependency$version, sep = "-") + } + else dependency$name + target_dir <- file.path(outputDir, target_dir) + if (same_path(dir, target_dir)) + return(dependency) + if (!dir_exists(outputDir)) + dir.create(outputDir) + + # Unlike htmltools::copyDependencyToDir(), + # we do not delete the target directory, but we + # do create it if necessary. + if (! dir_exists(target_dir)) dir.create(target_dir) + files <- if (dependency$all_files) + list.files(dir) + else { + unlist(dependency[c("script", "stylesheet", + "attachment")]) + } + srcfiles <- file.path(dir, files) + if (any(!file.exists(srcfiles))) { + stop(sprintf("Can't copy dependency files that don't exist: '%s'", + paste(srcfiles, collapse = "', '"))) + } + destfiles <- file.path(target_dir, files) + isdir <- file.info(srcfiles)$isdir + destfiles <- ifelse(isdir, dirname(destfiles), destfiles) + mapply(copy_if_changed, from = srcfiles, to = destfiles, + recursive = isdir, + MoreArgs = list(overwrite = TRUE, copy.mode = FALSE)) + dependency$src$file <- normalizePath(target_dir, "/", TRUE) + dependency +} + # return the html dependencies as an HTML string suitable for inclusion # in the head of a document -html_dependencies_as_string <- function(dependencies, lib_dir, output_dir) { +html_dependencies_as_string <- function(dependencies, lib_dir, output_dir, + allow_uptree_lib_dir = FALSE) { if (!is.null(lib_dir)) { - # using mustWork=FALSE insures non-disk based dependencies are - # return untouched, keeping the order of all deps. - dependencies <- lapply(dependencies, copyDependencyToDir, - outputDir = lib_dir, mustWork = FALSE) - dependencies <- lapply(dependencies, makeDependencyRelative, - basepath = output_dir, mustWork = FALSE) + if (allow_uptree_lib_dir && grepl("^\\.\\.", lib_dir)) { + abs_lib_dir <- normalizePath(lib_dir, winslash = "/") + dependencies <- lapply(dependencies, copy_html_dependency, abs_lib_dir, + mustWork = FALSE) + dependencies <- lapply(dependencies, makeDependencyRelative, abs_lib_dir, + mustWork = FALSE) + return(renderDependencies(dependencies, "file", encodeFunc = identity, + hrefFilter = function(path) { + file.path(lib_dir, path) + })) + } else { + # using mustWork=FALSE insures non-disk based dependencies are + # return untouched, keeping the order of all deps. + dependencies <- lapply(dependencies, copyDependencyToDir, + outputDir = lib_dir, mustWork = FALSE) + dependencies <- lapply(dependencies, makeDependencyRelative, + basepath = output_dir, mustWork = FALSE) + } + } # Dependencies are iterated on as file based dependencies needs to be diff --git a/R/html_document.R b/R/html_document.R index 64ada6681c..50eb80fa63 100644 --- a/R/html_document.R +++ b/R/html_document.R @@ -141,6 +141,8 @@ #' default definition of R Markdown. See the \code{\link{rmarkdown_format}} for #' additional details. #' @param pandoc_args Additional command line options to pass to pandoc +#' @param allow_uptree_lib_dir Allow dependencies to be placed in a directory +#' above the current document's location in the directory tree. #' @param ... Additional function arguments to pass to the base R Markdown HTML #' output formatter \code{\link{html_document_base}} #' @return R Markdown output format to pass to \code{\link{render}} @@ -356,6 +358,52 @@ #' Due to the above restrictions, you might consider using the \code{includes} #' parameter as an alternative to providing a fully custom template. #' +#'@section Directory structure: +#' +#' By default \code{html_document} and related HTML document types put +#' dependency files into the main output directory or a subdirectory specified +#' by the \code{lib_dir} parameter: +#' If \code{lib_dir} is not a direct descendant of the main output directory, +#' \code{render()} will throw and error with the message +#' "The path <file> does not appear to be a descendant of <dir>". +#' +#' Sometimes it is useful to have a directory tree where the different +#' HTML documents are in their own subdirectories and the dependencies are in +#' a common directory at the root of the site. +#' +#' \itemize{ +#' \item +#' \code{main_dir/} +#' \itemize{ +#' \item +#' \code{lib/} +#' \itemize{ +#' \item dependencies go here +#' } +#' } +#' \item \code{index.Rmd} +#' \item +#' \code{node-01/} +#' \itemize{ +#' \item \code{index.Rmd} +#' } +#' \item +#' \code{node-02/} +#' \itemize{ +#' \item \code{index.Rmd} +#' } +#' } +#' +#' One way to achieve this is with the `render_site` command, but knitting +#' individual documents in subdirectories (such as with the RStudio "knit" +#' button) will result in errors. +#' +#' It is possible to achieve this directory structure by setting the +#' `allow_uptree_lib_dir` parameter to `yes` or `true` in the +#' `output/html_document` section of the YAML header +#' and set `lib_dir` to a relative path, such as `../lib` or `../site_lib` +#' in `node-01/index.Rmd` and `node-02/index.Rmd` in the example above. +#' #' @examples #' \dontrun{ #' library(rmarkdown) @@ -394,6 +442,7 @@ html_document <- function(toc = FALSE, lib_dir = NULL, md_extensions = NULL, pandoc_args = NULL, + allow_uptree_lib_dir = FALSE, ...) { # self_contained = TRUE already uses --standalone @@ -671,6 +720,7 @@ html_document <- function(toc = FALSE, pandoc_args = pandoc_args, extra_dependencies = extra_dependencies, css = css, + allow_uptree_lib_dir = allow_uptree_lib_dir, ...) ) } diff --git a/R/html_document_base.R b/R/html_document_base.R index 8992aad03a..d8e03c32a0 100644 --- a/R/html_document_base.R +++ b/R/html_document_base.R @@ -8,6 +8,8 @@ #' @param dependency_resolver A dependency resolver #' @param copy_resources Copy resources #' @param bootstrap_compatible Bootstrap compatible +#' @param allow_uptree_lib_dir Allow lib_dir not to be a descendent of the +#' output directory. #' @param ... Ignored #' #' @return HTML base output format. @@ -25,6 +27,7 @@ html_document_base <- function(theme = NULL, extra_dependencies = NULL, css = NULL, bootstrap_compatible = FALSE, + allow_uptree_lib_dir = FALSE, ...) { # default for dependency_resolver @@ -141,12 +144,21 @@ html_document_base <- function(theme = NULL, # If we can add bootstrap for Shiny, do it format_deps <- append(format_deps, bootstrap_dependencies("bootstrap")) } + + # Allow the user to override default dependencies by injecting alternate + # dependencies with the same name into extra_dependencies. + if (length(format_deps) > 0 && length(extra_dependencies) > 0) { + names(format_deps) <- lapply(format_deps, function(x) x$name) + names(extra_dependencies) <- lapply(extra_dependencies, function(x) x$name) + format_deps <- format_deps[setdiff(names(format_deps), + names(extra_dependencies))] + } format_deps <- append(format_deps, extra_dependencies) extras <- html_extras_for_document(knit_meta, runtime, dependency_resolver, format_deps) args <- c(args, pandoc_html_extras_args(extras, self_contained, lib_dir, - output_dir)) + output_dir, allow_uptree_lib_dir)) preserved_chunks <<- extract_preserve_chunks(input_file) diff --git a/R/html_extras.R b/R/html_extras.R index 02fdd43cae..84de6086e2 100644 --- a/R/html_extras.R +++ b/R/html_extras.R @@ -18,7 +18,7 @@ html_extras_for_document <- function(knit_meta, runtime, dependency_resolver, # convert html extras to the pandoc args required to include them pandoc_html_extras_args <- function(extras, self_contained, lib_dir, - output_dir) { + output_dir, allow_uptree_lib_dir) { args <- c() @@ -26,10 +26,12 @@ pandoc_html_extras_args <- function(extras, self_contained, lib_dir, dependencies <- extras$dependencies if (length(dependencies) > 0) { if (self_contained) - file <- as_tmpfile(html_dependencies_as_string(dependencies, NULL, NULL)) + file <- as_tmpfile(html_dependencies_as_string(dependencies, NULL, NULL, + allow_uptree_lib_dir = FALSE)) else file <- as_tmpfile(html_dependencies_as_string(dependencies, lib_dir, - output_dir)) + output_dir, + allow_uptree_lib_dir)) args <- c(args, pandoc_include_args(in_header = file)) } diff --git a/R/output_format.R b/R/output_format.R index a4afa6d7d7..ce82df9477 100644 --- a/R/output_format.R +++ b/R/output_format.R @@ -60,6 +60,8 @@ #' each file. The return is the new file scope. Also, the arguments should #' include \code{...} for the future extensions. #' @param base_format An optional format to extend. +#' @param allow_uptree_lib_dir Allow \code{lib_dir} output parameter not to +#' be a descendent of the output directory. #' @return An R Markdown output format definition that can be passed to #' \code{\link{render}}. #' @seealso \link{render}, \link{knitr_options}, \link{pandoc_options} @@ -81,7 +83,8 @@ output_format <- function(knitr, post_processor = NULL, on_exit = NULL, file_scope = NULL, - base_format = NULL) { + base_format = NULL, + allow_uptree_lib_dir = FALSE) { format <- list( knitr = knitr, @@ -95,7 +98,8 @@ output_format <- function(knitr, intermediates_generator = intermediates_generator, post_processor = post_processor, file_scope = file_scope, - on_exit = on_exit + on_exit = on_exit, + allow_uptree_lib_dir = allow_uptree_lib_dir ) class(format) <- "rmarkdown_output_format" @@ -191,6 +195,8 @@ merge_output_formats <- function(base, pandoc = merge_pandoc_options(base$pandoc, overlay$pandoc), keep_md = merge_scalar(base$keep_md, overlay$keep_md), + allow_uptree_lib_dir = + merge_scalar(base$allow_uptree_lib_dir, overlay$allow_uptree_lib_dir), clean_supporting = merge_scalar(base$clean_supporting, overlay$clean_supporting), df_print = @@ -902,7 +908,14 @@ knit_print.output_format_dependency <- function(x, ...) { merge_output_format_dependency <- function(fmt, dep) { dep$name <- NULL # remove to be consistent with arguments of output_format dep$base_format <- fmt - do.call(output_format, dep) + fmt2 <- do.call(output_format, dep) + cls <- class(fmt2) + # Make sure named elements are in the same order, to pass tests. + fmt2 <- fmt2[c(intersect(names(fmt), names(fmt2)), + setdiff(names(fmt), names(fmt2)), + setdiff(names(fmt2), names(fmt)))] + class(fmt2) <- cls + fmt2 } merge_output_format_dependencies <- function(fmt, deps) { diff --git a/man/html_document.Rd b/man/html_document.Rd index 9070b6b9fe..12971b02b4 100644 --- a/man/html_document.Rd +++ b/man/html_document.Rd @@ -33,6 +33,7 @@ html_document( lib_dir = NULL, md_extensions = NULL, pandoc_args = NULL, + allow_uptree_lib_dir = FALSE, ... ) } @@ -208,6 +209,9 @@ additional details.} \item{pandoc_args}{Additional command line options to pass to pandoc} +\item{allow_uptree_lib_dir}{Allow dependencies to be placed in a directory +above the current document's location in the directory tree.} + \item{...}{Additional function arguments to pass to the base R Markdown HTML output formatter \code{\link{html_document_base}}} } @@ -461,6 +465,54 @@ Due to the above restrictions, you might consider using the \code{includes} parameter as an alternative to providing a fully custom template. } +\section{Directory structure}{ + + +By default \code{html_document} and related HTML document types put +dependency files into the main output directory or a subdirectory specified +by the \code{lib_dir} parameter: +If \code{lib_dir} is not a direct descendant of the main output directory, +\code{render()} will throw and error with the message +"The path does not appear to be a descendant of ". + +Sometimes it is useful to have a directory tree where the different +HTML documents are in their own subdirectories and the dependencies are in +a common directory at the root of the site. + +\itemize{ +\item +\code{main_dir/} +\itemize{ +\item +\code{lib/} +\itemize{ +\item dependencies go here +} +} +\item \code{index.Rmd} +\item +\code{node-01/} +\itemize{ +\item \code{index.Rmd} +} +\item +\code{node-02/} +\itemize{ +\item \code{index.Rmd} +} +} + +One way to achieve this is with the \code{render_site} command, but knitting +individual documents in subdirectories (such as with the RStudio "knit" +button) will result in errors. + +It is possible to achieve this directory structure by setting the +\code{allow_uptree_lib_dir} parameter to \code{yes} or \code{true} in the +\code{output/html_document} section of the YAML header +and set \code{lib_dir} to a relative path, such as \code{../lib} or \code{../site_lib} +in \code{node-01/index.Rmd} and \code{node-02/index.Rmd} in the example above. +} + \examples{ \dontrun{ library(rmarkdown) diff --git a/man/html_document_base.Rd b/man/html_document_base.Rd index 3f872d09a6..a2be643274 100644 --- a/man/html_document_base.Rd +++ b/man/html_document_base.Rd @@ -17,6 +17,7 @@ html_document_base( extra_dependencies = NULL, css = NULL, bootstrap_compatible = FALSE, + allow_uptree_lib_dir = FALSE, ... ) } @@ -105,6 +106,9 @@ Sass variables, functions, mixins, etc.} \item{bootstrap_compatible}{Bootstrap compatible} +\item{allow_uptree_lib_dir}{Allow lib_dir not to be a descendent of the +output directory.} + \item{...}{Ignored} } \value{ diff --git a/man/output_format.Rd b/man/output_format.Rd index ace48bfd09..df94641a86 100644 --- a/man/output_format.Rd +++ b/man/output_format.Rd @@ -17,7 +17,8 @@ output_format( post_processor = NULL, on_exit = NULL, file_scope = NULL, - base_format = NULL + base_format = NULL, + allow_uptree_lib_dir = FALSE ) } \arguments{ @@ -91,6 +92,9 @@ each file. The return is the new file scope. Also, the arguments should include \code{...} for the future extensions.} \item{base_format}{An optional format to extend.} + +\item{allow_uptree_lib_dir}{Allow \code{lib_dir} output parameter not to +be a descendent of the output directory.} } \value{ An R Markdown output format definition that can be passed to diff --git a/man/rmarkdown-package.Rd b/man/rmarkdown-package.Rd index 8c66b09c9f..88597bd730 100644 --- a/man/rmarkdown-package.Rd +++ b/man/rmarkdown-package.Rd @@ -87,6 +87,7 @@ Other contributors: \item Aidan Lister (jQuery StickyTabs) [contributor, copyright holder] \item Benct Philip Jonsson (pagebreak Lua filter) [contributor, copyright holder] \item Albert Krewinkel (pagebreak Lua filter) [contributor, copyright holder] + \item Jonathan Gilligan \email{jonathan.gilligan@gmail.com} (\href{https://orcid.org/0000-0003-1375-6686}{ORCID}) [contributor] } } diff --git a/tests/testthat/html-uptree-lib_dir/index.Rmd b/tests/testthat/html-uptree-lib_dir/index.Rmd new file mode 100644 index 0000000000..5278edea50 --- /dev/null +++ b/tests/testthat/html-uptree-lib_dir/index.Rmd @@ -0,0 +1,30 @@ +--- +title: "R Markdown Webpage" +output: + html_document: + lib_dir: lib + css: "lib/styles.css" + self_contained: false +--- + +```{r setup, include=FALSE} +knitr::opts_chunk$set(echo = TRUE) +``` + +# Home Page + +* [Page 1](node-01/index.html) +* [Page 2](node-02/index.html) + +## Section 1 + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque sapien nisl, egestas ut erat eu, egestas porttitor tellus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed pellentesque volutpat justo, et cursus lorem pulvinar luctus. Curabitur porta, diam a pretium egestas, dui dolor tempus sem, non facilisis turpis tortor a lectus. Morbi nec enim aliquam, eleifend libero eget, efficitur quam. Fusce dapibus elit vitae tellus hendrerit tristique. Donec felis elit, gravida non orci consectetur, finibus sollicitudin justo. Curabitur imperdiet pellentesque elit ac ultricies. Vestibulum erat leo, tristique non felis a, fringilla pellentesque dolor. Vivamus sem justo, commodo sit amet ultrices in, lobortis sit amet lacus. Donec feugiat sem vel arcu feugiat, sed maximus elit aliquam. Pellentesque justo leo, pellentesque a mollis eget, suscipit ac turpis. Duis ornare dui quis nisi dictum, at consequat justo auctor. + +## Section 2 + +Nullam ullamcorper ac nunc sed tempus. Suspendisse sagittis tortor auctor magna aliquam, eu porta libero pretium. Vestibulum placerat feugiat mattis. Nulla ornare luctus quam vel iaculis. Nulla ornare justo venenatis viverra mollis. Aliquam pretium dui sed sem accumsan blandit. Integer aliquam posuere odio, ac interdum lorem egestas in. Vivamus sed est dolor. Nulla cursus blandit elit nec porta. Etiam dictum libero vel magna pulvinar convallis. Proin lacinia elementum ligula a malesuada. Ut rhoncus tortor vitae lorem ultrices luctus. Aenean sit amet libero non metus fringilla lacinia id quis massa. Nulla sollicitudin tortor non turpis suscipit, in imperdiet ex finibus. + +## Section 3 + +Sed leo tortor, sagittis sit amet lacus eu, tincidunt ornare lacus. Integer lorem lacus, facilisis nec turpis et, fermentum scelerisque felis. Pellentesque ultrices nibh lacus, ut tincidunt metus finibus quis. Nunc tincidunt eget urna a lacinia. Sed auctor lorem eu ultrices interdum. Aliquam vehicula ornare massa, ut placerat mi imperdiet et. Sed facilisis eleifend tortor, id semper nisl congue eu. Donec malesuada dolor eget ex rutrum, nec consequat erat ultrices. Maecenas iaculis leo id est lacinia laoreet. Donec tempor cursus orci. Suspendisse potenti. Etiam cursus iaculis tincidunt. + diff --git a/tests/testthat/html-uptree-lib_dir/lib/.gitkeep b/tests/testthat/html-uptree-lib_dir/lib/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/testthat/html-uptree-lib_dir/lib/styles.css b/tests/testthat/html-uptree-lib_dir/lib/styles.css new file mode 100644 index 0000000000..fbc765fccf --- /dev/null +++ b/tests/testthat/html-uptree-lib_dir/lib/styles.css @@ -0,0 +1,4 @@ + +p { + color: red; +} diff --git a/tests/testthat/html-uptree-lib_dir/node-01/index.Rmd b/tests/testthat/html-uptree-lib_dir/node-01/index.Rmd new file mode 100644 index 0000000000..dac7cfcc12 --- /dev/null +++ b/tests/testthat/html-uptree-lib_dir/node-01/index.Rmd @@ -0,0 +1,31 @@ +--- +title: "Page #1" +output: + html_document: + allow_uptree_lib_dir: true + lib_dir: "../lib" + css: "../lib/styles.css" + self_contained: false +--- + +```{r setup, include=FALSE} +knitr::opts_chunk$set(echo = TRUE) +``` + +# This is Page #1. + +* [Home](../index.html) +* [Page 2](../node-02/index.html) + +## Section 1 + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque sapien nisl, egestas ut erat eu, egestas porttitor tellus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed pellentesque volutpat justo, et cursus lorem pulvinar luctus. Curabitur porta, diam a pretium egestas, dui dolor tempus sem, non facilisis turpis tortor a lectus. Morbi nec enim aliquam, eleifend libero eget, efficitur quam. Fusce dapibus elit vitae tellus hendrerit tristique. Donec felis elit, gravida non orci consectetur, finibus sollicitudin justo. Curabitur imperdiet pellentesque elit ac ultricies. Vestibulum erat leo, tristique non felis a, fringilla pellentesque dolor. Vivamus sem justo, commodo sit amet ultrices in, lobortis sit amet lacus. Donec feugiat sem vel arcu feugiat, sed maximus elit aliquam. Pellentesque justo leo, pellentesque a mollis eget, suscipit ac turpis. Duis ornare dui quis nisi dictum, at consequat justo auctor. + +## Section 2 + +Nullam ullamcorper ac nunc sed tempus. Suspendisse sagittis tortor auctor magna aliquam, eu porta libero pretium. Vestibulum placerat feugiat mattis. Nulla ornare luctus quam vel iaculis. Nulla ornare justo venenatis viverra mollis. Aliquam pretium dui sed sem accumsan blandit. Integer aliquam posuere odio, ac interdum lorem egestas in. Vivamus sed est dolor. Nulla cursus blandit elit nec porta. Etiam dictum libero vel magna pulvinar convallis. Proin lacinia elementum ligula a malesuada. Ut rhoncus tortor vitae lorem ultrices luctus. Aenean sit amet libero non metus fringilla lacinia id quis massa. Nulla sollicitudin tortor non turpis suscipit, in imperdiet ex finibus. + +## Section 3 + +Sed leo tortor, sagittis sit amet lacus eu, tincidunt ornare lacus. Integer lorem lacus, facilisis nec turpis et, fermentum scelerisque felis. Pellentesque ultrices nibh lacus, ut tincidunt metus finibus quis. Nunc tincidunt eget urna a lacinia. Sed auctor lorem eu ultrices interdum. Aliquam vehicula ornare massa, ut placerat mi imperdiet et. Sed facilisis eleifend tortor, id semper nisl congue eu. Donec malesuada dolor eget ex rutrum, nec consequat erat ultrices. Maecenas iaculis leo id est lacinia laoreet. Donec tempor cursus orci. Suspendisse potenti. Etiam cursus iaculis tincidunt. + diff --git a/tests/testthat/html-uptree-lib_dir/node-02/index.Rmd b/tests/testthat/html-uptree-lib_dir/node-02/index.Rmd new file mode 100644 index 0000000000..6df47ca9f8 --- /dev/null +++ b/tests/testthat/html-uptree-lib_dir/node-02/index.Rmd @@ -0,0 +1,31 @@ +--- +title: "Page #2" +output: + html_document: + allow_uptree_lib_dir: yes + lib_dir: "../lib" + css: "../lib/styles.css" + self_contained: false +--- + +```{r setup, include=FALSE} +knitr::opts_chunk$set(echo = TRUE) +``` + +# This is Page #2. + +* [Home](../index.html) +* [Page 1](../node-01/index.html) + +## Section 1 + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque sapien nisl, egestas ut erat eu, egestas porttitor tellus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed pellentesque volutpat justo, et cursus lorem pulvinar luctus. Curabitur porta, diam a pretium egestas, dui dolor tempus sem, non facilisis turpis tortor a lectus. Morbi nec enim aliquam, eleifend libero eget, efficitur quam. Fusce dapibus elit vitae tellus hendrerit tristique. Donec felis elit, gravida non orci consectetur, finibus sollicitudin justo. Curabitur imperdiet pellentesque elit ac ultricies. Vestibulum erat leo, tristique non felis a, fringilla pellentesque dolor. Vivamus sem justo, commodo sit amet ultrices in, lobortis sit amet lacus. Donec feugiat sem vel arcu feugiat, sed maximus elit aliquam. Pellentesque justo leo, pellentesque a mollis eget, suscipit ac turpis. Duis ornare dui quis nisi dictum, at consequat justo auctor. + +## Section 2 + +Nullam ullamcorper ac nunc sed tempus. Suspendisse sagittis tortor auctor magna aliquam, eu porta libero pretium. Vestibulum placerat feugiat mattis. Nulla ornare luctus quam vel iaculis. Nulla ornare justo venenatis viverra mollis. Aliquam pretium dui sed sem accumsan blandit. Integer aliquam posuere odio, ac interdum lorem egestas in. Vivamus sed est dolor. Nulla cursus blandit elit nec porta. Etiam dictum libero vel magna pulvinar convallis. Proin lacinia elementum ligula a malesuada. Ut rhoncus tortor vitae lorem ultrices luctus. Aenean sit amet libero non metus fringilla lacinia id quis massa. Nulla sollicitudin tortor non turpis suscipit, in imperdiet ex finibus. + +## Section 3 + +Sed leo tortor, sagittis sit amet lacus eu, tincidunt ornare lacus. Integer lorem lacus, facilisis nec turpis et, fermentum scelerisque felis. Pellentesque ultrices nibh lacus, ut tincidunt metus finibus quis. Nunc tincidunt eget urna a lacinia. Sed auctor lorem eu ultrices interdum. Aliquam vehicula ornare massa, ut placerat mi imperdiet et. Sed facilisis eleifend tortor, id semper nisl congue eu. Donec malesuada dolor eget ex rutrum, nec consequat erat ultrices. Maecenas iaculis leo id est lacinia laoreet. Donec tempor cursus orci. Suspendisse potenti. Etiam cursus iaculis tincidunt. + diff --git a/tests/testthat/html-uptree-lib_dir/node-03/index.Rmd b/tests/testthat/html-uptree-lib_dir/node-03/index.Rmd new file mode 100644 index 0000000000..197033b7a3 --- /dev/null +++ b/tests/testthat/html-uptree-lib_dir/node-03/index.Rmd @@ -0,0 +1,32 @@ +--- +title: "Page #3" +output: + html_document: + allow_uptree_lib_dir: no + lib_dir: "../lib" + css: "../lib/styles.css" + self_contained: false +--- + +```{r setup, include=FALSE} +knitr::opts_chunk$set(echo = TRUE) +``` + +# This is Page #3. + +* [Home](../index.html) +* [Page 1](../node-01/index.html) +* [Page 2](../node-02/index.html) + +## Section 1 + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque sapien nisl, egestas ut erat eu, egestas porttitor tellus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed pellentesque volutpat justo, et cursus lorem pulvinar luctus. Curabitur porta, diam a pretium egestas, dui dolor tempus sem, non facilisis turpis tortor a lectus. Morbi nec enim aliquam, eleifend libero eget, efficitur quam. Fusce dapibus elit vitae tellus hendrerit tristique. Donec felis elit, gravida non orci consectetur, finibus sollicitudin justo. Curabitur imperdiet pellentesque elit ac ultricies. Vestibulum erat leo, tristique non felis a, fringilla pellentesque dolor. Vivamus sem justo, commodo sit amet ultrices in, lobortis sit amet lacus. Donec feugiat sem vel arcu feugiat, sed maximus elit aliquam. Pellentesque justo leo, pellentesque a mollis eget, suscipit ac turpis. Duis ornare dui quis nisi dictum, at consequat justo auctor. + +## Section 2 + +Nullam ullamcorper ac nunc sed tempus. Suspendisse sagittis tortor auctor magna aliquam, eu porta libero pretium. Vestibulum placerat feugiat mattis. Nulla ornare luctus quam vel iaculis. Nulla ornare justo venenatis viverra mollis. Aliquam pretium dui sed sem accumsan blandit. Integer aliquam posuere odio, ac interdum lorem egestas in. Vivamus sed est dolor. Nulla cursus blandit elit nec porta. Etiam dictum libero vel magna pulvinar convallis. Proin lacinia elementum ligula a malesuada. Ut rhoncus tortor vitae lorem ultrices luctus. Aenean sit amet libero non metus fringilla lacinia id quis massa. Nulla sollicitudin tortor non turpis suscipit, in imperdiet ex finibus. + +## Section 3 + +Sed leo tortor, sagittis sit amet lacus eu, tincidunt ornare lacus. Integer lorem lacus, facilisis nec turpis et, fermentum scelerisque felis. Pellentesque ultrices nibh lacus, ut tincidunt metus finibus quis. Nunc tincidunt eget urna a lacinia. Sed auctor lorem eu ultrices interdum. Aliquam vehicula ornare massa, ut placerat mi imperdiet et. Sed facilisis eleifend tortor, id semper nisl congue eu. Donec malesuada dolor eget ex rutrum, nec consequat erat ultrices. Maecenas iaculis leo id est lacinia laoreet. Donec tempor cursus orci. Suspendisse potenti. Etiam cursus iaculis tincidunt. + diff --git a/tests/testthat/test-html-uptree-lib_dir.R b/tests/testthat/test-html-uptree-lib_dir.R new file mode 100644 index 0000000000..c4f903f20a --- /dev/null +++ b/tests/testthat/test-html-uptree-lib_dir.R @@ -0,0 +1,40 @@ +context("html-uptree-lib_dir") + +# copy part of our demo site to a tempdir +local_create_site <- function(files, env = parent.frame()) { + site_dir <- tempfile() + dir.create(site_dir, recursive = TRUE) + withr::defer(unlink(site_dir, recursive = TRUE), envir = env) + # by default copy all files + if (missing(files)) files <- c("index.Rmd", "node-01", "node-02", "lib") + file.copy(test_path("html-uptree-lib_dir", files), site_dir, recursive = TRUE) + site_dir +} + +test_that("render_pages", { + + # copy our demo site to a tempdir + site_dir <- local_create_site() + + # render it + capture.output({ + render(file.path(site_dir, "index.Rmd")) + render(file.path(site_dir, "node-01", "index.Rmd")) + render(file.path(site_dir, "node-02", "index.Rmd")) + }) + + # did the html files get rendered and the css get copied? + html_files <- c("index.html") + html_files <- c(file.path(site_dir, html_files), + file.path(site_dir, c("node-01", "node-02"), html_files)) + expect_true(all(file.exists(html_files))) +}) + +test_that("disable-uptree-lib_dir", { + site_dir <- local_create_site(c("index.Rmd", "node-03", "lib")) + expect_error( + render(file.path(site_dir, "node-03", "index.Rmd")), + regexp = "The path .* does not appear to be a descendant of .*" + ) +}) + diff --git a/tests/testthat/test-output_format.R b/tests/testthat/test-output_format.R index 64eb240c6d..dd6553eaba 100644 --- a/tests/testthat/test-output_format.R +++ b/tests/testthat/test-output_format.R @@ -1,6 +1,7 @@ test_that("all elements can be NULL", { out_fmt <- output_format( - knitr = NULL, pandoc = NULL, keep_md = NULL, clean_supporting = NULL + knitr = NULL, pandoc = NULL, keep_md = NULL, clean_supporting = NULL, + allow_uptree_lib_dir = NULL ) lapply(out_fmt, expect_null) }) @@ -10,6 +11,7 @@ test_that("inherits base format", { base_fmt$file_scope <- identity out_fmt <- output_format( knitr = NULL, pandoc = NULL, keep_md = NULL, clean_supporting = NULL, + allow_uptree_lib_dir = NULL, base_format = base_fmt ) classes <- lapply(base_fmt, class)