PageSourceSearch

https://docs.poliastro.space/en/latest/_static/doctools.js

js poliastro.space collected 2026-10-04 00:06:37 UTC 8,171 bytes, 264 lines download raw bytes

1/*
2 * doctools.js
3 * ~~~~~~~~~~~
4 *
5 * Base JavaScript utilities for all Sphinx HTML documentation.
6 *
7 * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
8 * :license: BSD, see LICENSE for details.
9 *
10 */
11"use strict";
12
13const _ready = (callback) => {
14  if (document.readyState !== "loading") {
15    callback();
16  } else {
17    document.addEventListener("DOMContentLoaded", callback);
18  }
19};
20
21/**
22 * highlight a given string on a node by wrapping it in
23 * span elements with the given class name.
24 */
25const _highlight = (node, addItems, text, className) => {
26  if (node.nodeType === Node.TEXT_NODE) {
27    const val = node.nodeValue;
28    const parent = node.parentNode;
29    const pos = val.toLowerCase().indexOf(text);
30    if (
31      pos >= 0 &&
32      !parent.classList.contains(className) &&
33      !parent.classList.contains("nohighlight")
34    ) {
35      let span;
36
37      const closestNode = parent.closest("body, svg, foreignObject");
38      const isInSVG = closestNode && closestNode.matches("svg");
39      if (isInSVG) {
40        span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
41      } else {
42        span = document.createElement("span");
43        span.classList.add(className);
44      }
45
46      span.appendChild(document.createTextNode(val.substr(pos, text.length)));
47      parent.insertBefore(
48        span,
49        parent.insertBefore(
50          document.createTextNode(val.substr(pos + text.length)),
51          node.nextSibling
52        )
53      );
54      node.nodeValue = val.substr(0, pos);
55
56      if (isInSVG) {
57        const rect = document.createElementNS(
58          "http://www.w3.org/2000/svg",
59          "rect"
60        );
61        const bbox = parent.getBBox();
62        rect.x.baseVal.value = bbox.x;
63        rect.y.baseVal.value = bbox.y;
64        rect.width.baseVal.value = bbox.width;
65        rect.height.baseVal.value = bbox.height;
66        rect.setAttribute("class", className);
67        addItems.push({ parent: parent, target: rect });
68      }
69    }
70  } else if (node.matches && !node.matches("button, select, textarea")) {
71    node.childNodes.forEach((el) => _highlight(el, addItems, text, className));
72  }
73};
74const _highlightText = (thisNode, text, className) => {
75  let addItems = [];
76  _highlight(thisNode, addItems, text, className);
77  addItems.forEach((obj) =>
78    obj.parent.insertAdjacentElement("beforebegin", obj.target)
79  );
80};
81
82/**
83 * Small JavaScript module for the documentation.
84 */
85const Documentation = {
86  init: () => {
87    Documentation.highlightSearchWords();
88    Documentation.initDomainIndexTable();
89    Documentation.initOnKeyListeners();
90  },
91
92  /**
93   * i18n support
94   */
95  TRANSLATIONS: {},
96  PLURAL_EXPR: (n) => (n === 1 ? 0 : 1),
97  LOCALE: "unknown",
98
99  // gettext and ngettext don't access this so that the functions
100  // can safely bound to a different name (_ = Documentation.gettext)
101  gettext: (string) => {
102    const translated = Documentation.TRANSLATIONS[string];
103    switch (typeof translated) {
104      case "undefined":
105        return string; // no translation
106      case "string":
107        return translated; // translation exists
108      default:
109        return translated[0]; // (singular, plural) translation tuple exists
110    }
111  },
112
113  ngettext: (singular, plural, n) => {
114    const translated = Documentation.TRANSLATIONS[singular];
115    if (typeof translated !== "undefined")
116      return translated[Documentation.PLURAL_EXPR(n)];
117    return n === 1 ? singular : plural;
118  },
119
120  addTranslations: (catalog) => {
121    Object.assign(Documentation.TRANSLATIONS, catalog.messages);
122    Documentation.PLURAL_EXPR = new Function(
123      "n",
124      `return (${catalog.plural_expr})`
125    );
126    Documentation.LOCALE = catalog.locale;
127  },
128
129  /**
130   * highlight the search words provided in the url in the text
131   */
132  highlightSearchWords: () => {
133    const highlight =
134      new URLSearchParams(window.location.search).get("highlight") || "";
135    const terms = highlight.toLowerCase().split(/\s+/).filter(x => x);
136    if (terms.length === 0) return; // nothing to do
137
138    // There should never be more than one element matching "div.body"
139    const divBody = document.querySelectorAll("div.body");
140    const body = divBody.length ? divBody[0] : document.querySelector("body");
141    window.setTimeout(() => {
142      terms.forEach((term) => _highlightText(body, term, "highlighted"));
143    }, 10);
144
145    const searchBox = document.getElementById("searchbox");
146    if (searchBox === null) return;
147    searchBox.appendChild(
148      document
149        .createRange()
150        .createContextualFragment(
151          '<p class="highlight-link">' +
152            '<a href="javascript:Documentation.hideSearchWords()">' +
153            Documentation.gettext("Hide Search Matches") +
154            "</a></p>"
155        )
156    );
157  },
158
159  /**
160   * helper function to hide the search marks again
161   */
162  hideSearchWords: () => {
163    document
164      .querySelectorAll("#searchbox .highlight-link")
165      .forEach((el) => el.remove());
166    document
167      .querySelectorAll("span.highlighted")
168      .forEach((el) => el.classList.remove("highlighted"));
169    const url = new URL(window.location);
170    url.searchParams.delete("highlight");
171    window.history.replaceState({}, "", url);
172  },
173
174  /**
175   * helper function to focus on search bar
176   */
177  focusSearchBar: () => {
178    document.querySelectorAll("input[name=q]")[0]?.focus();
179  },
180
181  /**
182   * Initialise the domain index toggle buttons
183   */
184  initDomainIndexTable: () => {
185    const toggler = (el) => {
186      const idNumber = el.id.substr(7);
187      const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`);
188      if (el.src.substr(-9) === "minus.png") {
189        el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`;
190        toggledRows.forEach((el) => (el.style.display = "none"));
191      } else {
192        el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`;
193        toggledRows.forEach((el) => (el.style.display = ""));
194      }
195    };
196
197    const togglerElements = document.querySelectorAll("img.toggler");
198    togglerElements.forEach((el) =>
199      el.addEventListener("click", (event) => toggler(event.currentTarget))
200    );
201    togglerElements.forEach((el) => (el.style.display = ""));
202    if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler);
203  },
204
205  initOnKeyListeners: () => {
206    // only install a listener if it is really needed
207    if (
208      !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS &&
209      !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS
210    )
211      return;
212
213    const blacklistedElements = new Set([
214      "TEXTAREA",
215      "INPUT",
216      "SELECT",
217      "BUTTON",
218    ]);
219    document.addEventListener("keydown", (event) => {
220      if (blacklistedElements.has(document.activeElement.tagName)) return; // bail for input elements
221      if (event.altKey || event.ctrlKey || event.metaKey) return; // bail with special keys
222
223      if (!event.shiftKey) {
224        switch (event.key) {
225          case "ArrowLeft":
226            if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
227
228            const prevLink = document.querySelector('link[rel="prev"]');
229            if (prevLink && prevLink.href) {
230              window.location.href = prevLink.href;
231              event.preventDefault();
232            }
233            break;
234          case "ArrowRight":
235            if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
236
237            const nextLink = document.querySelector('link[rel="next"]');
238            if (nextLink && nextLink.href) {
239              window.location.href = nextLink.href;
240              event.preventDefault();
241            }
242            break;
243          case "Escape":
244            if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break;
245            Documentation.hideSearchWords();
246            event.preventDefault();
247        }
248      }
249
250      // some keyboard layouts may need Shift to get /
251      switch (event.key) {
252        case "/":
253          if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break;
254          Documentation.focusSearchBar();
255          event.preventDefault();
256      }
257    });
258  },
259};
260
261// quick alias for translations
262const _ = Documentation.gettext;
263
264_ready(Documentation.init);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.