Skip to content

Commit

Permalink
Merge branch 'trallard/update-ci' of https://github.com/trallard/pyda…
Browse files Browse the repository at this point in the history
…ta-sphinx-theme into trallard/update-ci
  • Loading branch information
trallard committed May 23, 2024
2 parents 4a59ab5 + 996bfda commit 2f77ce1
Show file tree
Hide file tree
Showing 26 changed files with 405 additions and 295 deletions.
5 changes: 5 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,8 @@ repos:
rev: "0.7.1"
hooks:
- id: nbstripout

- repo: https://github.com/mondeja/pre-commit-po-hooks
rev: v1.7.3
hooks:
- id: remove-metadata
4 changes: 2 additions & 2 deletions docs/_static/switcher.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
"url": "https://pydata-sphinx-theme.readthedocs.io/en/latest/"
},
{
"name": "0.15.2 (stable)",
"version": "v0.15.2",
"name": "0.15.3 (stable)",
"version": "v0.15.3",
"url": "https://pydata-sphinx-theme.readthedocs.io/en/stable/",
"preferred": true
},
Expand Down
5 changes: 5 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@
togglebutton_hint = str(_("Click to expand"))
togglebutton_hint_hide = str(_("Click to collapse"))

# -- Sphinx-copybutton options ---------------------------------------------
# Exclude copy button from appearing over notebook cell numbers by using :not()
# The default copybutton selector is `div.highlight pre`
# https://github.com/executablebooks/sphinx-copybutton/blob/master/sphinx_copybutton/__init__.py#L82
copybutton_selector = ":not(.prompt) > div.highlight pre"

# -- Options for HTML output -------------------------------------------------

Expand Down
20 changes: 14 additions & 6 deletions docs/user_guide/announcements.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,20 @@ For example, the following configuration tells the theme to load the ``custom-te
Update or remove announcement banner
------------------------------------

To update or remove the announcement banner, you can change the value of
``html_theme_options["announcement"]`` in your ``conf.py`` or you can edit the
contents of the ``custom-template.html`` file directly. For example, if you have a
temporary announcement that you want to remove without rebuilding your
documentation pages, you can use an empty ``custom-template.html`` file and the
banner will be hidden.
If you set ``html_theme_options["announcement"]`` to plain text or HTML, then to
update the announcement banner you need to modify this string and rebuild your
documentation pages. To remove the announcement banner, set this value to an
empty string and rebuild your documentation pages.

If you set ``html_theme_options["announcement"]`` to a URL string (starts with
``http``), then you can edit the file at that URL to update the announcement
banner. Saving an empty file at that URL will remove the announcement banner.
That's the main advantage of using a URL--you can change the announcement banner
without rebuilding and redeploying all of your documentation pages. For example,
if you point the announcement to the URL of a file in your repo, as we do on
this documentation site (see previous section), then you can edit, save and push
your changes to just that file (empty file = remove announcement) without
rebuilding and redeploying all your docs.

.. _version-warning-banners:

Expand Down
11 changes: 11 additions & 0 deletions docs/user_guide/web-components.rst
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,17 @@ You can see it in action by hovering over the code cell below:
print("A copybutton in the top-right!")
.. admonition:: nbsphinx

If your documentation site uses both nbsphinx and Sphinx-copybutton, you
will want to add the following line to your ``conf.py`` file to prevent the
copy button from appearing on top of notebook cell numbers:

.. code-block:: python
:caption: conf.py
copybutton_selector = ":not(.prompt) > div.highlight pre"
Toggle buttons
==============

Expand Down
16 changes: 13 additions & 3 deletions src/pydata_sphinx_theme/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
from sphinx.builders.dirhtml import DirectoryHTMLBuilder
from sphinx.errors import ExtensionError

from . import edit_this_page, logo, pygment, short_link, toctree, translator, utils
from . import edit_this_page, logo, pygments, short_link, toctree, translator, utils

__version__ = "0.15.3rc1"
__version__ = "0.15.3"


