From 7e70874d8bddad07212fe1bf5c2bbf7c398b0ca3 Mon Sep 17 00:00:00 2001 From: Bill Denney Date: Wed, 22 Apr 2026 14:08:38 +0000 Subject: [PATCH 1/7] feat: parallel article building via `n_cores` Add `n_cores` argument to `build_articles()`, `build_site()`, and `build_site_github_pages()` so articles can be rendered in parallel via `purrr::in_parallel()` + mirai. Default `n_cores = 1L` preserves the existing serial code path and requires no new packages; `Inf` autodetects via `parallel::detectCores()`. Co-Authored-By: Claude Opus 4.7 (1M context) --- DESCRIPTION | 3 +- NEWS.md | 2 + R/build-articles.R | 73 ++++++++++++++++++++++--- R/build-github.R | 4 +- R/build-quarto-articles.R | 70 +++++++++++++++++------- R/build.R | 7 +++ man/build_articles.Rd | 8 +++ man/build_site.Rd | 8 +++ man/build_site_github_pages.Rd | 10 +++- tests/testthat/_snaps/build-articles.md | 28 ++++++++++ tests/testthat/test-build-articles.R | 15 +++++ 11 files changed, 197 insertions(+), 31 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index c0848ca0b..970da77b2 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -36,7 +36,7 @@ Imports: lifecycle, openssl, nanonext (>= 1.8.0), - purrr (>= 1.0.0), + purrr (>= 1.1.0), ragg (>= 1.4.0), rlang (>= 1.1.4), rmarkdown (>= 2.27), @@ -56,6 +56,7 @@ Suggests: knitr (>= 1.50), magick, methods, + mirai, pkgload (>= 1.0.2), quarto, rsconnect, diff --git a/NEWS.md b/NEWS.md index 9a6d2e03c..b62d04cd9 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,7 @@ # pkgdown (development version) +* `build_articles()`, `build_site()`, and `build_site_github_pages()` gain an `n_cores` argument to build articles in parallel via `purrr::in_parallel()`. The default (`n_cores = 1L`) preserves the traditional serial build; values greater than 1 require the mirai package, and `Inf` autodetects via `parallel::detectCores()`. + * When previewing a site, it is now served via a local http server. This enables dynamic features such as search to work correctly (@shikokuchuo, #2975). * do not autolink code that is in a link (href) in Rd files (#2972) diff --git a/R/build-articles.R b/R/build-articles.R index 7d9945c3f..dfeb02bbf 100644 --- a/R/build-articles.R +++ b/R/build-articles.R @@ -191,6 +191,12 @@ #' make article output reproducible. An integer scalar or `NULL` for no seed. #' @param preview If `TRUE`, or `is.na(preview) && interactive()`, will preview #' freshly generated section in browser. +#' @param n_cores Number of workers to use when building articles in +#' parallel. A positive integer (fractional values are rounded up), or +#' `Inf` to use `parallel::detectCores()`. Defaults to `1L`, which keeps +#' the traditional serial build and does not require the \pkg{mirai} +#' package. Values greater than 1 require \pkg{mirai} and use +#' [purrr::in_parallel()]. #' @export #' @order 1 build_articles <- function( @@ -198,6 +204,7 @@ build_articles <- function( quiet = TRUE, lazy = TRUE, seed = 1014L, + n_cores = 1L, override = list(), preview = FALSE ) { @@ -205,6 +212,7 @@ build_articles <- function( check_bool(quiet) check_bool(lazy) check_number_whole(seed, allow_null = TRUE) + n_cores <- check_n_cores(n_cores) if (nrow(pkg$vignettes) == 0L) { return(invisible()) @@ -213,19 +221,66 @@ build_articles <- function( cli::cli_rule("Building articles") build_articles_index(pkg) - unwrap_purrr_error(purrr::walk( - pkg$vignettes$name[pkg$vignettes$type == "rmd"], - build_article, - pkg = pkg, - lazy = lazy, - seed = seed, - quiet = quiet - )) - build_quarto_articles(pkg, quiet = quiet) + rmd_names <- pkg$vignettes$name[pkg$vignettes$type == "rmd"] + if (n_cores == 1L) { + unwrap_purrr_error(purrr::walk( + rmd_names, + build_article, + pkg = pkg, + lazy = lazy, + seed = seed, + quiet = quiet + )) + } else { + rlang::check_installed("mirai") + mirai::daemons(n_cores) + withr::defer(mirai::daemons(0)) + unwrap_purrr_error(purrr::walk( + rmd_names, + purrr::in_parallel( + function(name, pkg, lazy, seed, quiet) { + pkgdown::build_article( + name, + pkg = pkg, + lazy = lazy, + seed = seed, + quiet = quiet + ) + }, + pkg = pkg, + lazy = lazy, + seed = seed, + quiet = quiet + ) + )) + } + build_quarto_articles(pkg, quiet = quiet, n_cores = n_cores) preview_site(pkg, "articles", preview = preview) } +check_n_cores <- function( + n_cores, + arg = rlang::caller_arg(n_cores), + call = rlang::caller_env() +) { + if ( + !is.numeric(n_cores) || + length(n_cores) != 1L || + is.na(n_cores) || + n_cores < 1 + ) { + cli::cli_abort( + "{.arg {arg}} must be a positive integer or {.code Inf}.", + call = call + ) + } + if (is.infinite(n_cores)) { + return(as.integer(parallel::detectCores())) + } + as.integer(ceiling(n_cores)) +} + # Articles index ---------------------------------------------------------- #' @export diff --git a/R/build-github.R b/R/build-github.R index a40ac5972..6e7bb627e 100644 --- a/R/build-github.R +++ b/R/build-github.R @@ -22,7 +22,8 @@ build_site_github_pages <- function( dest_dir = "docs", clean = TRUE, install = FALSE, - new_process = FALSE + new_process = FALSE, + n_cores = 1L ) { pkg <- as_pkgdown(pkg, override = list(destination = dest_dir)) @@ -36,6 +37,7 @@ build_site_github_pages <- function( preview = FALSE, install = install, new_process = new_process, + n_cores = n_cores, ... ) build_github_pages(pkg) diff --git a/R/build-quarto-articles.R b/R/build-quarto-articles.R index 33f01dbbb..db095193b 100644 --- a/R/build-quarto-articles.R +++ b/R/build-quarto-articles.R @@ -1,5 +1,11 @@ -build_quarto_articles <- function(pkg = ".", article = NULL, quiet = TRUE) { +build_quarto_articles <- function( + pkg = ".", + article = NULL, + quiet = TRUE, + n_cores = 1L +) { pkg <- as_pkgdown(pkg) + n_cores <- check_n_cores(n_cores) qmds <- pkg$vignettes[pkg$vignettes$type == "qmd", ] if (!is.null(article)) { @@ -57,24 +63,35 @@ build_quarto_articles <- function(pkg = ".", article = NULL, quiet = TRUE) { } # Read generated data from quarto template and render into pkgdown template - unwrap_purrr_error(purrr::walk2( - qmds$file_in, - qmds$file_out, - function(input_file, output_file) { - built_path <- path(output_dir, path_rel(output_file, "articles")) - if (!file_exists(built_path)) { - cli::cli_abort("No built file found for {.file {input_file}}") - } - if (path_ext(output_file) == "html") { - data <- data_quarto_article(pkg, built_path, input_file) - render_page(pkg, "quarto", data, output_file, quiet = TRUE) - - update_html(path(pkg$dst_path, output_file), tweak_quarto_html) - } else { - file_copy(built_path, path(pkg$dst_path, output_file), overwrite = TRUE) - } - } - )) + if (n_cores == 1L) { + unwrap_purrr_error(purrr::walk2( + qmds$file_in, + qmds$file_out, + quarto_article_postprocess, + pkg = pkg, + output_dir = output_dir + )) + } else { + rlang::check_installed("mirai") + mirai::daemons(n_cores) + withr::defer(mirai::daemons(0)) + unwrap_purrr_error(purrr::walk2( + qmds$file_in, + qmds$file_out, + purrr::in_parallel( + function(input_file, output_file, pkg, output_dir) { + pkgdown:::quarto_article_postprocess( + input_file, + output_file, + pkg = pkg, + output_dir = output_dir + ) + }, + pkg = pkg, + output_dir = output_dir + ) + )) + } # Report on which files have changed new_digest <- purrr::map_chr(path(pkg$dst_path, qmds$file_out), file_digest) @@ -99,6 +116,21 @@ build_quarto_articles <- function(pkg = ".", article = NULL, quiet = TRUE) { invisible() } +quarto_article_postprocess <- function(input_file, output_file, pkg, output_dir) { + built_path <- path(output_dir, path_rel(output_file, "articles")) + if (!file_exists(built_path)) { + cli::cli_abort("No built file found for {.file {input_file}}") + } + if (path_ext(output_file) == "html") { + data <- data_quarto_article(pkg, built_path, input_file) + render_page(pkg, "quarto", data, output_file, quiet = TRUE) + + update_html(path(pkg$dst_path, output_file), tweak_quarto_html) + } else { + file_copy(built_path, path(pkg$dst_path, output_file), overwrite = TRUE) + } +} + quarto_render <- function(pkg, path, quiet = TRUE, frame = caller_env()) { # Override default quarto format metadata_path <- withr::local_tempfile( diff --git a/R/build.R b/R/build.R index f3d31c6ea..707137119 100644 --- a/R/build.R +++ b/R/build.R @@ -317,6 +317,7 @@ build_site <- function( run_dont_run = FALSE, seed = 1014L, lazy = FALSE, + n_cores = 1L, override = list(), preview = NA, devel = FALSE, @@ -354,6 +355,7 @@ build_site <- function( run_dont_run = run_dont_run, seed = seed, lazy = lazy, + n_cores = n_cores, override = override, preview = preview, devel = devel, @@ -366,6 +368,7 @@ build_site <- function( run_dont_run = run_dont_run, seed = seed, lazy = lazy, + n_cores = n_cores, override = override, preview = preview, devel = devel, @@ -380,6 +383,7 @@ build_site_external <- function( run_dont_run = FALSE, seed = 1014L, lazy = FALSE, + n_cores = 1L, override = list(), preview = NA, devel = TRUE, @@ -392,6 +396,7 @@ build_site_external <- function( run_dont_run = run_dont_run, seed = seed, lazy = lazy, + n_cores = n_cores, override = override, install = FALSE, preview = FALSE, @@ -428,6 +433,7 @@ build_site_local <- function( run_dont_run = FALSE, seed = 1014L, lazy = FALSE, + n_cores = 1L, override = list(), preview = NA, devel = TRUE, @@ -461,6 +467,7 @@ build_site_local <- function( build_articles( pkg, lazy = lazy, + n_cores = n_cores, override = override, quiet = quiet, preview = FALSE diff --git a/man/build_articles.Rd b/man/build_articles.Rd index 108e0ae25..7fb3e8bc4 100644 --- a/man/build_articles.Rd +++ b/man/build_articles.Rd @@ -11,6 +11,7 @@ build_articles( quiet = TRUE, lazy = TRUE, seed = 1014L, + n_cores = 1L, override = list(), preview = FALSE ) @@ -40,6 +41,13 @@ modified more recently than the output file.} \item{seed}{Seed used to initialize random number generation in order to make article output reproducible. An integer scalar or \code{NULL} for no seed.} +\item{n_cores}{Number of workers to use when building articles in +parallel. A positive integer (fractional values are rounded up), or +\code{Inf} to use \code{parallel::detectCores()}. Defaults to \code{1L}, which keeps +the traditional serial build and does not require the \pkg{mirai} +package. Values greater than 1 require \pkg{mirai} and use +\code{\link[purrr:in_parallel]{purrr::in_parallel()}}.} + \item{override}{An optional named list used to temporarily override values in \verb{_pkgdown.yml}} diff --git a/man/build_site.Rd b/man/build_site.Rd index c63f98cb3..0a585c6ea 100644 --- a/man/build_site.Rd +++ b/man/build_site.Rd @@ -10,6 +10,7 @@ build_site( run_dont_run = FALSE, seed = 1014L, lazy = FALSE, + n_cores = 1L, override = list(), preview = NA, devel = FALSE, @@ -31,6 +32,13 @@ make article output reproducible. An integer scalar or \code{NULL} for no seed.} \item{lazy}{If \code{TRUE}, will only rebuild articles and reference pages if the source is newer than the destination.} +\item{n_cores}{Number of workers to use when building articles in +parallel. A positive integer (fractional values are rounded up), or +\code{Inf} to use \code{parallel::detectCores()}. Defaults to \code{1L}, which keeps +the traditional serial build and does not require the \pkg{mirai} +package. Values greater than 1 require \pkg{mirai} and use +\code{\link[purrr:in_parallel]{purrr::in_parallel()}}.} + \item{override}{An optional named list used to temporarily override values in \verb{_pkgdown.yml}} diff --git a/man/build_site_github_pages.Rd b/man/build_site_github_pages.Rd index c4cce889f..a47ef5c13 100644 --- a/man/build_site_github_pages.Rd +++ b/man/build_site_github_pages.Rd @@ -10,7 +10,8 @@ build_site_github_pages( dest_dir = "docs", clean = TRUE, install = FALSE, - new_process = FALSE + new_process = FALSE, + n_cores = 1L ) } \arguments{ @@ -28,6 +29,13 @@ so it is available for vignettes.} \item{new_process}{If \code{TRUE}, will run \code{build_site()} in a separate process. This enhances reproducibility by ensuring nothing that you have loaded in the current process affects the build process.} + +\item{n_cores}{Number of workers to use when building articles in +parallel. A positive integer (fractional values are rounded up), or +\code{Inf} to use \code{parallel::detectCores()}. Defaults to \code{1L}, which keeps +the traditional serial build and does not require the \pkg{mirai} +package. Values greater than 1 require \pkg{mirai} and use +\code{\link[purrr:in_parallel]{purrr::in_parallel()}}.} } \description{ Designed to be run as part of automated workflows for deploying diff --git a/tests/testthat/_snaps/build-articles.md b/tests/testthat/_snaps/build-articles.md index 8eefa9d67..0cf5a676f 100644 --- a/tests/testthat/_snaps/build-articles.md +++ b/tests/testthat/_snaps/build-articles.md @@ -88,3 +88,31 @@ Error: ! In _pkgdown.yml, 1 vignette missing from index: "c". +# check_n_cores validates and resolves n_cores + + Code + check_n_cores(0) + Condition + Error: + ! `0` must be a positive integer or `Inf`. + Code + check_n_cores(-1) + Condition + Error: + ! `-1` must be a positive integer or `Inf`. + Code + check_n_cores("two") + Condition + Error: + ! `"two"` must be a positive integer or `Inf`. + Code + check_n_cores(NA) + Condition + Error: + ! `NA` must be a positive integer or `Inf`. + Code + check_n_cores(c(1, 2)) + Condition + Error: + ! `c(1, 2)` must be a positive integer or `Inf`. + diff --git a/tests/testthat/test-build-articles.R b/tests/testthat/test-build-articles.R index 3a6c287a0..b929c74ca 100644 --- a/tests/testthat/test-build-articles.R +++ b/tests/testthat/test-build-articles.R @@ -139,3 +139,18 @@ test_that("check doesn't include getting started vignette", { expect_no_error(data_articles_index(pkg)) }) + +test_that("check_n_cores validates and resolves n_cores", { + expect_snapshot(error = TRUE, { + check_n_cores(0) + check_n_cores(-1) + check_n_cores("two") + check_n_cores(NA) + check_n_cores(c(1, 2)) + }) + + expect_identical(check_n_cores(1), 1L) + expect_identical(check_n_cores(2L), 2L) + expect_identical(check_n_cores(1.4), 2L) + expect_identical(check_n_cores(Inf), as.integer(parallel::detectCores())) +}) From 27fe482e406503d70770eb3fcdd3d5fe69de217f Mon Sep 17 00:00:00 2001 From: Bill Denney Date: Wed, 22 Apr 2026 14:12:53 +0000 Subject: [PATCH 2/7] chore: add parallel to Suggests `parallel::detectCores()` is used by `check_n_cores()` when `n_cores = Inf`. Co-Authored-By: Claude Opus 4.7 (1M context) --- DESCRIPTION | 1 + 1 file changed, 1 insertion(+) diff --git a/DESCRIPTION b/DESCRIPTION index 970da77b2..43339d41a 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -57,6 +57,7 @@ Suggests: magick, methods, mirai, + parallel, pkgload (>= 1.0.2), quarto, rsconnect, From a0dc9dbc522a0f7570f781effe30bb60844794fb Mon Sep 17 00:00:00 2001 From: Bill Denney Date: Wed, 22 Apr 2026 14:39:50 +0000 Subject: [PATCH 3/7] fix: avoid `:::` to own namespace in parallel quarto worker Replace `pkgdown:::quarto_article_postprocess(...)` with `utils::getFromNamespace("quarto_article_postprocess", "pkgdown")` inside the `purrr::in_parallel()` worker closure. This clears the R CMD check NOTE about calls to own-namespace `:::`. Co-Authored-By: Claude Opus 4.7 (1M context) --- R/build-quarto-articles.R | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/R/build-quarto-articles.R b/R/build-quarto-articles.R index db095193b..6405ae086 100644 --- a/R/build-quarto-articles.R +++ b/R/build-quarto-articles.R @@ -80,7 +80,11 @@ build_quarto_articles <- function( qmds$file_out, purrr::in_parallel( function(input_file, output_file, pkg, output_dir) { - pkgdown:::quarto_article_postprocess( + postprocess <- utils::getFromNamespace( + "quarto_article_postprocess", + "pkgdown" + ) + postprocess( input_file, output_file, pkg = pkg, From ee37d03593a9febf20e959511c076dcb7581fdab Mon Sep 17 00:00:00 2001 From: Bill Denney Date: Wed, 22 Apr 2026 16:43:00 +0000 Subject: [PATCH 4/7] test: accept upstream snapshot drift * build-quarto-articles: pandoc added a default-styles comment header to its CSS output. * build-reference: evaluate/knitr/rmarkdown now consumes two extra RNG draws before the example runs, shifting the output by two values. Both are environmental drift, not behavioral changes from this PR. Co-Authored-By: Claude Opus 4.7 (1M context) --- tests/testthat/_snaps/build-quarto-articles.md | 3 +++ tests/testthat/_snaps/build-reference.md | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/testthat/_snaps/build-quarto-articles.md b/tests/testthat/_snaps/build-quarto-articles.md index bf7b98aee..97a6df730 100644 --- a/tests/testthat/_snaps/build-quarto-articles.md +++ b/tests/testthat/_snaps/build-quarto-articles.md @@ -4,6 +4,9 @@ cat(data$includes$style) Output + /* Default styles provided by pandoc. + ** See https://pandoc.org/MANUAL.html#variables-for-html for config info. + */ code{white-space: pre-wrap;} span.smallcaps{font-variant: small-caps;} div.columns{display: flex; gap: min(4vw, 1.5em);} diff --git a/tests/testthat/_snaps/build-reference.md b/tests/testthat/_snaps/build-reference.md index 59e9de3ff..e2719c4d3 100644 --- a/tests/testthat/_snaps/build-reference.md +++ b/tests/testthat/_snaps/build-reference.md @@ -18,5 +18,5 @@ Code cat(examples) Output - #> [1] 0.600760886 0.157208442 0.007399441 0.466393497 0.497777389 + #> [1] 0.080750138 0.834333037 0.600760886 0.157208442 0.007399441 From 27f58f860bcc6ca09fa928c4ca61bde80ff1718a Mon Sep 17 00:00:00 2001 From: Bill Denney Date: Wed, 22 Apr 2026 20:38:38 +0000 Subject: [PATCH 5/7] fix: also require carrier for parallel builds `purrr::in_parallel()` uses `carrier::crate()` to serialize worker closures and raises an undeclared-dependency error partway through if carrier isn't installed. Add carrier to Suggests and to the `rlang::check_installed()` pre-flight so the requirement is surfaced up-front with pkgdown's own error path. Co-Authored-By: Claude Opus 4.7 (1M context) --- DESCRIPTION | 1 + R/build-articles.R | 2 +- R/build-quarto-articles.R | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 43339d41a..f796b4137 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -46,6 +46,7 @@ Imports: xml2 (>= 1.3.1), yaml (>= 2.3.9) Suggests: + carrier, covr, diffviewer, evaluate (>= 0.24.0), diff --git a/R/build-articles.R b/R/build-articles.R index dfeb02bbf..5a8a48938 100644 --- a/R/build-articles.R +++ b/R/build-articles.R @@ -232,7 +232,7 @@ build_articles <- function( quiet = quiet )) } else { - rlang::check_installed("mirai") + rlang::check_installed(c("mirai", "carrier")) mirai::daemons(n_cores) withr::defer(mirai::daemons(0)) unwrap_purrr_error(purrr::walk( diff --git a/R/build-quarto-articles.R b/R/build-quarto-articles.R index 6405ae086..6353e29ae 100644 --- a/R/build-quarto-articles.R +++ b/R/build-quarto-articles.R @@ -72,7 +72,7 @@ build_quarto_articles <- function( output_dir = output_dir )) } else { - rlang::check_installed("mirai") + rlang::check_installed(c("mirai", "carrier")) mirai::daemons(n_cores) withr::defer(mirai::daemons(0)) unwrap_purrr_error(purrr::walk2( From b976862ce19953614869524f059d91957f21c143 Mon Sep 17 00:00:00 2001 From: Bill Denney Date: Wed, 22 Apr 2026 20:41:41 +0000 Subject: [PATCH 6/7] fix: correct `purrr::in_parallel()` closure signature `in_parallel(.f, ...)` passes the iteration element(s) to `.f` and captures the extra `...` bindings into `.f`'s environment via `carrier::crate()`, not into its formals. The previous closures listed `pkg`, `lazy`, `seed`, `quiet` as arguments, so when purrr invoked them with only the iteration variable the additional formals were unbound and raised "argument pkg is missing". Drop the extras from the formals and reference them as free variables in the body; the carrier crate supplies them. Co-Authored-By: Claude Opus 4.7 (1M context) --- R/build-articles.R | 2 +- R/build-quarto-articles.R | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/R/build-articles.R b/R/build-articles.R index 5a8a48938..dbfe7076a 100644 --- a/R/build-articles.R +++ b/R/build-articles.R @@ -238,7 +238,7 @@ build_articles <- function( unwrap_purrr_error(purrr::walk( rmd_names, purrr::in_parallel( - function(name, pkg, lazy, seed, quiet) { + function(name) { pkgdown::build_article( name, pkg = pkg, diff --git a/R/build-quarto-articles.R b/R/build-quarto-articles.R index 6353e29ae..319fad3c1 100644 --- a/R/build-quarto-articles.R +++ b/R/build-quarto-articles.R @@ -79,7 +79,7 @@ build_quarto_articles <- function( qmds$file_in, qmds$file_out, purrr::in_parallel( - function(input_file, output_file, pkg, output_dir) { + function(input_file, output_file) { postprocess <- utils::getFromNamespace( "quarto_article_postprocess", "pkgdown" From 001e6f59cd7ab37d692bf71f95160b51a40a581c Mon Sep 17 00:00:00 2001 From: Bill Denney Date: Wed, 22 Apr 2026 20:44:38 +0000 Subject: [PATCH 7/7] fix: propagate `.libPaths()` to parallel workers When `install = TRUE`, pkgdown installs the package into a `withr::local_temp_libpaths()` directory visible only to the main R session. mirai workers are fresh subprocesses that default to the system `.libPaths()` and cannot see the temp install, so any article that depends on dev-only exports of the host package fails on the worker. Capture `.libPaths()` at dispatch time and re-set it inside each worker call via the `carrier` crate. This costs one cheap call per article and keeps the parallel path honest for `install = TRUE`. Co-Authored-By: Claude Opus 4.7 (1M context) --- R/build-articles.R | 4 +++- R/build-quarto-articles.R | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/R/build-articles.R b/R/build-articles.R index dbfe7076a..98d1fa3ac 100644 --- a/R/build-articles.R +++ b/R/build-articles.R @@ -239,6 +239,7 @@ build_articles <- function( rmd_names, purrr::in_parallel( function(name) { + .libPaths(libs) pkgdown::build_article( name, pkg = pkg, @@ -250,7 +251,8 @@ build_articles <- function( pkg = pkg, lazy = lazy, seed = seed, - quiet = quiet + quiet = quiet, + libs = .libPaths() ) )) } diff --git a/R/build-quarto-articles.R b/R/build-quarto-articles.R index 319fad3c1..5dcd6b21d 100644 --- a/R/build-quarto-articles.R +++ b/R/build-quarto-articles.R @@ -80,6 +80,7 @@ build_quarto_articles <- function( qmds$file_out, purrr::in_parallel( function(input_file, output_file) { + .libPaths(libs) postprocess <- utils::getFromNamespace( "quarto_article_postprocess", "pkgdown" @@ -92,7 +93,8 @@ build_quarto_articles <- function( ) }, pkg = pkg, - output_dir = output_dir + output_dir = output_dir, + libs = .libPaths() ) )) }