Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add version switcher to the site #575

Merged
merged 11 commits into from
Jun 12, 2024
12 changes: 6 additions & 6 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,9 @@ It should be saved as the `APP_PUSH_TEST_PAT`

The [documentation site](https://appsilon.github.io/rhino/)
is built and deployed automatically by our [`pkgdown.yml`](workflows/pkgdown.yml) workflow.
This workflow is triggered when a
[release](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository)
is published, or a pre-release is changed to a release.
It is also possible to manually run it for a selected tag/branch
from the [Actions](https://github.com/Appsilon/rhino/actions/workflows/pkgdown.yml) tab.
It is triggered on each push to the `main` branch.
It runs the `pkgdown/build.R` script which builds the documentation
for all Rhino versions listed in `pkgdown/versions.yml`.

## Release process

Expand Down Expand Up @@ -82,7 +80,9 @@ for the `main` branch should be green).
Do not add a link to GitHub releases yet - the link won't work and will fail CRAN checks.
* Edit the list of changes to make it useful and understandable for our users.
See [keep a changelog](https://keepachangelog.com/) for some guidelines.
5. Submit the changes in a pull request titled "Release X.Y.Z".
5. Update `pkgdown/versions.yml`.
* Add a new version corresponding to the release you are preparing.
6. Submit the changes in a pull request titled "Release X.Y.Z".
Get it approved and merged.

### Submitting to CRAN
Expand Down
38 changes: 20 additions & 18 deletions .github/workflows/pkgdown.yml
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:
kamilzyla marked this conversation as resolved.
Show resolved Hide resolved
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
Expand All @@ -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 "$GITHUB_ACTOR@users.noreply.github.com"
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
111 changes: 111 additions & 0 deletions pkgdown/build.R
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)")
kamilzyla marked this conversation as resolved.
Show resolved Hide resolved
}
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)]
)
}
}
69 changes: 52 additions & 17 deletions pkgdown/extra.css
Original file line number Diff line number Diff line change
@@ -1,36 +1,50 @@
:root {
--primary-color: #7B7CD2 ;
--primary-color: #7b7cd2;
}

.navbar {
background-color: var(--primary-color) !important;
--bs-primary-rgb: 123, 124, 210;
}

#navbar > ul.navbar-nav > li.nav-item a:hover {
background-color: var(--primary-color) !important;
.navbar a.dropdown-item:hover {
background-color: var(--primary-color);
}

#navbar > ul.navbar-nav > li.nav-item > a {
color: rgba(255, 255, 255, 0.8);
.navbar .navbar-nav .nav-item.active > .nav-link {
color: #fff;
background-color: var(--primary-color);
}

.navbar-light .navbar-nav .active > .nav-link {
background-color: var(--primary-color) !important;
color: #fff !important;
.navbar .navbar-nav .nav-item > .nav-link {
color: rgba(255, 255, 255, 0.8);

&:hover {
background-color: var(--primary-color);
color: #fff;
}
}

.navbar-brand {
color: #fff !important;
}
--bs-navbar-brand-color: #fff;

nav .text-muted {
color: #d8d8d8 !important;
&:hover {
--bs-navbar-brand-hover-color: rgba(255, 255, 255, 0.8);
}
}

a {
color: var(--primary-color);
}

a.nav-link,
TymekDev marked this conversation as resolved.
Show resolved Hide resolved
.home {
color: hsl(0, 0%, 80%);

&:hover {
color: hsl(0, 0%, 100%);
}
}

a:hover {
color: #2c2b2b;
}
Expand All @@ -41,14 +55,34 @@ button.btn.btn-primary.btn-copy-ex {
}

.home {
display: none;
left: 0px;
position: absolute;
padding: 8px 30px;
color: rgba(255,255,255,0.55);

@media (min-width: 1250px) {
display: initial;
}
}

.home:hover {
color: rgba(255,255,255,0.9);
#version-switcher {
margin-inline-start: 0.5rem;
margin-inline-end: auto;

@media (min-width: 992px) {
margin-inline-end: 2rem;
}

& > a {
background-color: hsl(239.3, 40.2%, 55.3%);
color: rgba(255, 255, 255, 0.8);
padding: 0.25rem 1rem;
border-radius: 1rem;

&:hover {
color: white;
}
}
}

summary:has(h3#past) {
Expand All @@ -58,6 +92,7 @@ summary:has(h3#past) {

&::marker,
&::-webkit-details-marker {
font-size: calc(1.3rem + .6vw); /* an equivalent of Bootstrap's h3 that's within the summary */
/* an equivalent of Bootstrap's h3 that's within the summary */
font-size: calc(1.3rem + 0.6vw);
}
}
71 changes: 71 additions & 0 deletions pkgdown/navbar_template.html
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}}
Loading
Loading