| 
1 |  | -import { initAppliesSwitch } from "./applies-switch";  | 
2 |  | -import { initCopyButton } from "./copybutton";  | 
3 |  | -import { initHighlight } from "./hljs";  | 
4 |  | -import { initImageCarousel } from "./image-carousel";  | 
5 |  | -import "./markdown/applies-to";  | 
6 |  | -import { openDetailsWithAnchor } from "./open-details-with-anchor";  | 
7 |  | -import { initNav } from "./pages-nav";  | 
8 |  | -import { initSmoothScroll } from "./smooth-scroll";  | 
9 |  | -import { initTabs } from "./tabs";  | 
10 |  | -import { initTocNav } from "./toc-nav";  | 
11 |  | -import "htmx-ext-head-support";  | 
12 |  | -import "htmx-ext-preload";  | 
13 |  | -import { $, $$ } from "select-dom";  | 
14 |  | -import { UAParser } from "ua-parser-js";  | 
15 |  | -import katex from "katex";  | 
16 |  | -import "katex/dist/katex.min.css";  | 
17 |  | - | 
18 |  | -const { getOS } = new UAParser();  | 
 | 1 | +import { initAppliesSwitch } from './applies-switch'  | 
 | 2 | +import { initCopyButton } from './copybutton'  | 
 | 3 | +import { initHighlight } from './hljs'  | 
 | 4 | +import { initImageCarousel } from './image-carousel'  | 
 | 5 | +import './markdown/applies-to'  | 
 | 6 | +import { openDetailsWithAnchor } from './open-details-with-anchor'  | 
 | 7 | +import { initNav } from './pages-nav'  | 
 | 8 | +import { initSmoothScroll } from './smooth-scroll'  | 
 | 9 | +import { initTabs } from './tabs'  | 
 | 10 | +import { initTocNav } from './toc-nav'  | 
 | 11 | +import 'htmx-ext-head-support'  | 
 | 12 | +import 'htmx-ext-preload'  | 
 | 13 | +import katex from 'katex'  | 
 | 14 | +import 'katex/dist/katex.min.css'  | 
 | 15 | +import { $, $$ } from 'select-dom'  | 
 | 16 | +import { UAParser } from 'ua-parser-js'  | 
 | 17 | + | 
 | 18 | +const { getOS } = new UAParser()  | 
19 | 19 | const isLazyLoadNavigationEnabled =  | 
20 |  | -  $('meta[property="docs:feature:lazy-load-navigation"]')?.content === "true";  | 
 | 20 | +    $('meta[property="docs:feature:lazy-load-navigation"]')?.content === 'true'  | 
21 | 21 | 
 
  | 