def update_config(app):
Expand All @@ -26,6 +26,16 @@ def update_config(app):
theme_options = utils.get_theme_options_dict(app)
warning = partial(utils.maybe_warn, app)

# TODO: DEPRECATE after v1.0
themes = ["light", "dark"]
for theme in themes:
if style := theme_options.get(f"pygment_{theme}_style"):
theme_options[f"pygments_{theme}_style"] = style
warning(
f'The parameter "pygment_{theme}_style" was renamed to '
f'"pygments_{theme}_style" (note the "s" on "pygments").'
)

# Validate icon links
if not isinstance(theme_options.get("icon_links", []), list):
raise ExtensionError(
Expand Down Expand Up @@ -269,7 +279,7 @@ def setup(app: Sphinx) -> Dict[str, str]:
app.connect("html-page-context", update_and_remove_templates)
app.connect("html-page-context", logo.setup_logo_path)
app.connect("html-page-context", utils.set_secondary_sidebar_items)
app.connect("build-finished", pygment.overwrite_pygments_css)
app.connect("build-finished", pygments.overwrite_pygments_css)
app.connect("build-finished", logo.copy_logo_images)

# https://www.sphinx-doc.org/en/master/extdev/i18n.html#extension-internationalization-i18n-and-localization-l10n-using-i18n-api
Expand Down
165 changes: 100 additions & 65 deletions src/pydata_sphinx_theme/assets/scripts/pydata-sphinx-theme.js
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,18 @@ var setupSearchButtons = () => {
* - DOCUMENTATION_OPTIONS.theme_switcher_url
*/

/**
* path component of URL
*/
var getCurrentUrlPath = () => {
if (DOCUMENTATION_OPTIONS.BUILDER == "dirhtml") {
return DOCUMENTATION_OPTIONS.pagename == "index"
? `/`
: `${DOCUMENTATION_OPTIONS.pagename}/`;
}
return `${DOCUMENTATION_OPTIONS.pagename}.html`;
};

/**
* Check if corresponding page path exists in other version of docs
* and, if so, go there instead of the homepage of the other docs version
Expand All @@ -320,7 +332,7 @@ var setupSearchButtons = () => {
async function checkPageExistsAndRedirect(event) {
// ensure we don't follow the initial link
event.preventDefault();
let currentFilePath = `${DOCUMENTATION_OPTIONS.pagename}.html`;
const currentFilePath = getCurrentUrlPath();
let tryUrl = event.currentTarget.getAttribute("href");
let otherDocsHomepage = tryUrl.replace(currentFilePath, "");
try {
Expand Down Expand Up @@ -372,7 +384,7 @@ async function fetchVersionSwitcherJSON(url) {

// Populate the version switcher from the JSON data
function populateVersionSwitcher(data, versionSwitcherBtns) {
const currentFilePath = `${DOCUMENTATION_OPTIONS.pagename}.html`;
const currentFilePath = getCurrentUrlPath();
versionSwitcherBtns.forEach((btn) => {
// Set empty strings by default so that these attributes exist and can be used in CSS selectors
btn.dataset["activeVersionName"] = "";
Expand Down Expand Up @@ -476,21 +488,18 @@ function showVersionWarningBanner(data) {
return;
}
// now construct the warning banner
var outer = document.createElement("aside");
// TODO: add to translatable strings
outer.setAttribute("aria-label", "Version warning");
const banner = document.querySelector(".bd-header-version-warning");
const middle = document.createElement("div");
const inner = document.createElement("div");
const bold = document.createElement("strong");
const button = document.createElement("a");
// these classes exist since pydata-sphinx-theme v0.10.0
// the init class is used for animation
outer.classList = "bd-header-version-warning container-fluid init";
middle.classList = "bd-header-announcement__content";
inner.classList = "sidebar-message";
button.classList =
"btn text-wrap font-weight-bold ms-3 my-1 align-baseline pst-button-link-to-stable-version";
button.href = `${preferredURL}${DOCUMENTATION_OPTIONS.pagename}.html`;
button.href = `${preferredURL}${getCurrentUrlPath()}`;
button.innerText = "Switch to stable version";
button.onclick = checkPageExistsAndRedirect;
// add the version-dependent text
Expand All @@ -510,35 +519,12 @@ function showVersionWarningBanner(data) {
} else {
bold.innerText = `version ${version}`;
}
outer.appendChild(middle);
banner.appendChild(middle);
middle.appendChild(inner);
inner.appendChild(bold);
inner.appendChild(document.createTextNode("."));
inner.appendChild(button);
const skipLink = document.getElementById("pst-skip-link");
skipLink.after(outer);
// At least 3rem height
const autoHeight = Math.max(
outer.offsetHeight,
3 * parseFloat(getComputedStyle(document.documentElement).fontSize),
);
// Set height and vertical padding to 0 to prepare the height transition
outer.style.setProperty("height", 0);
outer.style.setProperty("padding-top", 0);
outer.style.setProperty("padding-bottom", 0);
outer.classList.remove("init");
// Set height to the computed height with a small timeout to activate the transition
setTimeout(() => {
outer.style.setProperty("height", `${autoHeight}px`);
// Wait for a bit more than 300ms (the transition duration) then remove the
// forcefully set styles and let CSS take over
setTimeout(() => {
outer.style.removeProperty("padding-top");
outer.style.removeProperty("padding-bottom");
outer.style.removeProperty("height");
outer.style.setProperty("min-height", "3rem");
}, 320);
}, 10);
banner.classList.remove("d-none");
}

/*******************************************************************************
Expand Down Expand Up @@ -572,40 +558,30 @@ function initRTDObserver() {
observer.observe(document.body, config);
}

// fetch the JSON version data (only once), then use it to populate the version
// switcher and maybe show the version warning bar
var versionSwitcherBtns = document.querySelectorAll(
".version-switcher__button",
);
const hasSwitcherMenu = versionSwitcherBtns.length > 0;
const hasVersionsJSON = DOCUMENTATION_OPTIONS.hasOwnProperty(
"theme_switcher_json_url",
);
const wantsWarningBanner = DOCUMENTATION_OPTIONS.show_version_warning_banner;

if (hasVersionsJSON && (hasSwitcherMenu || wantsWarningBanner)) {
const data = await fetchVersionSwitcherJSON(
DOCUMENTATION_OPTIONS.theme_switcher_json_url,
async function fetchAndUseVersions() {
// fetch the JSON version data (only once), then use it to populate the version
// switcher and maybe show the version warning bar
var versionSwitcherBtns = document.querySelectorAll(
".version-switcher__button",
);
// TODO: remove the `if(data)` once the `return null` is fixed within fetchVersionSwitcherJSON.
// We don't really want the switcher and warning bar to silently not work.
if (data) {
populateVersionSwitcher(data, versionSwitcherBtns);
if (wantsWarningBanner) {
showVersionWarningBanner(data);
}
}
}

/**
* Fix bug #1603
*/
function fixMoreLinksInMobileSidebar() {
const dropdown = document.querySelector(
".bd-sidebar-primary [id^=pst-nav-more-links]",
const hasSwitcherMenu = versionSwitcherBtns.length > 0;
const hasVersionsJSON = DOCUMENTATION_OPTIONS.hasOwnProperty(
"theme_switcher_json_url",
);
if (dropdown !== null) {
dropdown.classList.add("show");
const wantsWarningBanner = DOCUMENTATION_OPTIONS.show_version_warning_banner;

if (hasVersionsJSON && (hasSwitcherMenu || wantsWarningBanner)) {
const data = await fetchVersionSwitcherJSON(
DOCUMENTATION_OPTIONS.theme_switcher_json_url,
);
// TODO: remove the `if(data)` once the `return null` is fixed within fetchVersionSwitcherJSON.
// We don't really want the switcher and warning bar to silently not work.
if (data) {
populateVersionSwitcher(data, versionSwitcherBtns);
if (wantsWarningBanner) {
showVersionWarningBanner(data);
}
}
}
}

Expand Down Expand Up @@ -718,15 +694,74 @@ function debounce(callback, wait) {
};
}

/*******************************************************************************
* Announcement banner - fetch and load remote HTML
*/
async function setupAnnouncementBanner() {
const banner = document.querySelector(".bd-header-announcement");
const { pstAnnouncementUrl } = banner.dataset;

if (!pstAnnouncementUrl) {
return;
}

try {
const response = await fetch(pstAnnouncementUrl);
if (!response.ok) {
throw new Error(
`[PST]: HTTP response status not ok: ${response.status} ${response.statusText}`,
);
}
const data = await response.text();
if (data.length === 0) {
console.log(`[PST]: Empty announcement at: ${pstAnnouncementUrl}`);
return;
}
banner.innerHTML = `<div class="bd-header-announcement__content">${data}</div>`;
banner.classList.remove("d-none");
} catch (_error) {
console.log(`[PST]: Failed to load announcement at: ${pstAnnouncementUrl}`);
console.error(_error);
}
}

/*******************************************************************************
* Reveal (and animate) the banners (version warning, announcement) together
*/
async function fetchRevealBannersTogether() {
// Wait until finished fetching and loading banners
await Promise.allSettled([fetchAndUseVersions(), setupAnnouncementBanner()]);

// The revealer element should have CSS rules that set height to 0, overflow
// to hidden, and an animation transition on the height (unless the user has
// turned off animations)
const revealer = document.querySelector(".pst-async-banner-revealer");

// Remove the d-none (display-none) class to calculate the children heights.
revealer.classList.remove("d-none");

// Add together the heights of the element's children
const height = Array.from(revealer.children).reduce(
(height, el) => height + el.offsetHeight,
0,
);

// Use the calculated height to give the revealer a non-zero height (if
// animations allowed, the height change will animate)
revealer.style.setProperty("height", `${height}px`);
}

/*******************************************************************************
* Call functions after document loading.
*/

// Call this one first to kick off the network request for the version warning
// and announcement banner data as early as possible.
documentReady(fetchRevealBannersTogether);
documentReady(addModeListener);
documentReady(scrollToActive);
documentReady(addTOCInteractivity);
documentReady(setupSearchButtons);
documentReady(initRTDObserver);
documentReady(setupMobileSidebarKeyboardHandlers);
documentReady(fixMoreLinksInMobileSidebar);
documentReady(setupLiteralBlockTabStops);
6 changes: 2 additions & 4 deletions src/pydata_sphinx_theme/assets/styles/abstracts/_links.scss
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,8 @@ $link-hover-decoration-thickness: unquote("max(3px, .1875rem, .12em)") !default;
@mixin link-decoration-hover {
@if $link-hover-decoration-thickness {
text-decoration-thickness: $link-hover-decoration-thickness;
// Disable ink skipping on underlines on hover. Browsers haven't
// standardised on this part of the spec yet, so set both properties
text-decoration-skip-ink: none; // Chromium, Firefox
text-decoration-skip: none; // Safari
// Disable ink skipping on underlines on hover.
text-decoration-skip-ink: none;
}
}

Expand Down
15 changes: 15 additions & 0 deletions src/pydata_sphinx_theme/assets/styles/content/_figures.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
figure > a,
figure > a > img,
figure > img,
figure > video {
display: block;
margin-left: auto;
margin-right: auto;
}

figure {
a.headerlink {
// So that header link doesn't push caption to be off-center.
Expand All @@ -16,12 +25,18 @@ figure {
margin-left: auto;
margin-right: auto;
margin-top: 0.3rem;
text-align: center;

& > p:last-child {
// Don't add extra margin to already existing figure bottom margin
margin-bottom: 0;
}

p {
text-align: start;
display: inline-block;
}

table.table {
width: fit-content;
margin-left: auto;
Expand Down
Loading

0 comments on commit 2f77ce1

Please sign in to comment.