URI:
       sphinx_highlight.js - sphere - GPU-based 3D discrete element method algorithm with optional fluid coupling
  HTML git clone git://src.adamsgaard.dk/sphere
   DIR Log
   DIR Files
   DIR Refs
   DIR LICENSE
       ---
       sphinx_highlight.js (5325B)
       ---
            1 /* Highlighting utilities for Sphinx HTML documentation. */
            2 "use strict";
            3 
            4 const SPHINX_HIGHLIGHT_ENABLED = true;
            5 
            6 /**
            7  * highlight a given string on a node by wrapping it in
            8  * span elements with the given class name.
            9  */
           10 const _highlight = (node, addItems, text, className) => {
           11   if (node.nodeType === Node.TEXT_NODE) {
           12     const val = node.nodeValue;
           13     const parent = node.parentNode;
           14     const pos = val.toLowerCase().indexOf(text);
           15     if (
           16       pos >= 0
           17       && !parent.classList.contains(className)
           18       && !parent.classList.contains("nohighlight")
           19     ) {
           20       let span;
           21 
           22       const closestNode = parent.closest("body, svg, foreignObject");
           23       const isInSVG = closestNode && closestNode.matches("svg");
           24       if (isInSVG) {
           25         span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
           26       } else {
           27         span = document.createElement("span");
           28         span.classList.add(className);
           29       }
           30 
           31       span.appendChild(document.createTextNode(val.substr(pos, text.length)));
           32       const rest = document.createTextNode(val.substr(pos + text.length));
           33       parent.insertBefore(span, parent.insertBefore(rest, node.nextSibling));
           34       node.nodeValue = val.substr(0, pos);
           35       /* There may be more occurrences of search term in this node. So call this
           36        * function recursively on the remaining fragment.
           37        */
           38       _highlight(rest, addItems, text, className);
           39 
           40       if (isInSVG) {
           41         const rect = document.createElementNS(
           42           "http://www.w3.org/2000/svg",
           43           "rect",
           44         );
           45         const bbox = parent.getBBox();
           46         rect.x.baseVal.value = bbox.x;
           47         rect.y.baseVal.value = bbox.y;
           48         rect.width.baseVal.value = bbox.width;
           49         rect.height.baseVal.value = bbox.height;
           50         rect.setAttribute("class", className);
           51         addItems.push({ parent: parent, target: rect });
           52       }
           53     }
           54   } else if (node.matches && !node.matches("button, select, textarea")) {
           55     node.childNodes.forEach((el) => _highlight(el, addItems, text, className));
           56   }
           57 };
           58 const _highlightText = (thisNode, text, className) => {
           59   let addItems = [];
           60   _highlight(thisNode, addItems, text, className);
           61   addItems.forEach((obj) =>
           62     obj.parent.insertAdjacentElement("beforebegin", obj.target),
           63   );
           64 };
           65 
           66 /**
           67  * Small JavaScript module for the documentation.
           68  */
           69 const SphinxHighlight = {
           70   /**
           71    * highlight the search words provided in localstorage in the text
           72    */
           73   highlightSearchWords: () => {
           74     if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight
           75 
           76     // get and clear terms from localstorage
           77     const url = new URL(window.location);
           78     const highlight =
           79       localStorage.getItem("sphinx_highlight_terms")
           80       || url.searchParams.get("highlight")
           81       || "";
           82     localStorage.removeItem("sphinx_highlight_terms");
           83     // Update history only if '?highlight' is present; otherwise it
           84     // clears text fragments (not set in window.location by the browser)
           85     if (url.searchParams.has("highlight")) {
           86       url.searchParams.delete("highlight");
           87       window.history.replaceState({}, "", url);
           88     }
           89 
           90     // get individual terms from highlight string
           91     const terms = highlight
           92       .toLowerCase()
           93       .split(/\s+/)
           94       .filter((x) => x);
           95     if (terms.length === 0) return; // nothing to do
           96 
           97     // There should never be more than one element matching "div.body"
           98     const divBody = document.querySelectorAll("div.body");
           99     const body = divBody.length ? divBody[0] : document.querySelector("body");
          100     window.setTimeout(() => {
          101       terms.forEach((term) => _highlightText(body, term, "highlighted"));
          102     }, 10);
          103 
          104     const searchBox = document.getElementById("searchbox");
          105     if (searchBox === null) return;
          106     searchBox.appendChild(
          107       document
          108         .createRange()
          109         .createContextualFragment(
          110           '<p class="highlight-link">'
          111             + '<a href="javascript:SphinxHighlight.hideSearchWords()">'
          112             + _("Hide Search Matches")
          113             + "</a></p>",
          114         ),
          115     );
          116   },
          117 
          118   /**
          119    * helper function to hide the search marks again
          120    */
          121   hideSearchWords: () => {
          122     document
          123       .querySelectorAll("#searchbox .highlight-link")
          124       .forEach((el) => el.remove());
          125     document
          126       .querySelectorAll("span.highlighted")
          127       .forEach((el) => el.classList.remove("highlighted"));
          128     localStorage.removeItem("sphinx_highlight_terms");
          129   },
          130 
          131   initEscapeListener: () => {
          132     // only install a listener if it is really needed
          133     if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return;
          134 
          135     document.addEventListener("keydown", (event) => {
          136       // bail for input elements
          137       if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName))
          138         return;
          139       // bail with special keys
          140       if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey)
          141         return;
          142       if (
          143         DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS
          144         && event.key === "Escape"
          145       ) {
          146         SphinxHighlight.hideSearchWords();
          147         event.preventDefault();
          148       }
          149     });
          150   },
          151 };
          152 
          153 _ready(() => {
          154   /* Do not call highlightSearchWords() when we are on the search page.
          155    * It will highlight words from the *previous* search query.
          156    */
          157   if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords();
          158   SphinxHighlight.initEscapeListener();
          159 });