22 | 22 | /**  | 
23 | 23 |  * Initialize KaTeX math rendering for elements with class 'math'  | 
24 | 24 |  */  | 
25 | 25 | function initMath() {  | 
26 |  | -  const mathElements = $$(".math");  | 
27 |  | -  mathElements.forEach((element) => {  | 
28 |  | -    try {  | 
29 |  | -      const content = element.textContent?.trim();  | 
30 |  | -      if (!content) return;  | 
31 |  | - | 
32 |  | -      // Determine if this is display math based on content and element type  | 
33 |  | -      const isDisplayMath =  | 
34 |  | -        element.tagName === "DIV" ||  | 
35 |  | -        content.includes("\\[") ||  | 
36 |  | -        content.includes("$$") ||  | 
37 |  | -        content.includes("\\begin{") ||  | 
38 |  | -        content.includes("\n");  | 
39 |  | - | 
40 |  | -      // Clean up common LaTeX delimiters  | 
41 |  | -      const cleanContent = content  | 
42 |  | -        .replace(/^\$\$|\$\$$/g, "") // Remove $$ delimiters  | 
43 |  | -        .replace(/^\\\[|\\\]$/g, "") // Remove \[ \] delimiters  | 
44 |  | -        .trim();  | 
45 |  | - | 
46 |  | -      // Clear the element content before rendering  | 
47 |  | -      element.innerHTML = "";  | 
48 |  | - | 
49 |  | -      katex.render(cleanContent, element, {  | 
50 |  | -        throwOnError: false,  | 
51 |  | -        displayMode: isDisplayMath,  | 
52 |  | -        strict: false, // Allow some LaTeX extensions  | 
53 |  | -        trust: false, // Security: don't trust arbitrary commands  | 
54 |  | -        output: "mathml", // Only render MathML, not HTML  | 
55 |  | -        macros: {  | 
56 |  | -          // Add common macros if needed  | 
57 |  | -        },  | 
58 |  | -      });  | 
59 |  | -    } catch (error) {  | 
60 |  | -      console.warn("KaTeX rendering error:", error);  | 
61 |  | -      // Fallback: keep the original content  | 
62 |  | -      element.innerHTML = element.textContent || "";  | 
63 |  | -    }  | 
64 |  | -  });  | 
 | 26 | +    const mathElements = $$('.math')  | 
 | 27 | +    mathElements.forEach((element) => {  | 
 | 28 | +        try {  | 
 | 29 | +            const content = element.textContent?.trim()  | 
 | 30 | +            if (!content) return  | 
 | 31 | + | 
 | 32 | +            // Determine if this is display math based on content and element type  | 
 | 33 | +            const isDisplayMath =  | 
 | 34 | +                element.tagName === 'DIV' ||  | 
 | 35 | +                content.includes('\\[') ||  | 
 | 36 | +                content.includes('$$') ||  | 
 | 37 | +                content.includes('\\begin{') ||  | 
 | 38 | +                content.includes('\n')  | 
 | 39 | + | 
 | 40 | +            // Clean up common LaTeX delimiters  | 
 | 41 | +            const cleanContent = content  | 
 | 42 | +                .replace(/^\$\$|\$\$$/g, '') // Remove $$ delimiters  | 
 | 43 | +                .replace(/^\\\[|\\\]$/g, '') // Remove \[ \] delimiters  | 
 | 44 | +                .trim()  | 
 | 45 | + | 
 | 46 | +            // Clear the element content before rendering  | 
 | 47 | +            element.innerHTML = ''  | 
 | 48 | + | 
 | 49 | +            katex.render(cleanContent, element, {  | 
 | 50 | +                throwOnError: false,  | 
 | 51 | +                displayMode: isDisplayMath,  | 
 | 52 | +                strict: false, // Allow some LaTeX extensions  | 
 | 53 | +                trust: false, // Security: don't trust arbitrary commands  | 
 | 54 | +                output: 'mathml', // Only render MathML, not HTML  | 
 | 55 | +                macros: {  | 
 | 56 | +                    // Add common macros if needed  | 
 | 57 | +                },  | 
 | 58 | +            })  | 
 | 59 | +        } catch (error) {  | 
 | 60 | +            console.warn('KaTeX rendering error:', error)  | 
 | 61 | +            // Fallback: keep the original content  | 
 | 62 | +            element.innerHTML = element.textContent || ''  | 
 | 63 | +        }  | 
 | 64 | +    })  | 
65 | 65 | }  | 
66 | 66 | 
 
  | 
