-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #575 from Appsilon/530-versioned-pkgdown
Add version switcher to the site
- Loading branch information
Showing
6 changed files
with
290 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,19 @@ | ||
name: pkgdown | ||
on: | ||
# Run when a release is published, or a pre-release is changed to a release. Reference: | ||
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#release | ||
# https://docs.github.com/en/webhooks/webhook-events-and-payloads#release | ||
release: | ||
types: [released] | ||
# It is also possible to manually trigger this workflow for a selected tag/branch | ||
# from the "Actions" tab on GitHub. | ||
workflow_dispatch: | ||
push: | ||
branches: [main] | ||
permissions: | ||
contents: write | ||
jobs: | ||
main: | ||
pkgdown: | ||
name: Build and publish website | ||
runs-on: ubuntu-latest | ||
timeout-minutes: 30 | ||
steps: | ||
- name: Checkout repository | ||
uses: actions/checkout@v3 | ||
uses: actions/checkout@v4 | ||
with: | ||
fetch-depth: 0 | ||
|
||
- name: Install R | ||
uses: r-lib/actions/setup-r@v2 | ||
|
@@ -29,13 +25,19 @@ jobs: | |
with: | ||
extra-packages: any::pkgdown, local::. | ||
|
||
- name: Configure git | ||
- name: Build site | ||
shell: Rscript {0} | ||
run: | | ||
git config user.name "$GITHUB_ACTOR" | ||
git config user.email "[email protected]" | ||
source("pkgdown/build.R") | ||
build_versioned( | ||
repo = ".", | ||
versions = yaml::read_yaml("pkgdown/versions.yml"), | ||
root_url = "https://appsilon.github.io/rhino", | ||
destination = "docs" | ||
) | ||
- name: Build and deploy site | ||
shell: Rscript {0} | ||
run: pkgdown::deploy_to_branch(branch = "bot/github-pages") | ||
env: | ||
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} | ||
- name: Deploy | ||
uses: JamesIves/github-pages-deploy-action@v4 | ||
with: | ||
folder: docs | ||
branch: bot/github-pages |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
#' @param repo The path to the git repository to build. | ||
#' @param versions A list of lists. Each sublist should contain the following keys: | ||
#' - `git_ref`: The git ref to build. | ||
#' - `url`: The URL path for the version. | ||
#' - `label`: The label to display in the navbar. To use the version from DESCRIPTION provide `TRUE`. | ||
#' Additonally, exactly one version should have `url` set to "/". | ||
#' @param root_url The root URL for all versions of the website. | ||
#' @param destination The destination directory for the built website. | ||
build_versioned <- function(repo, versions, root_url, destination) { | ||
validate_versions(versions) | ||
|
||
# Prepare a repo for building | ||
temp_repo <- fs::dir_copy(repo, fs::file_temp("versioned-build-repo-")) | ||
on.exit(fs::dir_delete(temp_repo)) | ||
# NOTE: detach to avoid git worktree complaining about the current ref being checked out | ||
system2("git", c("-C", temp_repo, "switch", "--detach", "@")) | ||
build_version <- build_version_factory(temp_repo, versions, root_url, destination) | ||
|
||
# NOTE: building the root URL first, so pkgdown doesn't complain about a non-empty destination directory | ||
root_index <- purrr::detect_index(versions, \(x) isTRUE(x$url == "/")) | ||
purrr::walk(c(versions[root_index], versions[-root_index]), build_version) | ||
} | ||
|
||
validate_versions <- function(versions) { | ||
expected_names <- c("git_ref", "url", "label") | ||
n_root <- 0 | ||
purrr::walk(versions, function(version) { | ||
diff <- setdiff(expected_names, names(version)) | ||
if (length(diff) > 0) { | ||
stop("A version is missing the following keys: ", paste(diff, collapse = ", ")) | ||
} | ||
if (isTRUE(version$url == "/")) { | ||
n_root <<- n_root + 1 | ||
} | ||
}) | ||
if (n_root != 1) { | ||
stop("Exactly one version should have url set to '/'") | ||
} | ||
} | ||
|
||
build_version_factory <- function(repo, versions, root_url, destination) { | ||
navbar_template <- navbar_template_factory(versions, root_url) | ||
destination <- fs::path_abs(destination) | ||
extra_css_path <- fs::path_join(c(repo, "pkgdown", "extra.css")) | ||
|
||
function(version) { | ||
# Prepare a worktree for building | ||
build_dir <- fs::file_temp("versioned-build-worktree-") | ||
on.exit(system2("git", c("-C", repo, "worktree", "remove", "--force", build_dir))) # NOTE: --force because we add the navbar file | ||
status <- system2("git", c("-C", repo, "worktree", "add", build_dir, version$git_ref)) | ||
if (status != 0) { | ||
stop("Failed to create a worktree for ref ", version$git_ref) | ||
} | ||
|
||
# Write the navbar template and extra.css | ||
template_dir <- fs::path_join(c(build_dir, "pkgdown", "templates")) | ||
fs::dir_create(template_dir) | ||
writeLines(navbar_template(version), fs::path_join(c(template_dir, "navbar.html"))) | ||
fs::file_copy(extra_css_path, fs::path_join(c(build_dir, "pkgdown", "extra.css")), overwrite = TRUE) | ||
|
||
# NOTE: providing an absolute path to build_site won't work: https://github.com/r-lib/pkgdown/issues/2172 | ||
withr::with_dir(build_dir, { | ||
pkgdown::build_site_github_pages( | ||
override = list( | ||
url = sub("/$", "", url_join(root_url, version$url)), | ||
navbar = list(type = "light") | ||
), | ||
dest_dir = fs::path_join(c(destination, version$url)) | ||
) | ||
}) | ||
} | ||
} | ||
|
||
url_join <- function(url, path) { | ||
paste( | ||
sub("/$", "", url), | ||
sub("^/", "", path), | ||
sep = "/" | ||
) | ||
} | ||
|
||
navbar_template_factory <- function(versions, root_url) { | ||
navbar_code <- readLines("pkgdown/navbar_template.html") | ||
index_current <- grep("___CURRENT_PLACEHOLDER___", navbar_code) | ||
index_options <- grep("___OPTIONS_PLACEHOLDER___", navbar_code) | ||
stopifnot(index_current < index_options) | ||
wrap_label <- function(label) { | ||
if (isTRUE(label)) { | ||
label <- paste(desc::desc_get_version(), "(dev)") | ||
} | ||
label | ||
} | ||
function(version) { | ||
c( | ||
navbar_code[1:(index_current - 1)], | ||
wrap_label(version$label), | ||
navbar_code[(index_current + 1):(index_options - 1)], | ||
purrr::map_chr( | ||
versions, | ||
function(ver) { | ||
sprintf( | ||
'<li><a class="dropdown-item" href="%s">%s</a></li>', | ||
url_join(root_url, ver$url), | ||
wrap_label(ver$label) | ||
) | ||
} | ||
), | ||
navbar_code[(index_options + 1):length(navbar_code)] | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
{{#navbar}} | ||
<nav | ||
class="navbar fixed-top navbar-{{{type}}} navbar-expand-lg bg-{{{bg}}}" | ||
data-bs-theme="{{{type}}}" | ||
> | ||
<div class="container"> | ||
{{#includes}}{{{before_title}}}{{/includes}} | ||
<a class="navbar-brand me-2" href="{{#site}}{{root}}{{/site}}index.html" | ||
>{{#site}}{{title}}{{/site}}</a | ||
> | ||
|
||
<div id="version-switcher" class="dropdown"> | ||
<a | ||
href="#" | ||
class="nav-link dropdown-toggle" | ||
data-bs-toggle="dropdown" | ||
role="button" | ||
aria-expanded="false" | ||
aria-haspopup="true" | ||
> | ||
___CURRENT_PLACEHOLDER___ | ||
</a> | ||
<ul class="dropdown-menu"> | ||
___OPTIONS_PLACEHOLDER___ | ||
</ul> | ||
</div> | ||
|
||
{{#includes}}{{{before_navbar}}}{{/includes}} | ||
<button | ||
class="navbar-toggler" | ||
type="button" | ||
data-bs-toggle="collapse" | ||
data-bs-target="#navbar" | ||
aria-controls="navbar" | ||
aria-expanded="false" | ||
aria-label="{{#translate}}{{toggle_nav}}{{/translate}}" | ||
> | ||
<span class="navbar-toggler-icon"></span> | ||
</button> | ||
|
||
<div id="navbar" class="collapse navbar-collapse ms-3"> | ||
{{#left}} | ||
<ul class="navbar-nav me-auto"> | ||
{{{.}}} | ||
</ul> | ||
{{/left}} | ||
|
||
<form class="form-inline my-2 my-lg-0" role="search"> | ||
<input | ||
type="search" | ||
class="form-control me-sm-2" | ||
aria-label="{{#translate}}{{toggle_nav}}{{/translate}}" | ||
name="search-input" | ||
data-search-index="{{#site}}{{root}}{{/site}}search.json" | ||
id="search-input" | ||
placeholder="{{#translate}}{{search_for}}{{/translate}}" | ||
autocomplete="off" | ||
/> | ||
</form> | ||
|
||
{{#right}} | ||
<ul class="navbar-nav"> | ||
{{{.}}} | ||
</ul> | ||
{{/right}} | ||
</div> | ||
|
||
{{#includes}}{{{after_navbar}}}{{/includes}} | ||
</div> | ||
</nav> | ||
{{/navbar}} |
Oops, something went wrong.