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

Consider readthedocs style handling of multiple versions #1373

Open
hadley opened this issue Jul 31, 2020 · 4 comments
Open

Consider readthedocs style handling of multiple versions #1373

hadley opened this issue Jul 31, 2020 · 4 comments
Labels
deploy ✈️ feature a feature request or enhancement

Comments

@hadley
Copy link
Member

hadley commented Jul 31, 2020

(with a few tweaks for our needs)

  • Latest continues to live in top-level directory
  • Tagged releases built in /version/... (also need to be able to run locally in case automation fails or otherwise needs update)
  • Need to somehow record all versions in central location
  • Default template gets javascript popup for switching versions
  • Need to consider no-index or canonical strategy to ensure that google doesn't find old version of docs.
  • Optional javascript that displays "this isn't the latest version" banner somewhere on page
@hadley
Copy link
Member Author

hadley commented Aug 1, 2020

Imagined url structure:

  • /: "stable"/"latest" version
  • /devel: development version
  • /1.0.0/ etc: old versions

Any "versioned" (e.g. devel or tagged release) site would set the canonical url to the root.

How would github builds work? Regular builds go in devel. Tagged builds make two versions — one is versioned in 2.0.0 and the other is unversioned in the root. The versioned site exists mostly for future use — we'd avoid linking to it, but we do want to build at release time to avoid having to rebuild an old version when we release the next version.

Would have ndjson file in root directory that's updated by versioned release — release just appends new version to end (so we can use union strategy to avoid merge conflicts)

@hadley hadley added feature a feature request or enhancement front end 🌷 General HTML, CSS, and JS issues labels Aug 20, 2020
@krlmlr
Copy link
Member

krlmlr commented Aug 21, 2020

  • Do we really need tagged builds to make two versions? Creating a tag triggers a separate CI run.
  • Can we do the same for pull requests? Closing a pull request would trigger an action to delete the version, we could also support a "sync" feature that purges versions if really necessary.
  • I'd love to see a "permalink" feature that links to the stable version of the current page.
  • Can we make good use of symlinks in the gh-pages branch?

@hadley
Copy link
Member Author

hadley commented Jul 12, 2023

@TymekDev
Copy link

Hi!

Last week I worked on implementing Appsilon/rhino#530. As a result I created a build script which creates a site with multiple versions of documentation and a switcher. You can view a demo at https://tymekdev.github.io/rhino.

This endeavor gave me a good overview of the issue and how to approach it. I will describe how the build script works and its shortcomings. I will also describe what decisions I think would have to be made before implementing this feature directly in pkgdown.

Hopefully, this gives a good overview on the matter. Let me know what do you think!

Best,
Tymek

Build Script

Goals

  • Keep the development version of documentation up to date
  • Default to a specific version (namely, latest CRAN release)
  • Allow for custom URL paths

Description

A version is tied to a git ref (~revision), and defined by:

  • a label to be shown in the switcher for a given version
  • a ref checked out to retrieve code of a given version
  • a href used for a URL path of a given version

Note

I considered using historical versions from CRAN, however I learned that these might not have vignettes included.

Key components to this solution is a build script and a navbar template template (no, I did not stutter 🙃).

Usage

source("pkgdown/build.R")

build_versioned(
  repo = ".",
  versions = list(
    list(
      ref = "refs/remotes/origin/main",
      href = "/dev",
      label = TRUE # takes version from DESCRIPTION and appends "(dev)" to it
    ),
    list(
      ref = "refs/tags/v1.7.0",
      href = "/",
      label = "1.7.0"
    ),
    list(
      ref = "refs/tags/v1.6.0"
      href = "/v1.6.0",
      label = "1.6.0",
    )
  ),
  url = "https://appsilon.github.io/rhino",
  destination = "docs"
)

Important

Why not revision instead of ref?
Using refs makes this work with GitHub checkout action. The repository is fetched there in a specific way.

Step by Step

  1. Copy repository into a <temp_repo> temporary directory and detach HEAD1
  2. Read the navbar template template
  3. Starting with a version with href = "/"2
    1. Create a git worktree in a <build_dir> temporary directory with version's ref checked out
    2. Create a navbar template. Populate the switcher with a current version and other dropdown options
    3. Write the navbar template to <build_dir>/pkgdown/templates/navbar.html
    4. Copy <temp_repo>/pkgdown/extra.css3 to <build_dir>/pkgdown/extra.css
    5. Run pkgdown::build_site_github_pages with two overrides: both url and destination have version's href appended

Result

Running the code presented above would create a directory with a following structure:

docs         <- version from v1.7.0 tag
├── dev      <- version from main branch
│  └── ...
├── v1.6.0   <- version from v1.6.0 tag
│  └── ...
└── ...

This way any static file server will get the job done and get the paths right. As you can see it working on GitHub pages.

Issues and Caveats

  1. Every version has its own sitemap.xml
  2. Every version has separate assets (Bootstrap, favicons, ...)
  3. All versions are indexed by search engines
  4. None of the versions has canonical URLs set up
  5. "Source" link in vignettes and function reference is hardcoded to HEAD (instead of a respective version)
  6. Switching a version redirects to index (instead of staying on the same subpage in target version if it exists)

I am quite sure that all of these could be addressed. However, this would be a significant effort - comparable if not bigger than adding a proper support to pkgdown itself.

Additionally, 6. can be treated as an extra. See how an old Bootstrap versions have a banner that just switches to an index page of the newest version.

Extending pkgdown

Below you can find the burning questions that, in my opinion, would have to be answered before implementing this feature.

Decide how versions are defined

There is quite a lot of room for automation here. A couple ideas:

  • List versions from historical CRAN releases
  • Search git tags by a pattern
  • Give a full control to the user

An MVP could use explicitly listed git revisions (as in the build script above).

Decide how to approach canonical URLs, indexing, and sitemap.xml

This gets tricky with adding a canonical URL to an older versions as content might get removed. There would have to be a detection mechanism to see if something disappeared in a later version (what is a "later" version, though?).

However, implementing this detection mechanism would make the following possible:

An MVP could simply index only the "stable" version (with href = "/"). The switcher could just land the user on an index page of a given version.

What to override in older versions

URL is a must. Styling would not be necessary4. Perhaps an equivalent of template.includes that's applied to every version?

An MVP could just override the URL.

Footnotes

  1. We use git worktrees. This avoids messing up user's repository. Detaching HEAD prevents complaints about a revision being already checked out.

  2. Otherwise, if we created a version in a subdirectory first, pkgdown would complain about non-empty directory.

  3. The switcher is styled there. We also get consistent styling.

  4. The script had to inject a template. If pkgdown is patched with a new template with a switcher, then using overrides to inject the data should suffice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
deploy ✈️ feature a feature request or enhancement
Projects
None yet
Development

No branches or pull requests

3 participants