diff --git a/docs/user_guide/version-dropdown.rst b/docs/user_guide/version-dropdown.rst index 94f367081..446af4833 100644 --- a/docs/user_guide/version-dropdown.rst +++ b/docs/user_guide/version-dropdown.rst @@ -29,6 +29,12 @@ The switcher requires the following configuration steps: Below is a more in-depth description of each of these configuration steps. +.. warning:: + Modern web browsers do not allow loading data when the request is made from a page loaded via the ``file:`` protocol. This means that if you build your documentation locally and then directly open one of its pages in the browser, **the version switcher will not be allowed to load its JSON data source** and you'll end up with an empty switcher menu. Possible work-arounds are: + + 1. View the locally-built files through a local webserver (Python provides a builtin module for this: https://docs.python.org/3/library/http.server.html). + 2. Disabling your browser's security settings (either by passing a command-line flag when launching the browser, or through a browser add-on). + Add a JSON file to define your switcher's versions -------------------------------------------------- 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 f244c75a7..a861cfdb0 100644 --- a/src/pydata_sphinx_theme/assets/scripts/pydata-sphinx-theme.js +++ b/src/pydata_sphinx_theme/assets/scripts/pydata-sphinx-theme.js @@ -406,23 +406,31 @@ async function checkPageExistsAndRedirect(event) { * @param {string} url The URL to load version switcher entries from. */ async function fetchVersionSwitcherJSON(url) { + const currentPath = getCurrentUrlPath(); // first check if it's a valid URL try { var result = new URL(url); } catch (err) { if (err instanceof TypeError) { - if (!window.location.origin) { - // window.location.origin is null for local static sites - // (ie. window.location.protocol == 'file:') - // - // TODO: Fix this to return the static version switcher by working out - // how to get the correct path to the switcher JSON file on local static builds - return null; + // Assume we got a relative path, and fix accordingly. + if (window.location.protocol == "file:") { + // Here instead of returning `null` we work out what the file path would be + // anyway (same code path as for served docs), as a convenience to folks who + // routinely disable CORS when they boot up their browser. + console.info( + "[PST] looks like you're viewing this site from a local filesystem, so " + + "the version switcher won't work unless you've disabled CORS. See " + + "https://pydata-sphinx-theme.readthedocs.io/en/stable/user_guide/version-dropdown.html", + ); } - // assume we got a relative path, and fix accordingly. But first, we need to - // use `fetch()` to follow redirects so we get the correct final base URL - const origin = await fetch(window.location.origin, { method: "HEAD" }); - result = new URL(url, origin.url); + const cutoff = window.location.href.indexOf(currentPath); + // cutoff == -1 can happen e.g. on the homepage of locally served docs, where you + // get something like http://127.0.0.1:8000/ (no trailing `index.html`) + const origin = + cutoff == -1 + ? window.location.href + : window.location.href.substring(0, cutoff); + result = new URL(url, origin); } else { // something unexpected happened throw err;