67 |  | -document.addEventListener("htmx:load", function (event) {  | 
68 |  | -  initTocNav();  | 
69 |  | -  initHighlight();  | 
70 |  | -  initCopyButton();  | 
71 |  | -  initTabs();  | 
72 |  | -  initAppliesSwitch();  | 
73 |  | -  initMath();  | 
74 |  | - | 
75 |  | -  // We do this so that the navigation is not initialized twice  | 
76 |  | -  if (isLazyLoadNavigationEnabled) {  | 
77 |  | -    if (event.detail.elt.id === "nav-tree") {  | 
78 |  | -      initNav();  | 
 | 67 | +document.addEventListener('htmx:load', function (event) {  | 
 | 68 | +    initTocNav()  | 
 | 69 | +    initHighlight()  | 
 | 70 | +    initCopyButton()  | 
 | 71 | +    initTabs()  | 
 | 72 | +    initAppliesSwitch()  | 
 | 73 | +    initMath()  | 
 | 74 | + | 
 | 75 | +    // We do this so that the navigation is not initialized twice  | 
 | 76 | +    if (isLazyLoadNavigationEnabled) {  | 
 | 77 | +        if (event.detail.elt.id === 'nav-tree') {  | 
 | 78 | +            initNav()  | 
 | 79 | +        }  | 
 | 80 | +    } else {  | 
 | 81 | +        initNav()  | 
 | 82 | +    }  | 
 | 83 | +    initSmoothScroll()  | 
 | 84 | +    openDetailsWithAnchor()  | 
 | 85 | +    initImageCarousel()  | 
 | 86 | + | 
 | 87 | +    const urlParams = new URLSearchParams(window.location.search)  | 
 | 88 | +    const editParam = urlParams.has('edit')  | 
 | 89 | +    if (editParam) {  | 
 | 90 | +        $('.edit-this-page.hidden')?.classList.remove('hidden')  | 
79 | 91 |     }  | 
80 |  | -  } else {  | 
81 |  | -    initNav();  | 
82 |  | -  }  | 
83 |  | -  initSmoothScroll();  | 
84 |  | -  openDetailsWithAnchor();  | 
85 |  | -  initImageCarousel();  | 
86 |  | - | 
87 |  | -  const urlParams = new URLSearchParams(window.location.search);  | 
88 |  | -  const editParam = urlParams.has("edit");  | 
89 |  | -  if (editParam) {  | 
90 |  | -    $(".edit-this-page.hidden")?.classList.remove("hidden");  | 
91 |  | -  }  | 
92 |  | -});  | 
 | 92 | +})  | 
93 | 93 | 
 
  | 
94 | 94 | // Don't remove style tags because they are used by the elastic global nav.  | 
95 |  | -document.addEventListener("htmx:removingHeadElement", function (event) {  | 
96 |  | -  const tagName = event.detail.headElement.tagName;  | 
97 |  | -  if (tagName === "STYLE") {  | 
98 |  | -    event.preventDefault();  | 
99 |  | -  }  | 
100 |  | -});  | 
101 |  | - | 
102 |  | -document.addEventListener("htmx:beforeRequest", function (event) {  | 
103 |  | -  if (  | 
104 |  | -    event.detail.requestConfig.verb === "get" &&  | 
105 |  | -    event.detail.requestConfig.triggeringEvent  | 
106 |  | -  ) {  | 
107 |  | -    const { ctrlKey, metaKey, shiftKey }: PointerEvent =  | 
108 |  | -      event.detail.requestConfig.triggeringEvent;  | 
109 |  | -    const { name: os } = getOS();  | 
110 |  | -    const modifierKey: boolean = os === "macOS" ? metaKey : ctrlKey;  | 
111 |  | -    if (shiftKey || modifierKey) {  | 
112 |  | -      event.preventDefault();  | 
113 |  | -      window.open(  | 
114 |  | -        event.detail.requestConfig.path,  | 
115 |  | -        "_blank",  | 
116 |  | -        "noopener,noreferrer",  | 
117 |  | -      );  | 
 | 95 | +document.addEventListener('htmx:removingHeadElement', function (event) {  | 
 | 96 | +    const tagName = event.detail.headElement.tagName  | 
 | 97 | +    if (tagName === 'STYLE') {  | 
 | 98 | +        event.preventDefault()  | 
 | 99 | +    }  | 
 | 100 | +})  | 
 | 101 | + | 
 | 102 | +document.addEventListener('htmx:beforeRequest', function (event) {  | 
 | 103 | +    if (  | 
 | 104 | +        event.detail.requestConfig.verb === 'get' &&  | 
 | 105 | +        event.detail.requestConfig.triggeringEvent  | 
 | 106 | +    ) {  | 
 | 107 | +        const { ctrlKey, metaKey, shiftKey }: PointerEvent =  | 
 | 108 | +            event.detail.requestConfig.triggeringEvent  | 
 | 109 | +        const { name: os } = getOS()  | 
 | 110 | +        const modifierKey: boolean = os === 'macOS' ? metaKey : ctrlKey  | 
 | 111 | +        if (shiftKey || modifierKey) {  | 
 | 112 | +            event.preventDefault()  | 
 | 113 | +            window.open(  | 
 | 114 | +                event.detail.requestConfig.path,  | 
 | 115 | +                '_blank',  | 
 | 116 | +                'noopener,noreferrer'  | 
 | 117 | +            )  | 
 | 118 | +        }  | 
 | 119 | +    }  | 
 | 120 | +})  | 
 | 121 | + | 
 | 122 | +document.body.addEventListener('htmx:oobBeforeSwap', function (event) {  | 
 | 123 | +    // This is needed to scroll to the top of the page when the content is swapped  | 
 | 124 | +    if (  | 
 | 125 | +        event.target.id === 'main-container' ||  | 
 | 126 | +        event.target.id === 'markdown-content' ||  | 
 | 127 | +        event.target.id === 'content-container'  | 
 | 128 | +    ) {  | 
 | 129 | +        window.scrollTo(0, 0)  | 
118 | 130 |     }  | 
119 |  | -  }  | 
120 |  | -});  | 
121 |  | - | 
122 |  | -document.body.addEventListener("htmx:oobBeforeSwap", function (event) {  | 
123 |  | -  // This is needed to scroll to the top of the page when the content is swapped  | 
124 |  | -  if (  | 
125 |  | -    event.target.id === "main-container" ||  | 
126 |  | -    event.target.id === "markdown-content" ||  | 
127 |  | -    event.target.id === "content-container"  | 
128 |  | -  ) {  | 
129 |  | -    window.scrollTo(0, 0);  | 
130 |  | -  }  | 
131 |  | -});  | 
132 |  | - | 
133 |  | -document.body.addEventListener("htmx:pushedIntoHistory", function (event) {  | 
134 |  | -  const pagesNav = $("#pages-nav");  | 
135 |  | -  const currentNavItem = $$(".current", pagesNav);  | 
136 |  | -  currentNavItem.forEach((el) => {  | 
137 |  | -    el.classList.remove("current");  | 
138 |  | -  });  | 
139 |  | -  const navItems = $$('a[href="' + event.detail.path + '"]', pagesNav);  | 
140 |  | -  navItems.forEach((navItem) => {  | 
141 |  | -    navItem.classList.add("current");  | 
142 |  | -  });  | 
143 |  | -});  | 
144 |  | - | 
145 |  | -document.body.addEventListener("htmx:responseError", function (event) {  | 
146 |  | -  // If you get a 404 error while clicking on a hx-get link, actually open the link  | 
147 |  | -  // This is needed because the browser doesn't update the URL when the response is a 404  | 
148 |  | -  // In production, cloudfront handles serving the 404 page.  | 
149 |  | -  // Locally, the DocumentationWebHost handles it.  | 
150 |  | -  // On previews, a generic 404 page is shown.  | 
151 |  | -  if (event.detail.xhr.status === 404) {  | 
152 |  | -    window.location.assign(event.detail.pathInfo.requestPath);  | 
153 |  | -  }  | 
154 |  | -});  | 
 | 131 | +})  | 
 | 132 | + | 
 | 133 | +document.body.addEventListener('htmx:pushedIntoHistory', function (event) {  | 
 | 134 | +    const pagesNav = $('#pages-nav')  | 
 | 135 | +    const currentNavItem = $$('.current', pagesNav)  | 
 | 136 | +    currentNavItem.forEach((el) => {  | 
 | 137 | +        el.classList.remove('current')  | 
 | 138 | +    })  | 
 | 139 | +    const navItems = $$('a[href="' + event.detail.path + '"]', pagesNav)  | 
 | 140 | +    navItems.forEach((navItem) => {  | 
 | 141 | +        navItem.classList.add('current')  | 
 | 142 | +    })  | 
 | 143 | +})  | 
 | 144 | + | 
 | 145 | +document.body.addEventListener('htmx:responseError', function (event) {  | 
 | 146 | +    // If you get a 404 error while clicking on a hx-get link, actually open the link  | 
 | 147 | +    // This is needed because the browser doesn't update the URL when the response is a 404  | 
 | 148 | +    // In production, cloudfront handles serving the 404 page.  | 
 | 149 | +    // Locally, the DocumentationWebHost handles it.  | 
 | 150 | +    // On previews, a generic 404 page is shown.  | 
 | 151 | +    if (event.detail.xhr.status === 404) {  | 
 | 152 | +        window.location.assign(event.detail.pathInfo.requestPath)  | 
 | 153 | +    }  | 
 | 154 | +})  | 
155 | 155 | 
 
  | 
156 | 156 | // We add a query string to the get request to make sure the requested page is up to date  | 
157 |  | -const docsBuilderVersion = $("body").dataset.docsBuilderVersion;  | 
158 |  | -document.body.addEventListener("htmx:configRequest", function (event) {  | 
159 |  | -  if (event.detail.verb === "get") {  | 
160 |  | -    event.detail.parameters["v"] = docsBuilderVersion;  | 
161 |  | -  }  | 
162 |  | -});  | 
 | 157 | +const docsBuilderVersion = $('body').dataset.docsBuilderVersion  | 
 | 158 | +document.body.addEventListener('htmx:configRequest', function (event) {  | 
 | 159 | +    if (event.detail.verb === 'get') {  | 
 | 160 | +        event.detail.parameters['v'] = docsBuilderVersion  | 
 | 161 | +    }  | 
 | 162 | +})  | 
163 | 163 | 
 
  | 
164 | 164 | // Here we need to strip the v parameter from the URL so  | 
165 | 165 | // that the browser doesn't show the v parameter in the address bar  | 
166 |  | -document.body.addEventListener("htmx:beforeHistoryUpdate", function (event) {  | 
167 |  | -  const params = new URLSearchParams(  | 
168 |  | -    event.detail.history.path.split("?")[1] ?? "",  | 
169 |  | -  );  | 
170 |  | -  params.delete("v");  | 
171 |  | -  const pathWithoutQueryString = event.detail.history.path.split("?")[0];  | 
172 |  | -  if (params.size === 0) {  | 
173 |  | -    event.detail.history.path = pathWithoutQueryString;  | 
174 |  | -  } else {  | 
175 |  | -    event.detail.history.path =  | 
176 |  | -      pathWithoutQueryString + "?" + params.toString();  | 
177 |  | -  }  | 
178 |  | -});  | 
 | 166 | +document.body.addEventListener('htmx:beforeHistoryUpdate', function (event) {  | 
 | 167 | +    const params = new URLSearchParams(  | 
 | 168 | +        event.detail.history.path.split('?')[1] ?? ''  | 
 | 169 | +    )  | 
 | 170 | +    params.delete('v')  | 
 | 171 | +    const pathWithoutQueryString = event.detail.history.path.split('?')[0]  | 
 | 172 | +    if (params.size === 0) {  | 
 | 173 | +        event.detail.history.path = pathWithoutQueryString  | 
 | 174 | +    } else {  | 
 | 175 | +        event.detail.history.path =  | 
 | 176 | +            pathWithoutQueryString + '?' + params.toString()  | 
 | 177 | +    }  | 
 | 178 | +})  | 
0 commit comments