{"version":3,"file":"scripts/pydata-sphinx-theme.js","mappings":"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","sources":["webpack://pydata_sphinx_theme/./src/pydata_sphinx_theme/assets/scripts/mixin.js","webpack://pydata_sphinx_theme/./node_modules/compare-versions/lib/esm/index.js","webpack://pydata_sphinx_theme/./src/pydata_sphinx_theme/assets/scripts/pydata-sphinx-theme.js"],"sourcesContent":["/* define several functions to replace jQuery methods\n * inspired by https://tobiasahlin.com/blog/move-from-jquery-to-vanilla-javascript/\n */\n\n/**\n * Execute a method if DOM has finished loading\n *\n * @param {function} callback the method to execute\n */\nexport function documentReady(callback) {\n if (document.readyState != \"loading\") callback();\n else document.addEventListener(\"DOMContentLoaded\", callback);\n}\n","/**\n * Compare [semver](https://semver.org/) version strings to find greater, equal or lesser.\n * This library supports the full semver specification, including comparing versions with different number of digits like `1.0.0`, `1.0`, `1`, and pre-release versions like `1.0.0-alpha`.\n * @param v1 - First version to compare\n * @param v2 - Second version to compare\n * @returns Numeric value compatible with the [Array.sort(fn) interface](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#Parameters).\n */\nexport const compareVersions = (v1, v2) => {\n // validate input and split into segments\n const n1 = validateAndParse(v1);\n const n2 = validateAndParse(v2);\n // pop off the patch\n const p1 = n1.pop();\n const p2 = n2.pop();\n // validate numbers\n const r = compareSegments(n1, n2);\n if (r !== 0)\n return r;\n // validate pre-release\n if (p1 && p2) {\n return compareSegments(p1.split('.'), p2.split('.'));\n }\n else if (p1 || p2) {\n return p1 ? -1 : 1;\n }\n return 0;\n};\n/**\n * Validate [semver](https://semver.org/) version strings.\n *\n * @param version Version number to validate\n * @returns `true` if the version number is a valid semver version number, `false` otherwise.\n *\n * @example\n * ```\n * validate('1.0.0-rc.1'); // return true\n * validate('1.0-rc.1'); // return false\n * validate('foo'); // return false\n * ```\n */\nexport const validate = (version) => typeof version === 'string' && /^[v\\d]/.test(version) && semver.test(version);\n/**\n * Compare [semver](https://semver.org/) version strings using the specified operator.\n *\n * @param v1 First version to compare\n * @param v2 Second version to compare\n * @param operator Allowed arithmetic operator to use\n * @returns `true` if the comparison between the firstVersion and the secondVersion satisfies the operator, `false` otherwise.\n *\n * @example\n * ```\n * compare('10.1.8', '10.0.4', '>'); // return true\n * compare('10.0.1', '10.0.1', '='); // return true\n * compare('10.1.1', '10.2.2', '<'); // return true\n * compare('10.1.1', '10.2.2', '<='); // return true\n * compare('10.1.1', '10.2.2', '>='); // return false\n * ```\n */\nexport const compare = (v1, v2, operator) => {\n // validate input operator\n assertValidOperator(operator);\n // since result of compareVersions can only be -1 or 0 or 1\n // a simple map can be used to replace switch\n const res = compareVersions(v1, v2);\n return operatorResMap[operator].includes(res);\n};\n/**\n * Match [npm semver](https://docs.npmjs.com/cli/v6/using-npm/semver) version range.\n *\n * @param version Version number to match\n * @param range Range pattern for version\n * @returns `true` if the version number is within the range, `false` otherwise.\n *\n * @example\n * ```\n * satisfies('1.1.0', '^1.0.0'); // return true\n * satisfies('1.1.0', '~1.0.0'); // return false\n * ```\n */\nexport const satisfies = (version, range) => {\n // if no range operator then \"=\"\n const m = range.match(/^([<>=~^]+)/);\n const op = m ? m[1] : '=';\n // if gt/lt/eq then operator compare\n if (op !== '^' && op !== '~')\n return compare(version, range, op);\n // else range of either \"~\" or \"^\" is assumed\n const [v1, v2, v3, , vp] = validateAndParse(version);\n const [r1, r2, r3, , rp] = validateAndParse(range);\n const v = [v1, v2, v3];\n const r = [r1, r2 !== null && r2 !== void 0 ? r2 : 'x', r3 !== null && r3 !== void 0 ? r3 : 'x'];\n // validate pre-release\n if (rp) {\n if (!vp)\n return false;\n if (compareSegments(v, r) !== 0)\n return false;\n if (compareSegments(vp.split('.'), rp.split('.')) === -1)\n return false;\n }\n // first non-zero number\n const nonZero = r.findIndex((v) => v !== '0') + 1;\n // pointer to where segments can be >=\n const i = op === '~' ? 2 : nonZero > 1 ? nonZero : 1;\n // before pointer must be equal\n if (compareSegments(v.slice(0, i), r.slice(0, i)) !== 0)\n return false;\n // after pointer must be >=\n if (compareSegments(v.slice(i), r.slice(i)) === -1)\n return false;\n return true;\n};\nconst semver = /^[v^~<>=]*?(\\d+)(?:\\.([x*]|\\d+)(?:\\.([x*]|\\d+)(?:\\.([x*]|\\d+))?(?:-([\\da-z\\-]+(?:\\.[\\da-z\\-]+)*))?(?:\\+[\\da-z\\-]+(?:\\.[\\da-z\\-]+)*)?)?)?$/i;\nconst validateAndParse = (version) => {\n if (typeof version !== 'string') {\n throw new TypeError('Invalid argument expected string');\n }\n const match = version.match(semver);\n if (!match) {\n throw new Error(`Invalid argument not valid semver ('${version}' received)`);\n }\n match.shift();\n return match;\n};\nconst isWildcard = (s) => s === '*' || s === 'x' || s === 'X';\nconst tryParse = (v) => {\n const n = parseInt(v, 10);\n return isNaN(n) ? v : n;\n};\nconst forceType = (a, b) => typeof a !== typeof b ? [String(a), String(b)] : [a, b];\nconst compareStrings = (a, b) => {\n if (isWildcard(a) || isWildcard(b))\n return 0;\n const [ap, bp] = forceType(tryParse(a), tryParse(b));\n if (ap > bp)\n return 1;\n if (ap < bp)\n return -1;\n return 0;\n};\nconst compareSegments = (a, b) => {\n for (let i = 0; i < Math.max(a.length, b.length); i++) {\n const r = compareStrings(a[i] || '0', b[i] || '0');\n if (r !== 0)\n return r;\n }\n return 0;\n};\nconst operatorResMap = {\n '>': [1],\n '>=': [0, 1],\n '=': [0],\n '<=': [-1, 0],\n '<': [-1],\n};\nconst allowedOperators = Object.keys(operatorResMap);\nconst assertValidOperator = (op) => {\n if (typeof op !== 'string') {\n throw new TypeError(`Invalid operator type, expected string but got ${typeof op}`);\n }\n if (allowedOperators.indexOf(op) === -1) {\n throw new Error(`Invalid operator, expected one of ${allowedOperators.join('|')}`);\n }\n};\n//# sourceMappingURL=index.js.map","// Define the custom behavior of the page\nimport { documentReady } from \"./mixin\";\nimport { compare, validate } from \"compare-versions\";\n\nimport \"../styles/pydata-sphinx-theme.scss\";\n\n/*******************************************************************************\n * Theme interaction\n */\n\nvar prefersDark = window.matchMedia(\"(prefers-color-scheme: dark)\");\n\n/**\n * set the the body theme to the one specified by the user browser\n *\n * @param {event} e\n */\nfunction autoTheme(e) {\n document.documentElement.dataset.theme = prefersDark.matches\n ? \"dark\"\n : \"light\";\n}\n\n/**\n * Set the theme using the specified mode.\n * It can be one of [\"auto\", \"dark\", \"light\"]\n *\n * @param {str} mode\n */\nfunction setTheme(mode) {\n if (mode !== \"light\" && mode !== \"dark\" && mode !== \"auto\") {\n console.error(`Got invalid theme mode: ${mode}. Resetting to auto.`);\n mode = \"auto\";\n }\n\n // get the theme\n var colorScheme = prefersDark.matches ? \"dark\" : \"light\";\n document.documentElement.dataset.mode = mode;\n var theme = mode == \"auto\" ? colorScheme : mode;\n document.documentElement.dataset.theme = theme;\n // TODO: remove this line after Bootstrap upgrade\n // v5.3 has a colors mode: https://getbootstrap.com/docs/5.3/customize/color-modes/\n document.querySelectorAll(\".dropdown-menu\").forEach((el) => {\n if (theme === \"dark\") {\n el.classList.add(\"dropdown-menu-dark\");\n } else {\n el.classList.remove(\"dropdown-menu-dark\");\n }\n });\n\n // save mode and theme\n localStorage.setItem(\"mode\", mode);\n localStorage.setItem(\"theme\", theme);\n console.log(`[PST]: Changed to ${mode} mode using the ${theme} theme.`);\n\n // add a listener if set on auto\n prefersDark.onchange = mode == \"auto\" ? autoTheme : \"\";\n}\n\n/**\n * Change the theme option order so that clicking on the btn is always a change\n * from \"auto\"\n */\nfunction cycleMode() {\n const defaultMode = document.documentElement.dataset.defaultMode || \"auto\";\n const currentMode = localStorage.getItem(\"mode\") || defaultMode;\n\n var loopArray = (arr, current) => {\n var nextPosition = arr.indexOf(current) + 1;\n if (nextPosition === arr.length) {\n nextPosition = 0;\n }\n return arr[nextPosition];\n };\n\n // make sure the next theme after auto is always a change\n var modeList = prefersDark.matches\n ? [\"auto\", \"light\", \"dark\"]\n : [\"auto\", \"dark\", \"light\"];\n var newMode = loopArray(modeList, currentMode);\n setTheme(newMode);\n}\n\n/**\n * add the theme listener on the btns of the navbar\n */\nfunction addModeListener() {\n // the theme was set a first time using the initial mini-script\n // running setMode will ensure the use of the dark mode if auto is selected\n setTheme(document.documentElement.dataset.mode);\n\n // Attach event handlers for toggling themes colors\n document.querySelectorAll(\".theme-switch-button\").forEach((el) => {\n el.addEventListener(\"click\", cycleMode);\n });\n}\n\n/*******************************************************************************\n * TOC interactivity\n */\n\n/**\n * TOC sidebar - add \"active\" class to parent list\n *\n * Bootstrap's scrollspy adds the active class to the link,\n * but for the automatic collapsing we need this on the parent list item.\n *\n * The event is triggered on \"window\" (and not the nav item as documented),\n * see https://github.com/twbs/bootstrap/issues/20086\n */\nfunction addTOCInteractivity() {\n window.addEventListener(\"activate.bs.scrollspy\", function () {\n const navLinks = document.querySelectorAll(\".bd-toc-nav a\");\n\n navLinks.forEach((navLink) => {\n navLink.parentElement.classList.remove(\"active\");\n });\n\n const activeNavLinks = document.querySelectorAll(\".bd-toc-nav a.active\");\n activeNavLinks.forEach((navLink) => {\n navLink.parentElement.classList.add(\"active\");\n });\n });\n}\n\n/*******************************************************************************\n * Scroll\n */\n\n/**\n * Navigation sidebar scrolling to active page\n */\nfunction scrollToActive() {\n // If the docs nav doesn't exist, do nothing (e.g., on search page)\n if (!document.querySelector(\".bd-docs-nav\")) {\n return;\n }\n\n var sidebar = document.querySelector(\"div.bd-sidebar\");\n\n // Remember the sidebar scroll position between page loads\n // Inspired on source of revealjs.com\n let storedScrollTop = parseInt(\n sessionStorage.getItem(\"sidebar-scroll-top\"),\n 10,\n );\n\n if (!isNaN(storedScrollTop)) {\n // If we've got a saved scroll position, just use that\n sidebar.scrollTop = storedScrollTop;\n console.log(\"[PST]: Scrolled sidebar using stored browser position...\");\n } else {\n // Otherwise, calculate a position to scroll to based on the lowest `active` link\n var sidebarNav = document.querySelector(\".bd-docs-nav\");\n var active_pages = sidebarNav.querySelectorAll(\".active\");\n if (active_pages.length > 0) {\n // Use the last active page as the offset since it's the page we're on\n var latest_active = active_pages[active_pages.length - 1];\n var offset =\n latest_active.getBoundingClientRect().y -\n sidebar.getBoundingClientRect().y;\n // Only scroll the navbar if the active link is lower than 50% of the page\n if (latest_active.getBoundingClientRect().y > window.innerHeight * 0.5) {\n let buffer = 0.25; // Buffer so we have some space above the scrolled item\n sidebar.scrollTop = offset - sidebar.clientHeight * buffer;\n console.log(\"[PST]: Scrolled sidebar using last active link...\");\n }\n }\n }\n\n // Store the sidebar scroll position\n window.addEventListener(\"beforeunload\", () => {\n sessionStorage.setItem(\"sidebar-scroll-top\", sidebar.scrollTop);\n });\n}\n\n/*******************************************************************************\n * Search\n */\n\n/**\n * Find any search forms on the page and return their input element\n */\nvar findSearchInput = () => {\n let forms = document.querySelectorAll(\"form.bd-search\");\n if (!forms.length) {\n // no search form found\n return;\n } else {\n var form;\n if (forms.length == 1) {\n // there is exactly one search form (persistent or hidden)\n form = forms[0];\n } else {\n // must be at least one persistent form, use the first persistent one\n form = document.querySelector(\n \":not(#pst-search-dialog) > form.bd-search\",\n );\n }\n return form.querySelector(\"input\");\n }\n};\n\n/**\n * Activate the search field on the page.\n * - If there is a search field already visible it will be activated.\n * - If not, then a search field will pop up.\n */\nvar toggleSearchField = () => {\n // Find the search input to highlight\n const input = findSearchInput();\n\n // if the input field is the hidden one (the one associated with the\n // search button) then toggle the button state (to show/hide the field)\n const searchDialog = document.getElementById(\"pst-search-dialog\");\n const hiddenInput = searchDialog.querySelector(\"input\");\n if (input === hiddenInput) {\n if (searchDialog.open) {\n searchDialog.close();\n } else {\n // Note: browsers should focus the input field inside the modal dialog\n // automatically when it is opened.\n searchDialog.showModal();\n }\n } else {\n // if the input field is not the hidden one, then toggle its focus state\n\n if (document.activeElement === input) {\n input.blur();\n } else {\n input.focus();\n input.select();\n input.scrollIntoView({ block: \"center\" });\n }\n }\n};\n\n/**\n * Add an event listener for toggleSearchField() for Ctrl/Cmd + K\n */\nvar addEventListenerForSearchKeyboard = () => {\n window.addEventListener(\n \"keydown\",\n (event) => {\n let input = findSearchInput();\n // toggle on Ctrl+k or ⌘+k\n if (\n // Ignore if shift or alt are pressed\n !event.shiftKey &&\n !event.altKey &&\n // On Mac use ⌘, all other OS use Ctrl\n (useCommandKey\n ? event.metaKey && !event.ctrlKey\n : !event.metaKey && event.ctrlKey) &&\n // Case-insensitive so the shortcut still works with caps lock\n /^k$/i.test(event.key)\n ) {\n event.preventDefault();\n toggleSearchField();\n }\n // also allow Escape key to hide (but not show) the dynamic search field\n else if (document.activeElement === input && /Escape/i.test(event.key)) {\n toggleSearchField();\n }\n },\n true,\n );\n};\n\n/**\n * If the user is on a Mac, use command (⌘) instead of control (ctrl) key\n *\n * Note: `navigator.platform` is deprecated; however MDN still recommends using\n * it for the one specific use case of detecting whether a keyboard shortcut\n * should use control or command:\n * https://developer.mozilla.org/en-US/docs/Web/API/Navigator/platform#examples\n */\nvar useCommandKey =\n navigator.platform.indexOf(\"Mac\") === 0 || navigator.platform === \"iPhone\";\n\n/**\n * Change the search hint to `meta key` if we are a Mac\n */\n\nvar changeSearchShortcutKey = () => {\n let shortcuts = document.querySelectorAll(\".search-button__kbd-shortcut\");\n if (useCommandKey) {\n shortcuts.forEach(\n (f) => (f.querySelector(\"kbd.kbd-shortcut__modifier\").innerText = \"⌘\"),\n );\n }\n};\n\nconst closeDialogOnBackdropClick = ({\n currentTarget: dialog,\n clientX,\n clientY,\n}) => {\n if (!dialog.open) {\n return;\n }\n\n // Dialog.getBoundingClientRect() does not include ::backdrop. (This is the\n // trick that allows us to determine if click was inside or outside of the\n // dialog: click handler includes backdrop, getBoundingClientRect does not.)\n const { left, right, top, bottom } = dialog.getBoundingClientRect();\n\n // 0, 0 means top left\n const clickWasOutsideDialog =\n clientX < left || right < clientX || clientY < top || bottom < clientY;\n\n if (clickWasOutsideDialog) {\n dialog.close();\n }\n};\n\n/**\n * Activate callbacks for search button popup\n */\nvar setupSearchButtons = () => {\n changeSearchShortcutKey();\n addEventListenerForSearchKeyboard();\n\n // Add the search button trigger event callback\n document.querySelectorAll(\".search-button__button\").forEach((btn) => {\n btn.onclick = toggleSearchField;\n });\n\n // If user clicks outside the search modal dialog, then close it.\n const searchDialog = document.getElementById(\"pst-search-dialog\");\n // Dialog click handler includes clicks on dialog ::backdrop.\n searchDialog.addEventListener(\"click\", closeDialogOnBackdropClick);\n};\n\n/*******************************************************************************\n * Version Switcher\n * Note that this depends on two variables existing that are defined in\n * and `html-page-context` hook:\n *\n * - DOCUMENTATION_OPTIONS.pagename\n * - DOCUMENTATION_OPTIONS.theme_switcher_url\n */\n\n/**\n * path component of URL\n */\nvar getCurrentUrlPath = () => {\n if (DOCUMENTATION_OPTIONS.BUILDER == \"dirhtml\") {\n return DOCUMENTATION_OPTIONS.pagename.endsWith(\"index\")\n ? `${DOCUMENTATION_OPTIONS.pagename.substring(0, DOCUMENTATION_OPTIONS.pagename.length - \"index\".length)}`\n : `${DOCUMENTATION_OPTIONS.pagename}/`;\n }\n return `${DOCUMENTATION_OPTIONS.pagename}.html`;\n};\n\n/**\n * Allow user to dismiss the warning banner about the docs version being dev / old.\n * We store the dismissal date and version, to give us flexibility about making the\n * dismissal last for longer than one browser session, if we decide to do that.\n *\n * @param {event} event the event that trigger the check\n */\nasync function DismissBannerAndStorePref(event) {\n const banner = document.querySelector(\"#bd-header-version-warning\");\n banner.remove();\n const version = DOCUMENTATION_OPTIONS.VERSION;\n const now = new Date();\n const banner_pref = JSON.parse(\n localStorage.getItem(\"pst_banner_pref\") || \"{}\",\n );\n console.debug(\n `[PST] Dismissing the version warning banner on ${version} starting ${now}.`,\n );\n banner_pref[version] = now;\n localStorage.setItem(\"pst_banner_pref\", JSON.stringify(banner_pref));\n}\n\n/**\n * Check if corresponding page path exists in other version of docs\n * and, if so, go there instead of the homepage of the other docs version\n *\n * @param {event} event the event that trigger the check\n */\nasync function checkPageExistsAndRedirect(event) {\n // ensure we don't follow the initial link\n event.preventDefault();\n const currentFilePath = getCurrentUrlPath();\n let tryUrl = event.currentTarget.getAttribute(\"href\");\n let otherDocsHomepage = tryUrl.replace(currentFilePath, \"\");\n try {\n let head = await fetch(tryUrl, { method: \"HEAD\" });\n if (head.ok) {\n location.href = tryUrl; // the page exists, go there\n } else {\n location.href = otherDocsHomepage;\n }\n } catch (err) {\n // something went wrong, probably CORS restriction, fallback to other docs homepage\n location.href = otherDocsHomepage;\n }\n}\n\n/**\n * Load and parse the version switcher JSON file from an absolute or relative URL.\n *\n * @param {string} url The URL to load version switcher entries from.\n */\nasync function fetchVersionSwitcherJSON(url) {\n const currentPath = getCurrentUrlPath();\n // first check if it's a valid URL\n try {\n var result = new URL(url);\n } catch (err) {\n if (err instanceof TypeError) {\n // Assume we got a relative path, and fix accordingly.\n if (window.location.protocol == \"file:\") {\n // Here instead of returning `null` we work out what the file path would be\n // anyway (same code path as for served docs), as a convenience to folks who\n // routinely disable CORS when they boot up their browser.\n console.info(\n \"[PST] looks like you're viewing this site from a local filesystem, so \" +\n \"the version switcher won't work unless you've disabled CORS. See \" +\n \"https://pydata-sphinx-theme.readthedocs.io/en/stable/user_guide/version-dropdown.html\",\n );\n }\n const cutoff = window.location.href.indexOf(currentPath);\n // cutoff == -1 can happen e.g. on the homepage of locally served docs, where you\n // get something like http://127.0.0.1:8000/ (no trailing `index.html`)\n const origin =\n cutoff == -1\n ? window.location.href\n : window.location.href.substring(0, cutoff);\n result = new URL(url, origin);\n } else {\n // something unexpected happened\n throw err;\n }\n }\n // load and return the JSON\n const response = await fetch(result);\n const data = await response.json();\n return data;\n}\n\n// Populate the version switcher from the JSON data\nfunction populateVersionSwitcher(data, versionSwitcherBtns) {\n const currentFilePath = getCurrentUrlPath();\n versionSwitcherBtns.forEach((btn) => {\n // Set empty strings by default so that these attributes exist and can be used in CSS selectors\n btn.dataset[\"activeVersionName\"] = \"\";\n btn.dataset[\"activeVersion\"] = \"\";\n });\n // in case there are multiple entries with the same version string, this helps us\n // decide which entry's `name` to put on the button itself. Without this, it would\n // always be the *last* version-matching entry; now it will be either the\n // version-matching entry that is also marked as `\"preferred\": true`, or if that\n // doesn't exist: the *first* version-matching entry.\n data = data.map((entry) => {\n // does this entry match the version that we're currently building/viewing?\n entry.match =\n entry.version == DOCUMENTATION_OPTIONS.theme_switcher_version_match;\n entry.preferred = entry.preferred || false;\n // if no custom name specified (e.g., \"latest\"), use version string\n if (!(\"name\" in entry)) {\n entry.name = entry.version;\n }\n return entry;\n });\n const hasMatchingPreferredEntry = data\n .map((entry) => entry.preferred && entry.match)\n .some(Boolean);\n var foundMatch = false;\n // create links to the corresponding page in the other docs versions\n data.forEach((entry) => {\n // create the node\n const anchor = document.createElement(\"a\");\n anchor.setAttribute(\n \"class\",\n \"dropdown-item list-group-item list-group-item-action py-1\",\n );\n anchor.setAttribute(\"href\", `${entry.url}${currentFilePath}`);\n anchor.setAttribute(\"role\", \"option\");\n const span = document.createElement(\"span\");\n span.textContent = `${entry.name}`;\n anchor.appendChild(span);\n // Add dataset values for the version and name in case people want\n // to apply CSS styling based on this information.\n anchor.dataset[\"versionName\"] = entry.name;\n anchor.dataset[\"version\"] = entry.version;\n // replace dropdown button text with the preferred display name of the\n // currently-viewed version, rather than using sphinx's {{ version }} variable.\n // also highlight the dropdown entry for the currently-viewed version's entry\n let matchesAndIsPreferred = hasMatchingPreferredEntry && entry.preferred;\n let matchesAndIsFirst =\n !hasMatchingPreferredEntry && !foundMatch && entry.match;\n if (matchesAndIsPreferred || matchesAndIsFirst) {\n anchor.classList.add(\"active\");\n versionSwitcherBtns.forEach((btn) => {\n btn.innerText = entry.name;\n btn.dataset[\"activeVersionName\"] = entry.name;\n btn.dataset[\"activeVersion\"] = entry.version;\n });\n foundMatch = true;\n }\n // There may be multiple version-switcher elements, e.g. one\n // in a slide-over panel displayed on smaller screens.\n document.querySelectorAll(\".version-switcher__menu\").forEach((menu) => {\n // we need to clone the node for each menu, but onclick attributes are not\n // preserved by `.cloneNode()` so we add onclick here after cloning.\n let node = anchor.cloneNode(true);\n node.onclick = checkPageExistsAndRedirect;\n // on click, AJAX calls will check if the linked page exists before\n // trying to redirect, and if not, will redirect to the homepage\n // for that version of the docs.\n menu.append(node);\n });\n });\n}\n\n/*******************************************************************************\n * Warning banner when viewing non-stable version of the docs.\n */\n\n/**\n * Show a warning banner when viewing a non-stable version of the docs.\n *\n * adapted 2023-06 from https://mne.tools/versionwarning.js, which was\n * originally adapted 2020-05 from https://scikit-learn.org/versionwarning.js\n *\n * @param {Array} data The version data used to populate the switcher menu.\n */\nfunction showVersionWarningBanner(data) {\n var version = DOCUMENTATION_OPTIONS.VERSION;\n // figure out what latest stable version is\n var preferredEntries = data.filter((entry) => entry.preferred);\n if (preferredEntries.length !== 1) {\n const howMany = preferredEntries.length == 0 ? \"No\" : \"Multiple\";\n console.log(\n `[PST] ${howMany} versions marked \"preferred\" found in versions JSON, ignoring.`,\n );\n return;\n }\n const preferredVersion = preferredEntries[0].version;\n const preferredURL = preferredEntries[0].url;\n // if already on preferred version, nothing to do\n const versionsAreComparable = validate(version) && validate(preferredVersion);\n if (versionsAreComparable && compare(version, preferredVersion, \"=\")) {\n console.log(\n \"[PST]: This is the preferred version of the docs, not showing the warning banner.\",\n );\n return;\n }\n // check if banner has been dismissed recently\n const dismiss_date_str = JSON.parse(\n localStorage.getItem(\"pst_banner_pref\") || \"{}\",\n )[version];\n if (dismiss_date_str != null) {\n const dismiss_date = new Date(dismiss_date_str);\n const now = new Date();\n const milliseconds_in_a_day = 24 * 60 * 60 * 1000;\n const days_passed = (now - dismiss_date) / milliseconds_in_a_day;\n const timeout_in_days = 14;\n if (days_passed < timeout_in_days) {\n console.info(\n `[PST] Suppressing version warning banner; was dismissed ${Math.floor(\n days_passed,\n )} day(s) ago`,\n );\n return;\n }\n }\n\n // now construct the warning banner\n const banner = document.querySelector(\"#bd-header-version-warning\");\n const middle = document.createElement(\"div\");\n const inner = document.createElement(\"div\");\n const bold = document.createElement(\"strong\");\n const button = document.createElement(\"a\");\n const close_btn = document.createElement(\"a\");\n // these classes exist since pydata-sphinx-theme v0.10.0\n // the init class is used for animation\n middle.classList = \"bd-header-announcement__content ms-auto me-auto\";\n inner.classList = \"sidebar-message\";\n button.classList =\n \"btn text-wrap font-weight-bold ms-3 my-1 align-baseline pst-button-link-to-stable-version\";\n button.href = `${preferredURL}${getCurrentUrlPath()}`;\n button.innerText = \"Switch to stable version\";\n button.onclick = checkPageExistsAndRedirect;\n close_btn.classList = \"ms-3 my-1 align-baseline\";\n const close_x = document.createElement(\"i\");\n close_btn.append(close_x);\n close_x.classList = \"fa-solid fa-xmark\";\n close_btn.onclick = DismissBannerAndStorePref;\n // add the version-dependent text\n inner.innerText = \"This is documentation for \";\n const isDev =\n version.includes(\"dev\") ||\n version.includes(\"rc\") ||\n version.includes(\"pre\");\n const newerThanPreferred =\n versionsAreComparable && compare(version, preferredVersion, \">\");\n if (isDev || newerThanPreferred) {\n bold.innerText = \"an unstable development version\";\n } else if (versionsAreComparable && compare(version, preferredVersion, \"<\")) {\n bold.innerText = `an old version (${version})`;\n } else if (!version) {\n bold.innerText = \"an unknown version\"; // e.g., an empty string\n } else {\n bold.innerText = `version ${version}`;\n }\n banner.appendChild(middle);\n banner.append(close_btn);\n middle.appendChild(inner);\n inner.appendChild(bold);\n inner.appendChild(document.createTextNode(\".\"));\n inner.appendChild(button);\n banner.classList.remove(\"d-none\");\n}\n\nasync function fetchAndUseVersions() {\n // fetch the JSON version data (only once), then use it to populate the version\n // switcher and maybe show the version warning bar\n var versionSwitcherBtns = document.querySelectorAll(\n \".version-switcher__button\",\n );\n const hasSwitcherMenu = versionSwitcherBtns.length > 0;\n const hasVersionsJSON = DOCUMENTATION_OPTIONS.hasOwnProperty(\n \"theme_switcher_json_url\",\n );\n const wantsWarningBanner = DOCUMENTATION_OPTIONS.show_version_warning_banner;\n\n if (hasVersionsJSON && (hasSwitcherMenu || wantsWarningBanner)) {\n const data = await fetchVersionSwitcherJSON(\n DOCUMENTATION_OPTIONS.theme_switcher_json_url,\n );\n // TODO: remove the `if(data)` once the `return null` is fixed within fetchVersionSwitcherJSON.\n // We don't really want the switcher and warning bar to silently not work.\n if (data) {\n populateVersionSwitcher(data, versionSwitcherBtns);\n if (wantsWarningBanner) {\n showVersionWarningBanner(data);\n }\n }\n }\n}\n\n/*******************************************************************************\n * Sidebar modals (for mobile / narrow screens)\n */\nfunction setupMobileSidebarKeyboardHandlers() {\n // These are the left and right sidebars for wider screens. We cut and paste\n // the content from these widescreen sidebars into the mobile dialogs, when\n // the user clicks the hamburger icon button\n const primarySidebar = document.getElementById(\"pst-primary-sidebar\");\n const secondarySidebar = document.getElementById(\"pst-secondary-sidebar\");\n\n // These are the corresponding left/right elements, which are empty\n // until the user clicks the hamburger icon\n const primaryDialog = document.getElementById(\"pst-primary-sidebar-modal\");\n const secondaryDialog = document.getElementById(\n \"pst-secondary-sidebar-modal\",\n );\n\n // These are the hamburger-style buttons in the header nav bar. They only\n // appear at narrow screen width.\n const primaryToggle = document.querySelector(\".primary-toggle\");\n const secondaryToggle = document.querySelector(\".secondary-toggle\");\n\n // Cut nodes and classes from `from`, paste into/onto `to`\n const cutAndPasteNodesAndClasses = (from, to) => {\n Array.from(from.childNodes).forEach((node) => to.appendChild(node));\n Array.from(from.classList).forEach((cls) => {\n from.classList.remove(cls);\n to.classList.add(cls);\n });\n };\n\n // Hook up the ways to open and close the dialog\n [\n [primaryToggle, primaryDialog, primarySidebar],\n [secondaryToggle, secondaryDialog, secondarySidebar],\n ].forEach(([toggleButton, dialog, sidebar]) => {\n if (!toggleButton || !dialog || !sidebar) {\n return;\n }\n\n // Clicking the button can only open the sidebar, not close it.\n // Clicking the button is also the *only* way to open the sidebar.\n toggleButton.addEventListener(\"click\", (event) => {\n event.preventDefault();\n event.stopPropagation();\n\n // When we open the dialog, we cut and paste the nodes and classes from\n // the widescreen sidebar into the dialog\n cutAndPasteNodesAndClasses(sidebar, dialog);\n\n dialog.showModal();\n });\n\n // Listen for clicks on the backdrop in order to close the dialog\n dialog.addEventListener(\"click\", closeDialogOnBackdropClick);\n\n // We have to manually attach the escape key because there's some code in\n // Sphinx's Sphinx_highlight.js that prevents the default behavior of the\n // escape key\n dialog.addEventListener(\"keydown\", (event) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n event.stopPropagation();\n dialog.close();\n }\n });\n\n // When the dialog is closed, move the nodes (and classes) back to their\n // original place\n dialog.addEventListener(\"close\", () => {\n cutAndPasteNodesAndClasses(dialog, sidebar);\n });\n });\n}\n\n/**\n * When the page loads, or the window resizes, or descendant nodes are added or\n * removed from the main element, check all code blocks and Jupyter notebook\n * outputs, and for each one that has scrollable overflow, set tabIndex = 0.\n */\nfunction addTabStopsToScrollableElements() {\n const updateTabStops = () => {\n document\n .querySelectorAll(\n [\n // code blocks\n \"pre\",\n // NBSphinx notebook output\n \".nboutput > .output_area\",\n // Myst-NB\n \".cell_output > .output\",\n // ipywidgets\n \".jp-RenderedHTMLCommon\",\n // [rST table nodes](https://www.docutils.org/docs/ref/doctree.html#table)\n \".pst-scrollable-table-container\",\n ].join(\", \"),\n )\n .forEach((el) => {\n el.tabIndex =\n el.scrollWidth > el.clientWidth || el.scrollHeight > el.clientHeight\n ? 0\n : -1;\n });\n };\n const debouncedUpdateTabStops = debounce(updateTabStops, 300);\n\n // On window resize\n window.addEventListener(\"resize\", debouncedUpdateTabStops);\n\n // The following MutationObserver is for ipywidgets, which take some time to\n // finish loading and rendering on the page (so even after the \"load\" event is\n // fired, they still have not finished rendering). Would be nice to replace\n // the MutationObserver if there is a way to hook into the ipywidgets code to\n // know when it is done.\n const mainObserver = new MutationObserver(debouncedUpdateTabStops);\n\n // On descendant nodes added/removed from main element\n mainObserver.observe(document.getElementById(\"main-content\"), {\n subtree: true,\n childList: true,\n });\n\n // On page load (when this function gets called)\n updateTabStops();\n}\nfunction debounce(callback, wait) {\n let timeoutId = null;\n return (...args) => {\n clearTimeout(timeoutId);\n timeoutId = setTimeout(() => {\n callback(...args);\n }, wait);\n };\n}\n\n/*******************************************************************************\n * Announcement banner - fetch and load remote HTML\n */\nasync function setupAnnouncementBanner() {\n const banner = document.querySelector(\".bd-header-announcement\");\n const { pstAnnouncementUrl } = banner ? banner.dataset : null;\n\n if (!pstAnnouncementUrl) {\n return;\n }\n\n try {\n const response = await fetch(pstAnnouncementUrl);\n if (!response.ok) {\n throw new Error(\n `[PST]: HTTP response status not ok: ${response.status} ${response.statusText}`,\n );\n }\n const data = await response.text();\n if (data.length === 0) {\n console.log(`[PST]: Empty announcement at: ${pstAnnouncementUrl}`);\n return;\n }\n banner.innerHTML = `
${data}
`;\n banner.classList.remove(\"d-none\");\n } catch (_error) {\n console.log(`[PST]: Failed to load announcement at: ${pstAnnouncementUrl}`);\n console.error(_error);\n }\n}\n\n/*******************************************************************************\n * Reveal (and animate) the banners (version warning, announcement) together\n */\nasync function fetchRevealBannersTogether() {\n // Wait until finished fetching and loading banners\n await Promise.allSettled([fetchAndUseVersions(), setupAnnouncementBanner()]);\n\n // The revealer element should have CSS rules that set height to 0, overflow\n // to hidden, and an animation transition on the height (unless the user has\n // turned off animations)\n const revealer = document.querySelector(\".pst-async-banner-revealer\");\n if (!revealer) {\n return;\n }\n\n // Remove the d-none (display-none) class to calculate the children heights.\n revealer.classList.remove(\"d-none\");\n\n // Add together the heights of the element's children\n const height = Array.from(revealer.children).reduce(\n (height, el) => height + el.offsetHeight,\n 0,\n );\n\n // Use the calculated height to give the revealer a non-zero height (if\n // animations allowed, the height change will animate)\n revealer.style.setProperty(\"height\", `${height}px`);\n\n // Wait for a bit more than 300ms (the transition duration), then set height\n // to auto so the banner can resize if the window is resized.\n setTimeout(() => {\n revealer.style.setProperty(\"height\", \"auto\");\n }, 320);\n}\n\n/*******************************************************************************\n * Call functions after document loading.\n */\n\n// This one first to kick off the network request for the version warning\n// and announcement banner data as early as possible.\ndocumentReady(fetchRevealBannersTogether);\n\ndocumentReady(addModeListener);\ndocumentReady(scrollToActive);\ndocumentReady(addTOCInteractivity);\ndocumentReady(setupSearchButtons);\ndocumentReady(setupMobileSidebarKeyboardHandlers);\n\n// Determining whether an element has scrollable content depends on stylesheets,\n// so we're checking for the \"load\" event rather than \"DOMContentLoaded\"\nif (document.readyState === \"complete\") {\n addTabStopsToScrollableElements();\n} else {\n window.addEventListener(\"load\", addTabStopsToScrollableElements);\n}\n"],"names":["documentReady","callback","document","readyState","addEventListener","validate","version","test","semver","compare","v1","v2","operator","assertValidOperator","res","n1","validateAndParse","n2","p1","pop","p2","r","compareSegments","split","compareVersions","operatorResMap","includes","TypeError","match","Error","shift","isWildcard","s","tryParse","v","n","parseInt","isNaN","compareStrings","a","b","ap","bp","String","forceType","i","Math","max","length","allowedOperators","Object","keys","op","indexOf","join","prefersDark","window","matchMedia","autoTheme","e","documentElement","dataset","theme","matches","setTheme","mode","console","error","colorScheme","querySelectorAll","forEach","el","classList","add","remove","localStorage","setItem","log","onchange","cycleMode","defaultMode","currentMode","getItem","arr","nextPosition","findSearchInput","forms","querySelector","toggleSearchField","input","searchDialog","getElementById","open","close","showModal","activeElement","blur","focus","select","scrollIntoView","block","useCommandKey","navigator","platform","closeDialogOnBackdropClick","currentTarget","dialog","clientX","clientY","left","right","top","bottom","getBoundingClientRect","getCurrentUrlPath","DOCUMENTATION_OPTIONS","BUILDER","pagename","endsWith","substring","async","DismissBannerAndStorePref","event","VERSION","now","Date","banner_pref","JSON","parse","debug","stringify","checkPageExistsAndRedirect","preventDefault","currentFilePath","tryUrl","getAttribute","otherDocsHomepage","replace","fetch","method","ok","location","href","err","fetchAndUseVersions","versionSwitcherBtns","hasSwitcherMenu","hasVersionsJSON","hasOwnProperty","wantsWarningBanner","show_version_warning_banner","data","url","currentPath","result","URL","protocol","info","cutoff","origin","response","json","fetchVersionSwitcherJSON","theme_switcher_json_url","btn","hasMatchingPreferredEntry","map","entry","theme_switcher_version_match","preferred","name","some","Boolean","foundMatch","anchor","createElement","setAttribute","span","textContent","appendChild","matchesAndIsPreferred","matchesAndIsFirst","innerText","menu","node","cloneNode","onclick","append","populateVersionSwitcher","preferredEntries","filter","howMany","preferredVersion","preferredURL","versionsAreComparable","dismiss_date_str","dismiss_date","days_passed","floor","banner","middle","inner","bold","button","close_btn","close_x","isDev","newerThanPreferred","createTextNode","showVersionWarningBanner","addTabStopsToScrollableElements","updateTabStops","tabIndex","scrollWidth","clientWidth","scrollHeight","clientHeight","debouncedUpdateTabStops","wait","timeoutId","args","clearTimeout","setTimeout","debounce","MutationObserver","observe","subtree","childList","setupAnnouncementBanner","pstAnnouncementUrl","status","statusText","text","innerHTML","_error","Promise","allSettled","revealer","height","Array","from","children","reduce","offsetHeight","style","setProperty","sidebar","storedScrollTop","sessionStorage","active_pages","latest_active","offset","y","innerHeight","buffer","scrollTop","navLink","parentElement","shortcuts","f","changeSearchShortcutKey","shiftKey","altKey","metaKey","ctrlKey","key","primarySidebar","secondarySidebar","primaryDialog","secondaryDialog","primaryToggle","secondaryToggle","cutAndPasteNodesAndClasses","to","childNodes","cls","toggleButton","stopPropagation"],"sourceRoot":""}