{"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 // 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 if (!window.location.origin) {\n // window.location.origin is null for local static sites\n // (ie. window.location.protocol == 'file:')\n //\n // TODO: Fix this to return the static version switcher by working out\n // how to get the correct path to the switcher JSON file on local static builds\n return null;\n }\n // assume we got a relative path, and fix accordingly. But first, we need to\n // use `fetch()` to follow redirects so we get the correct final base URL\n const origin = await fetch(window.location.origin, { method: \"HEAD\" });\n result = new URL(url, origin.url);\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\n/*******************************************************************************\n * MutationObserver to move the ReadTheDocs button\n */\n\n/**\n * intercept the RTD flyout and place it in the rtd-footer-container if existing\n * if not it stays where on top of the page\n */\nfunction initRTDObserver() {\n const mutatedCallback = (mutationList, observer) => {\n mutationList.forEach((mutation) => {\n // Check whether the mutation is for RTD, which will have a specific structure\n if (mutation.addedNodes.length === 0) {\n return;\n }\n if (mutation.addedNodes[0].data === undefined) {\n return;\n }\n if (mutation.addedNodes[0].data.search(\"Inserted RTD Footer\") != -1) {\n mutation.addedNodes.forEach((node) => {\n document.getElementById(\"rtd-footer-container\").append(node);\n });\n }\n });\n };\n\n const observer = new MutationObserver(mutatedCallback);\n const config = { childList: true };\n observer.observe(document.body, config);\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(initRTDObserver);\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","result","URL","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","info","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","mutationList","observer","mutation","addedNodes","undefined","search","body","primarySidebar","secondarySidebar","primaryDialog","secondaryDialog","primaryToggle","secondaryToggle","cutAndPasteNodesAndClasses","to","childNodes","cls","toggleButton","stopPropagation"],"sourceRoot":""}