From 4a6b9508089ce9bbe3ff28ea94218ea80d58a6fb Mon Sep 17 00:00:00 2001 From: Salim B Date: Mon, 5 Dec 2022 06:49:41 +0100 Subject: [PATCH 01/27] Avoid exernal assets This is configurable via YAML option `template.params.external_assets`. --- R/build.R | 41 +++++++++++++------ R/theme.R | 76 ++++++++++++++++++++++++++++++++--- inst/BS5/assets_external.yaml | 45 +++++++++++++++++++++ inst/BS5/templates/head.html | 22 ---------- man/build_site.Rd | 15 ++++++- 5 files changed, 157 insertions(+), 42 deletions(-) create mode 100644 inst/BS5/assets_external.yaml diff --git a/R/build.R b/R/build.R index e7ccef797..0c0b854b3 100644 --- a/R/build.R +++ b/R/build.R @@ -141,7 +141,7 @@ #' The `template` field is mostly used to control the appearance of the site. #' See `vignette("customise")` for details. #' -#' There are two other `template` fields that control other aspects of the +#' There are three other `template` fields that control other aspects of the #' site: #' #' * `noindex: true` will suppress indexing of your pages by search engines: @@ -152,23 +152,38 @@ #' noindex: true #' ``` #' -#' * `google_site_verification` allows you to verify your site with google: +#' * `google_site_verification` allows you to verify your site with google: #' -#' ```yaml -#' template: -#' params: -#' google_site_verification: _nn6ile-a6x6lctOW -#' ``` +#' ```yaml +#' template: +#' params: +#' google_site_verification: _nn6ile-a6x6lctOW +#' ``` #' #' * `trailing_slash_redirect: true` will automatically redirect #' `your-package-url.com` to `your-package-url.com/`, using a JS script -#' added to the `` of the home page. This is useful in certain -#' redirect scenarios. +#' added to the `` of the home page. This is useful in certain +#' redirect scenarios. #' -#' ```yaml -#' template: -#' trailing_slash_redirect: true -#' ``` +#' ```yaml +#' template: +#' trailing_slash_redirect: true +#' ``` +#' +#' * `external_assets: true` will avoid the direct inclusion of certain +#' JS and CSS assets in the built site and instead let them be fetched +#' remotely from content delivery networks (CDNs). Enabling this option +#' results in additional cross-origin requests which might have adverse +#' effects on the privacy of your site's visitors. Your site will also stop +#' to work properly in case the CDN operators should decide to shut down +#' their service or stop hosting the specific versions of the assets pkgdown +#' uses. +#' +#' ```yaml +#' template: +#' params: +#' external_assets: true +#' ``` #' #' @section Analytics: #' diff --git a/R/theme.R b/R/theme.R index 197180281..695d1efa2 100644 --- a/R/theme.R +++ b/R/theme.R @@ -3,29 +3,93 @@ build_bslib <- function(pkg = ".") { bs_theme <- bs_theme(pkg) deps <- bslib::bs_theme_dependencies(bs_theme) - deps <- lapply(deps, htmltools::copyDependencyToDir, file.path(pkg$dst_path, "deps")) + deps <- lapply(deps, htmltools::copyDependencyToDir, path_deps(pkg)) deps <- lapply(deps, htmltools::makeDependencyRelative, pkg$dst_path) head <- htmltools::renderDependencies(deps, srcType = "file") - write_lines(head, data_deps_path(pkg)) + + # include additional external assets + use_ext <- isTRUE(pkg$meta$template$params$external_assets) + head <- paste( + head, + paste0(assemble_ext_assets(pkg, use_ext), collapse = "\n"), + sep = "\n" + ) + + write_lines(head, path_data_deps(pkg)) +} + +assemble_ext_assets <- function(pkg, + use_ext = FALSE) { + path_assets_yaml <- path_pkgdown(paste0("BS", pkg$bs_version), "assets_external.yaml") + deps_ext <- yaml::read_yaml(path_assets_yaml) + + purrr::map_chr(deps_ext, ~ { + # download resource if necessary + if (!use_ext) { + path <- path_deps(pkg, basename(.x$url)) + download.file(.x$url, path, quiet = TRUE) + + # download subressources (webfonts etc.) if necessary + if (isTRUE(.x$has_subressources)) { + file_content <- read_file(path) + pos <- gregexpr("(?<=\\burl\\((?!(data|https?):))[^)?#]*", file_content, perl = TRUE) + urls <- unique(unlist(regmatches(file_content, pos))) + subdirs <- unique(fs::path_dir(urls)) + fs::dir_create( + fs::path_norm(fs::path(path_deps(pkg), subdirs)), + recurse = TRUE + ) + remote_urls <- fs::path_norm(fs::path(fs::path_dir(.x$url), urls)) + purrr::walk2( + remote_urls, + urls, + ~ download.file(.x, fs::path_norm(path_deps(pkg, .y)), quiet = TRUE) + ) + } + .x$url <- fs::path_rel(path, pkg$dst_path) + } + + # assemble HTML tag + switch( + .x$type, + "stylesheet" = paste0( + sprintf('' + ), + "script" = paste0( + sprintf('' + ), + cli::cli_abort( + "Unknown asset type {.val {.x$type}} defined in {.file path_assets_yaml}." + ) + ) + }) } data_deps <- function(pkg, depth) { - if (!file.exists(data_deps_path(pkg))) { + if (!file.exists(path_data_deps(pkg))) { abort("Run pkgdown::init_site() first.") } deps_path <- paste0(up_path(depth), "deps") - data_deps <- read_lines(data_deps_path(pkg)) + data_deps <- read_lines(path_data_deps(pkg)) data_deps <- gsub('src="deps', sprintf('src="%s', deps_path), data_deps) data_deps <- gsub('href="deps', sprintf('href="%s', deps_path), data_deps) paste0(data_deps, collapse = "") } -data_deps_path <- function(pkg) { - file.path(pkg$dst_path, "deps", "data-deps.txt") +path_deps <- function(pkg, ...) { + file.path(pkg$dst_path, "deps", ...) +} + +path_data_deps <- function(pkg) { + file.path(path_deps(pkg), "data-deps.txt") } bs_theme <- function(pkg = ".") { diff --git a/inst/BS5/assets_external.yaml b/inst/BS5/assets_external.yaml new file mode 100644 index 000000000..f2776d9b8 --- /dev/null +++ b/inst/BS5/assets_external.yaml @@ -0,0 +1,45 @@ +# Font Awesome icons +- type: "stylesheet" + url: "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.1/css/all.min.css" + integrity: "sha256-mmgLkCYLUQbXn0B1SRqzHar6dCnv9oZFPEC1g1cwlkk=" + has_subressources: true +- type: "stylesheet" + url: "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.1/css/v4-shims.min.css" + integrity: "sha256-wZjR52fzng1pJHwx4aV2AO3yyTOXrcDW7jBpJtTwVxw=" + +# bootstrap-toc +- type: "script" + url: "https://cdn.jsdelivr.net/gh/afeld/bootstrap-toc@v1.0.1/dist/bootstrap-toc.min.js" + integrity: "sha256-4veVQbu7//Lk5TSmc7YV48MxtMy98e26cf5MrgZYnwo=" + +# headroom.js +- type: "script" + url: "https://cdnjs.cloudflare.com/ajax/libs/headroom/0.11.0/headroom.min.js" + integrity: "sha256-AsUX4SJE1+yuDu5+mAVzJbuYNPHj/WroHuZ8Ir/CkE0=" +- type: "script" + url: "https://cdnjs.cloudflare.com/ajax/libs/headroom/0.11.0/jQuery.headroom.min.js" + integrity: "sha256-ZX/yNShbjqsohH1k95liqY9Gd8uOiE1S4vZc+9KQ1K4=" + +# clipboard.js +- type: "script" + url: "https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.6/clipboard.min.js" + integrity: "sha256-inc5kl9MA1hkeYUt+EC3BhlIgyp/2jDIyBLS6k3UxPI=" + +# search +- type: "script" + url: "https://cdnjs.cloudflare.com/ajax/libs/fuse.js/6.4.6/fuse.js" + integrity: "sha512-zv6Ywkjyktsohkbp9bb45V6tEMoWhzFzXis+LrMehmJZZSys19Yxf1dopHx7WzIKxr5tK2dVcYmaCk2uqdjF4A==" +- type: "script" + url: "https://cdnjs.cloudflare.com/ajax/libs/autocomplete.js/0.38.0/autocomplete.jquery.min.js" + integrity: "sha512-GU9ayf+66Xx2TmpxqJpliWbT5PiGYxpaG8rfnBEk1LL8l1KGkRShhngwdXK1UgqhAzWpZHSiYPc09/NwDQIGyg==" +- type: "script" + url: "https://cdnjs.cloudflare.com/ajax/libs/mark.js/8.11.1/mark.min.js" + integrity: "sha512-5CYOlHXGh6QpOFA/TeTylKLWfB3ftPsde7AnmhuitiTX4K5SqCLBeKro6sPS8ilsz1Q4NRx3v8Ko2IBiszzdww==" + +# MathJax +- type: "script" + url: "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js" + integrity: "sha256-nvJJv9wWKEm88qvoQl9ekL2J+k/RWIsaSScxxlsrv8k=" +- type: "script" + url: "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/config/TeX-AMS-MML_HTMLorMML.js" + integrity: "sha256-84DKXVJXs0/F8OTMzX4UR909+jtl4G7SPypPavF+GfA=" diff --git a/inst/BS5/templates/head.html b/inst/BS5/templates/head.html index a10adc987..39c361d15 100644 --- a/inst/BS5/templates/head.html +++ b/inst/BS5/templates/head.html @@ -19,24 +19,6 @@ {{/has_favicons}} {{{headdeps}}} - - - - - - - - - - - - - - - - - - @@ -80,10 +62,6 @@ {{/google_site_verification}}{{/yaml}} - - - - - {{#yaml}}{{#ganalytics}} From 1a578ae8e68a7cb12ea45ab085ca058b75cc4ed8 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Tue, 28 May 2024 08:22:21 -0500 Subject: [PATCH 25/27] Restore original function name --- R/theme.R | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/R/theme.R b/R/theme.R index 70bbdc246..42cbe5e18 100644 --- a/R/theme.R +++ b/R/theme.R @@ -5,12 +5,8 @@ build_bslib <- function(pkg = ".", call = caller_env()) { cur_deps <- find_deps(pkg) cur_digest <- purrr::map_chr(cur_deps, file_digest) - deps <- c( - bslib::bs_theme_dependencies(bs_theme), - external_dependencies() - ) - - deps <- lapply(deps, htmltools::copyDependencyToDir, path_deps(pkg)) + deps <- c(bslib::bs_theme_dependencies(bs_theme), external_dependencies()) + deps <- lapply(deps, htmltools::copyDependencyToDir, path(pkg$dst_path, "deps")) deps <- lapply(deps, htmltools::makeDependencyRelative, pkg$dst_path) new_deps <- find_deps(pkg) @@ -27,11 +23,11 @@ build_bslib <- function(pkg = ".", call = caller_env()) { } head <- htmltools::renderDependencies(deps, srcType = "file") - write_lines(head, path_data_deps(pkg)) + write_lines(head, data_deps_path(pkg)) } data_deps <- function(pkg, depth) { - if (!file_exists(path_data_deps(pkg))) { + if (!file_exists(data_deps_path(pkg))) { cli::cli_abort( "Run {.fn pkgdown::init_site} first.", call = caller_env() @@ -40,19 +36,15 @@ data_deps <- function(pkg, depth) { deps_path <- paste0(up_path(depth), "deps") - data_deps <- read_lines(path_data_deps(pkg)) + data_deps <- read_lines(data_deps_path(pkg)) data_deps <- gsub('src="deps', sprintf('src="%s', deps_path), data_deps) data_deps <- gsub('href="deps', sprintf('href="%s', deps_path), data_deps) paste0(data_deps, collapse = "") } -path_deps <- function(pkg, ...) { - file.path(pkg$dst_path, "deps", ...) -} - -path_data_deps <- function(pkg) { - file.path(path_deps(pkg), "data-deps.txt") +data_deps_path <- function(pkg) { + path(pkg$dst_path, "deps", "data-deps.txt") } find_deps <- function(pkg) { From 75216aea37a04de3d16307fa5ccc35e7f5592be3 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Tue, 28 May 2024 08:33:24 -0500 Subject: [PATCH 26/27] Fix lint --- R/external-deps.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/external-deps.R b/R/external-deps.R index 4fe9f3364..93ad2fa33 100644 --- a/R/external-deps.R +++ b/R/external-deps.R @@ -81,7 +81,7 @@ cached_dependency <- function(name, version, files) { check_integrity(cache_path, file$integrity) } } - dep_files <- dir(cache_dir) + dep_files <- path_rel(dir_ls(cache_dir), cache_dir) htmltools::htmlDependency( name = name, From fd71d1a95323c30d7646b22f7c5d2d74ae4c6d7b Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Tue, 28 May 2024 08:33:37 -0500 Subject: [PATCH 27/27] Force consistent sort --- R/theme.R | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/R/theme.R b/R/theme.R index 42cbe5e18..b08d8ecca 100644 --- a/R/theme.R +++ b/R/theme.R @@ -17,7 +17,8 @@ build_bslib <- function(pkg = ".", call = caller_env()) { changed <- all_deps[!diff | is.na(diff)] if (length(changed) > 0) { - purrr::walk(changed, function(dst) { + withr::local_locale(LC_COLLATE = "C") + purrr::walk(sort(changed), function(dst) { cli::cli_inform("Updating {dst_path(path_rel(dst, pkg$dst_path))}") }) }