From 011ffcb0351093bda19e83401e066820fc120115 Mon Sep 17 00:00:00 2001 From: Daniel McCloy Date: Wed, 24 May 2023 15:50:01 -0700 Subject: [PATCH 1/6] add version warning banner --- docs/conf.py | 1 + src/pydata_sphinx_theme/__init__.py | 1 + .../assets/scripts/pydata-sphinx-theme.js | 68 +++++++++++++++++++ .../assets/styles/sections/_announcement.scss | 16 ++++- .../theme/pydata_sphinx_theme/theme.conf | 1 + 5 files changed, 85 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index d75c7d4e8..7115136f1 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -167,6 +167,7 @@ "navbar_align": "left", # [left, content, right] For testing that the navbar items align properly "navbar_center": ["version-switcher", "navbar-nav"], "announcement": "https://raw.githubusercontent.com/pydata/pydata-sphinx-theme/main/docs/_templates/custom-template.html", + "show_version_warning_banner": True, # "show_nav_level": 2, # "navbar_start": ["navbar-logo"], # "navbar_end": ["theme-switcher", "navbar-icon-links"], diff --git a/src/pydata_sphinx_theme/__init__.py b/src/pydata_sphinx_theme/__init__.py index 0c9c97741..1418fec6e 100644 --- a/src/pydata_sphinx_theme/__init__.py +++ b/src/pydata_sphinx_theme/__init__.py @@ -273,6 +273,7 @@ def _remove_empty_templates(tname): js = f""" DOCUMENTATION_OPTIONS.theme_switcher_json_url = '{json_url}'; DOCUMENTATION_OPTIONS.theme_switcher_version_match = '{version_match}'; + DOCUMENTATION_OPTIONS.show_version_warning_banner = {str(context["theme_show_version_warning_banner"]).lower()}; """ app.add_js_file(None, body=js) diff --git a/src/pydata_sphinx_theme/assets/scripts/pydata-sphinx-theme.js b/src/pydata_sphinx_theme/assets/scripts/pydata-sphinx-theme.js index d297ceb14..1f5460958 100644 --- a/src/pydata_sphinx_theme/assets/scripts/pydata-sphinx-theme.js +++ b/src/pydata_sphinx_theme/assets/scripts/pydata-sphinx-theme.js @@ -395,6 +395,71 @@ function initRTDObserver() { observer.observe(document.body, config); } +/******************************************************************************* + * Warning banner when viewing non-stable version of the docs. + */ +function showVersionWarningBanner() { + // adapted 2023-05 from https://mne.tools/versionwarning.js, which was + // originally adapted 2020-05 from https://scikit-learn.org/versionwarning.js + const version = DOCUMENTATION_OPTIONS.VERSION; + // figure out what latest stable version is + var stableRelease = Infinity; + const menu = document.querySelector(".version-switcher__menu"); + // fail early if not using the version selector + if (menu == null) { + return; + } + // from the menu, get the version number of the stable release + const releases = Array.from(menu.children); + const stableReleaseFromMenu = releases.filter( + ver => ver.getAttribute("data-version") == "stable" + )[0] + // hack to make sure the menu has been populated before we parse it + if (typeof stableReleaseFromMenu == "undefined") { + setTimeout(showVersionWarningBanner, 250); + return; + } + // convert version string to number (the .split is in case the version + // string is something like "1.3 (stable)") + stableRelease = parseFloat( + stableReleaseFromMenu.getAttribute("data-version-name").split(" ")[0] + ); + // now construct the warning banner + if (version !== "stable") { + var outer = document.createElement("div"); + const middle = document.createElement("div"); + const inner = document.createElement("div"); + const bold = document.createElement("strong"); + + // Someday maybe we can add a button that pulls its target URL from + // the relevant "stable" entry of the version switcher menu... + // const button = document.createElement("a"); + // button.href = `https://mne.tools/stable/${filePath}`; + // button.innerText = "Switch to latest stable version"; + // button.classList = "sd-btn sd-btn-danger sd-shadow-sm sd-text-wrap font-weight-bold ms-3 my-3 align-baseline"; + + // these classes exist since pydata-sphinx-theme v0.10.0 + outer.classList = "bd-header-version-warning container-fluid"; + middle.classList = "bd-header-announcement__content"; + inner.classList = "sidebar-message"; + outer.appendChild(middle); + middle.appendChild(inner); + // for less-than comparison: "dev" → NaN → false (which is what we want) + inner.innerText = "This is documentation for "; + if (parseFloat(version) < stableRelease) { + inner.innerText += "an " + bold.innerText = `old version (${version})`; + } else { + inner.innerText += "the " + bold.innerText = "unstable development version"; + } + inner.appendChild(bold); + inner.appendChild(document.createTextNode(`. Use the version switcher dropdown to select the stable version.`)) + // inner.appendChild(button); + document.body.prepend(outer); + } +} + /******************************************************************************* * Call functions after document loading. */ @@ -404,3 +469,6 @@ documentReady(scrollToActive); documentReady(addTOCInteractivity); documentReady(setupSearchButtons); documentReady(initRTDObserver); +if (DOCUMENTATION_OPTIONS.show_version_warning_banner) { + documentReady(showVersionWarningBanner); +} diff --git a/src/pydata_sphinx_theme/assets/styles/sections/_announcement.scss b/src/pydata_sphinx_theme/assets/styles/sections/_announcement.scss index b2287d6aa..963a00b48 100644 --- a/src/pydata_sphinx_theme/assets/styles/sections/_announcement.scss +++ b/src/pydata_sphinx_theme/assets/styles/sections/_announcement.scss @@ -1,4 +1,5 @@ -.bd-header-announcement { +.bd-header-announcement, +.bd-header-version-warning { min-height: 3rem; width: 100%; display: flex; @@ -25,7 +26,6 @@ height: 100%; left: 0; top: 0; - background-color: var(--pst-color-info); opacity: 0.2; content: ""; z-index: -1; // So it doesn't hover over the content @@ -35,3 +35,15 @@ display: none; } } + +.bd-header-announcement { + &:after { + background-color: var(--pst-color-info); + } +} + +.bd-header-version-warning { + &:after { + background-color: var(--pst-color-danger); + } +} \ No newline at end of file diff --git a/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/theme.conf b/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/theme.conf index b2b6cf024..413d49bcd 100644 --- a/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/theme.conf +++ b/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/theme.conf @@ -50,6 +50,7 @@ footer_start = copyright.html, sphinx-version.html footer_end = theme-version.html secondary_sidebar_items = page-toc.html, edit-this-page.html, sourcelink.html announcement = +show_version_warning_banner = False # DEPRECATE after 0.14 footer_items = From c0ba7380315f055d82baf211b5bda729a4e0f092 Mon Sep 17 00:00:00 2001 From: Daniel McCloy Date: Wed, 24 May 2023 16:52:51 -0700 Subject: [PATCH 2/6] do proper version string comparison instead of casting to float --- package-lock.json | 13 ++++++++++++- package.json | 3 ++- .../assets/scripts/pydata-sphinx-theme.js | 13 ++++++------- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index 89c5c3906..474c42cd0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,8 @@ "dependencies": { "@fortawesome/fontawesome-free": "6.1.2", "@popperjs/core": "^2.11.6", - "bootstrap": "^5.2.2" + "bootstrap": "^5.2.2", + "compare-versions": "^5.0.3" }, "devDependencies": { "axe-core": "^4.6.3", @@ -993,6 +994,11 @@ "node": ">= 6" } }, + "node_modules/compare-versions": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-5.0.3.tgz", + "integrity": "sha512-4UZlZP8Z99MGEY+Ovg/uJxJuvoXuN4M6B3hKaiackiHrgzQFEe3diJi1mf1PNHbFujM7FvLrK2bpgIaImbtZ1A==" + }, "node_modules/copy-webpack-plugin": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", @@ -5293,6 +5299,11 @@ "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", "dev": true }, + "compare-versions": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-5.0.3.tgz", + "integrity": "sha512-4UZlZP8Z99MGEY+Ovg/uJxJuvoXuN4M6B3hKaiackiHrgzQFEe3diJi1mf1PNHbFujM7FvLrK2bpgIaImbtZ1A==" + }, "copy-webpack-plugin": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", diff --git a/package.json b/package.json index f615c4a97..f992c9a7a 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "dependencies": { "@fortawesome/fontawesome-free": "6.1.2", "@popperjs/core": "^2.11.6", - "bootstrap": "^5.2.2" + "bootstrap": "^5.2.2", + "compare-versions": "^5.0.3" } } diff --git a/src/pydata_sphinx_theme/assets/scripts/pydata-sphinx-theme.js b/src/pydata_sphinx_theme/assets/scripts/pydata-sphinx-theme.js index 1f5460958..e3e378349 100644 --- a/src/pydata_sphinx_theme/assets/scripts/pydata-sphinx-theme.js +++ b/src/pydata_sphinx_theme/assets/scripts/pydata-sphinx-theme.js @@ -1,5 +1,6 @@ // Define the custom behavior of the page import { documentReady } from "./mixin"; +import { compare } from "compare-versions"; import "../styles/pydata-sphinx-theme.scss"; @@ -419,11 +420,9 @@ function showVersionWarningBanner() { setTimeout(showVersionWarningBanner, 250); return; } - // convert version string to number (the .split is in case the version + // isolate version string (the .split is in case the version // string is something like "1.3 (stable)") - stableRelease = parseFloat( - stableReleaseFromMenu.getAttribute("data-version-name").split(" ")[0] - ); + stableRelease = stableReleaseFromMenu.getAttribute("data-version-name").split(" ")[0]; // now construct the warning banner if (version !== "stable") { var outer = document.createElement("div"); @@ -432,9 +431,9 @@ function showVersionWarningBanner() { const bold = document.createElement("strong"); // Someday maybe we can add a button that pulls its target URL from - // the relevant "stable" entry of the version switcher menu... + // the relevant "stable" entry of the version switcher menu: // const button = document.createElement("a"); - // button.href = `https://mne.tools/stable/${filePath}`; + // button.href = `https://whatever/stable/${filePath}`; // button.innerText = "Switch to latest stable version"; // button.classList = "sd-btn sd-btn-danger sd-shadow-sm sd-text-wrap font-weight-bold ms-3 my-3 align-baseline"; @@ -446,7 +445,7 @@ function showVersionWarningBanner() { middle.appendChild(inner); // for less-than comparison: "dev" → NaN → false (which is what we want) inner.innerText = "This is documentation for "; - if (parseFloat(version) < stableRelease) { + if (compare(version, stableRelease, "<")) { inner.innerText += "an " bold.innerText = `old version (${version})`; } else { From 8dc62c869b75bab530ab676966c3c2caa4b2b785 Mon Sep 17 00:00:00 2001 From: Daniel McCloy Date: Wed, 24 May 2023 16:53:30 -0700 Subject: [PATCH 3/6] add documentation --- docs/user_guide/announcements.rst | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/docs/user_guide/announcements.rst b/docs/user_guide/announcements.rst index 9bb23e273..7218caa5d 100644 --- a/docs/user_guide/announcements.rst +++ b/docs/user_guide/announcements.rst @@ -38,3 +38,28 @@ For example, the following configuration tells the theme to load the ``custom-te ... "announcement": "https://github.com/pydata/pydata-sphinx-theme/raw/main/docs/_templates/custom-template.html", } + +Version warning banners +----------------------- + +In addition to the general-purpose announcement banner, the theme includes a built-in banner to warn users when they are viewing versions of your docs other than the latest stable version. To use this feature, add the following to your ``conf.py``: + +.. code-block:: python + + html_theme_options = { + ... + "show_version_warning_banner": True, + } + +.. warning:: + + This functionality relies on the :ref:`version switcher ` to determine the version number of the latest stable release. + *It will only work* if your version switcher ``.json`` has an entry with the version ``"stable"`` and a name that begins with a version string, for example: + + .. code-block:: json + + { + "name": "9.9.9 (current)", + "version": "stable", + "url": "https://anything" + } From 7d14a6607002c22e3fb393aa79954b965d7d995d Mon Sep 17 00:00:00 2001 From: Daniel McCloy Date: Wed, 24 May 2023 17:19:18 -0700 Subject: [PATCH 4/6] add unsaved changes :facepalm: --- .../assets/scripts/pydata-sphinx-theme.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pydata_sphinx_theme/assets/scripts/pydata-sphinx-theme.js b/src/pydata_sphinx_theme/assets/scripts/pydata-sphinx-theme.js index e3e378349..57f735885 100644 --- a/src/pydata_sphinx_theme/assets/scripts/pydata-sphinx-theme.js +++ b/src/pydata_sphinx_theme/assets/scripts/pydata-sphinx-theme.js @@ -445,12 +445,12 @@ function showVersionWarningBanner() { middle.appendChild(inner); // for less-than comparison: "dev" → NaN → false (which is what we want) inner.innerText = "This is documentation for "; - if (compare(version, stableRelease, "<")) { - inner.innerText += "an " - bold.innerText = `old version (${version})`; - } else { + if (version.includes("dev") || compare(version, stableRelease, ">")) { inner.innerText += "the " bold.innerText = "unstable development version"; + } else { + inner.innerText += "an " + bold.innerText = `old version (${version})`; } inner.appendChild(bold); inner.appendChild(document.createTextNode(`. Use the version switcher dropdown to select the stable version.`)) From 87a34ceb5d5cc4f1a61bd11ea81d9856fa2778f8 Mon Sep 17 00:00:00 2001 From: Daniel McCloy Date: Wed, 24 May 2023 17:21:19 -0700 Subject: [PATCH 5/6] run precommit :facepalm: --- .../assets/scripts/pydata-sphinx-theme.js | 120 +++++++++--------- .../assets/styles/sections/_announcement.scss | 2 +- 2 files changed, 64 insertions(+), 58 deletions(-) diff --git a/src/pydata_sphinx_theme/assets/scripts/pydata-sphinx-theme.js b/src/pydata_sphinx_theme/assets/scripts/pydata-sphinx-theme.js index 57f735885..4996f5abe 100644 --- a/src/pydata_sphinx_theme/assets/scripts/pydata-sphinx-theme.js +++ b/src/pydata_sphinx_theme/assets/scripts/pydata-sphinx-theme.js @@ -400,63 +400,69 @@ function initRTDObserver() { * Warning banner when viewing non-stable version of the docs. */ function showVersionWarningBanner() { - // adapted 2023-05 from https://mne.tools/versionwarning.js, which was - // originally adapted 2020-05 from https://scikit-learn.org/versionwarning.js - const version = DOCUMENTATION_OPTIONS.VERSION; - // figure out what latest stable version is - var stableRelease = Infinity; - const menu = document.querySelector(".version-switcher__menu"); - // fail early if not using the version selector - if (menu == null) { - return; - } - // from the menu, get the version number of the stable release - const releases = Array.from(menu.children); - const stableReleaseFromMenu = releases.filter( - ver => ver.getAttribute("data-version") == "stable" - )[0] - // hack to make sure the menu has been populated before we parse it - if (typeof stableReleaseFromMenu == "undefined") { - setTimeout(showVersionWarningBanner, 250); - return; - } - // isolate version string (the .split is in case the version - // string is something like "1.3 (stable)") - stableRelease = stableReleaseFromMenu.getAttribute("data-version-name").split(" ")[0]; - // now construct the warning banner - if (version !== "stable") { - var outer = document.createElement("div"); - const middle = document.createElement("div"); - const inner = document.createElement("div"); - const bold = document.createElement("strong"); - - // Someday maybe we can add a button that pulls its target URL from - // the relevant "stable" entry of the version switcher menu: - // const button = document.createElement("a"); - // button.href = `https://whatever/stable/${filePath}`; - // button.innerText = "Switch to latest stable version"; - // button.classList = "sd-btn sd-btn-danger sd-shadow-sm sd-text-wrap font-weight-bold ms-3 my-3 align-baseline"; - - // these classes exist since pydata-sphinx-theme v0.10.0 - outer.classList = "bd-header-version-warning container-fluid"; - middle.classList = "bd-header-announcement__content"; - inner.classList = "sidebar-message"; - outer.appendChild(middle); - middle.appendChild(inner); - // for less-than comparison: "dev" → NaN → false (which is what we want) - inner.innerText = "This is documentation for "; - if (version.includes("dev") || compare(version, stableRelease, ">")) { - inner.innerText += "the " - bold.innerText = "unstable development version"; - } else { - inner.innerText += "an " - bold.innerText = `old version (${version})`; - } - inner.appendChild(bold); - inner.appendChild(document.createTextNode(`. Use the version switcher dropdown to select the stable version.`)) - // inner.appendChild(button); - document.body.prepend(outer); + // adapted 2023-05 from https://mne.tools/versionwarning.js, which was + // originally adapted 2020-05 from https://scikit-learn.org/versionwarning.js + const version = DOCUMENTATION_OPTIONS.VERSION; + // figure out what latest stable version is + var stableRelease = Infinity; + const menu = document.querySelector(".version-switcher__menu"); + // fail early if not using the version selector + if (menu == null) { + return; + } + // from the menu, get the version number of the stable release + const releases = Array.from(menu.children); + const stableReleaseFromMenu = releases.filter( + (ver) => ver.getAttribute("data-version") == "stable" + )[0]; + // hack to make sure the menu has been populated before we parse it + if (typeof stableReleaseFromMenu == "undefined") { + setTimeout(showVersionWarningBanner, 250); + return; + } + // isolate version string (the .split is in case the version + // string is something like "1.3 (stable)") + stableRelease = stableReleaseFromMenu + .getAttribute("data-version-name") + .split(" ")[0]; + // now construct the warning banner + if (version !== "stable") { + var outer = document.createElement("div"); + const middle = document.createElement("div"); + const inner = document.createElement("div"); + const bold = document.createElement("strong"); + + // Someday maybe we can add a button that pulls its target URL from + // the relevant "stable" entry of the version switcher menu: + // const button = document.createElement("a"); + // button.href = `https://whatever/stable/${filePath}`; + // button.innerText = "Switch to latest stable version"; + // button.classList = "sd-btn sd-btn-danger sd-shadow-sm sd-text-wrap font-weight-bold ms-3 my-3 align-baseline"; + + // these classes exist since pydata-sphinx-theme v0.10.0 + outer.classList = "bd-header-version-warning container-fluid"; + middle.classList = "bd-header-announcement__content"; + inner.classList = "sidebar-message"; + outer.appendChild(middle); + middle.appendChild(inner); + // for less-than comparison: "dev" → NaN → false (which is what we want) + inner.innerText = "This is documentation for "; + if (version.includes("dev") || compare(version, stableRelease, ">")) { + inner.innerText += "the "; + bold.innerText = "unstable development version"; + } else { + inner.innerText += "an "; + bold.innerText = `old version (${version})`; } + inner.appendChild(bold); + inner.appendChild( + document.createTextNode( + `. Use the version switcher dropdown to select the stable version.` + ) + ); + // inner.appendChild(button); + document.body.prepend(outer); + } } /******************************************************************************* @@ -469,5 +475,5 @@ documentReady(addTOCInteractivity); documentReady(setupSearchButtons); documentReady(initRTDObserver); if (DOCUMENTATION_OPTIONS.show_version_warning_banner) { - documentReady(showVersionWarningBanner); + documentReady(showVersionWarningBanner); } diff --git a/src/pydata_sphinx_theme/assets/styles/sections/_announcement.scss b/src/pydata_sphinx_theme/assets/styles/sections/_announcement.scss index 963a00b48..c4eb88a7b 100644 --- a/src/pydata_sphinx_theme/assets/styles/sections/_announcement.scss +++ b/src/pydata_sphinx_theme/assets/styles/sections/_announcement.scss @@ -46,4 +46,4 @@ &:after { background-color: var(--pst-color-danger); } -} \ No newline at end of file +} From 657689efa9deecec025eb1d3a97447fa541b7356 Mon Sep 17 00:00:00 2001 From: Daniel McCloy Date: Wed, 24 May 2023 17:27:33 -0700 Subject: [PATCH 6/6] fix crossref --- docs/user_guide/announcements.rst | 2 +- docs/user_guide/version-dropdown.rst | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/user_guide/announcements.rst b/docs/user_guide/announcements.rst index 7218caa5d..1433d875a 100644 --- a/docs/user_guide/announcements.rst +++ b/docs/user_guide/announcements.rst @@ -53,7 +53,7 @@ In addition to the general-purpose announcement banner, the theme includes a bui .. warning:: - This functionality relies on the :ref:`version switcher ` to determine the version number of the latest stable release. + This functionality relies on the :ref:`version switcher ` to determine the version number of the latest stable release. *It will only work* if your version switcher ``.json`` has an entry with the version ``"stable"`` and a name that begins with a version string, for example: .. code-block:: json diff --git a/docs/user_guide/version-dropdown.rst b/docs/user_guide/version-dropdown.rst index 8a9b17cef..a243074d9 100644 --- a/docs/user_guide/version-dropdown.rst +++ b/docs/user_guide/version-dropdown.rst @@ -1,3 +1,5 @@ +.. _version-dropdowns: + Version switcher dropdowns ==========================