diff --git a/README.md b/README.md index e110c8a5c..ee9bb8c34 100644 --- a/README.md +++ b/README.md @@ -370,6 +370,8 @@ docs: [ ] ``` +On the JavaScript side, ExDoc emits the `"exdoc:loaded"` event. This event may be called multiple times, as you navigate across pages, so initialization that should happen only once must be conditional. We recommend external scripts to use `defer`, not `async`, as shown in the examples below. + ### Rendering Math If you write TeX-style math in your Markdown, such as `$\sum_{i}^{N} x_i$`, it ends up as raw text on the generated pages. To render expressions, we recommend using [KaTeX](https://katex.org/), a JavaScript library that turns expressions into graphics. To load and trigger KaTeX on every documentation page, we can insert the following HTML: @@ -381,13 +383,17 @@ If you write TeX-style math in your Markdown, such as `$\sum_{i}^{N} x_i$`, it e - + + + ``` @@ -402,7 +408,7 @@ Snippets are also objects you may want to render in a special manner. For exampl - ``` For more details and configuration options, see the [Mermaid usage docs](https://mermaid-js.github.io/mermaid/#/usage). diff --git a/assets/js/content.js b/assets/js/content.js index 8a2d5c698..e04f09eb0 100644 --- a/assets/js/content.js +++ b/assets/js/content.js @@ -6,8 +6,7 @@ import { settingsStore } from './settings-store' * corresponding to the current documentation page. */ -window.addEventListener('swup:page:view', initialize) -initialize() +window.addEventListener('exdoc:loaded', initialize) function initialize () { const notebookPath = window.location.pathname.replace(/(\.html)?$/, '.livemd') diff --git a/assets/js/copy-button.js b/assets/js/copy-button.js index 2272d3546..a3171e9dd 100644 --- a/assets/js/copy-button.js +++ b/assets/js/copy-button.js @@ -8,8 +8,7 @@ let buttonTemplate * Initializes copy buttons. */ -window.addEventListener('swup:page:view', initialize) -initialize() +window.addEventListener('exdoc:loaded', initialize) function initialize () { if (!('clipboard' in navigator)) return diff --git a/assets/js/makeup.js b/assets/js/makeup.js index cb867aa44..758255af2 100644 --- a/assets/js/makeup.js +++ b/assets/js/makeup.js @@ -6,8 +6,7 @@ const HIGHLIGHT_CLASS = 'hll' * Sets up dynamic behaviour for code blocks processed with *makeup*. */ -window.addEventListener('swup:page:view', initialize) -initialize() +window.addEventListener('exdoc:loaded', initialize) export function initialize () { // Hovering over a delimiter (bracket, parenthesis, do/end) diff --git a/assets/js/quick-switch.js b/assets/js/quick-switch.js index c36ef034a..08ab4b340 100644 --- a/assets/js/quick-switch.js +++ b/assets/js/quick-switch.js @@ -74,8 +74,7 @@ const state = { */ if (!isEmbedded) { - window.addEventListener('swup:page:view', initialize) - initialize() + window.addEventListener('exdoc:loaded', initialize) } function initialize () { diff --git a/assets/js/search-bar.js b/assets/js/search-bar.js index 25e555c97..2e50e04e4 100644 --- a/assets/js/search-bar.js +++ b/assets/js/search-bar.js @@ -21,8 +21,7 @@ const SEARCH_CLOSE_BUTTON_SELECTOR = 'form.search-bar .search-close-button' */ if (!isEmbedded) { - window.addEventListener('swup:page:view', initialize) - initialize() + window.addEventListener('exdoc:loaded', initialize) } function initialize () { diff --git a/assets/js/search-page.js b/assets/js/search-page.js index a60b95c72..7f647b4bd 100644 --- a/assets/js/search-page.js +++ b/assets/js/search-page.js @@ -20,8 +20,7 @@ lunr.Pipeline.registerFunction(docTrimmerFunction, 'docTrimmer') * Activates only on the `/search.html` page. */ -window.addEventListener('swup:page:view', initialize) -initialize() +window.addEventListener('exdoc:loaded', initialize) function initialize () { const pathname = window.location.pathname diff --git a/assets/js/settings.js b/assets/js/settings.js index e77cee4d7..4e21d82fe 100644 --- a/assets/js/settings.js +++ b/assets/js/settings.js @@ -26,8 +26,7 @@ const modalTabs = [ * Sets up the settings modal. */ -window.addEventListener('swup:page:view', initialize) -initialize() +window.addEventListener('exdoc:loaded', initialize) function initialize () { qsAll(SETTINGS_LINK_SELECTOR).forEach(element => { diff --git a/assets/js/sidebar/sidebar-drawer.js b/assets/js/sidebar/sidebar-drawer.js index 00bb25130..b6f0022c8 100644 --- a/assets/js/sidebar/sidebar-drawer.js +++ b/assets/js/sidebar/sidebar-drawer.js @@ -11,9 +11,7 @@ const SIDEBAR_TOGGLE_SELECTOR = '.sidebar-toggle' const smallScreenQuery = window.matchMedia(`screen and (max-width: ${SMALL_SCREEN_BREAKPOINT}px)`) if (!isEmbedded) { - setDefaultSidebarState() - - window.addEventListener('swup:page:view', setDefaultSidebarState) + window.addEventListener('exdoc:loaded', setDefaultSidebarState) const sidebar = document.getElementById('sidebar') const sidebarToggle = qs(SIDEBAR_TOGGLE_SELECTOR) @@ -49,6 +47,7 @@ if (!isEmbedded) { sessionStorage.setItem(SIDEBAR_WIDTH_KEY, width) document.body.style.setProperty('--sidebarWidth', `${width}px`) }) + // We observe on mousedown because we only care about user resize. sidebar.addEventListener('mousedown', () => resizeObserver.observe(sidebar)) sidebar.addEventListener('mouseup', () => resizeObserver.unobserve(sidebar)) diff --git a/assets/js/sidebar/sidebar-list.js b/assets/js/sidebar/sidebar-list.js index 5838d61f3..a76b0dfdf 100644 --- a/assets/js/sidebar/sidebar-list.js +++ b/assets/js/sidebar/sidebar-list.js @@ -89,9 +89,12 @@ export function initialize () { }) window.addEventListener('hashchange', markCurrentHashInSidebar) - window.addEventListener('swup:page:view', markCurrentHashInSidebar) + // We listen to swup:page:view event because we need to trigger + // markCurrentHashInSidebar() before scollNodeListToCurrentCategory. + window.addEventListener('swup:page:view', markCurrentHashInSidebar) markCurrentHashInSidebar() + // Triggers layout, defer. requestAnimationFrame(scrollNodeListToCurrentCategory) } diff --git a/assets/js/swup.js b/assets/js/swup.js index b56789733..6f9fccd6b 100644 --- a/assets/js/swup.js +++ b/assets/js/swup.js @@ -3,6 +3,10 @@ import SwupA11yPlugin from '@swup/a11y-plugin' import SwupProgressPlugin from '@swup/progress-plugin' import { isEmbedded } from './globals' +window.addEventListener('DOMContentLoaded', () => { + window.dispatchEvent(new Event('exdoc:loaded')) +}) + if (!isEmbedded && window.location.protocol !== 'file:') { new Swup({ animationSelector: false, @@ -15,4 +19,8 @@ if (!isEmbedded && window.location.protocol !== 'file:') { linkSelector: 'a[href]:not([href^="/"]):not([href^="http"])', plugins: [new SwupA11yPlugin(), new SwupProgressPlugin({delay: 500})] }) + + window.addEventListener('swup:page:view', () => { + window.dispatchEvent(new Event('exdoc:loaded')) + }) } diff --git a/assets/js/tabsets.js b/assets/js/tabsets.js index 18d722f0a..6d60eb142 100644 --- a/assets/js/tabsets.js +++ b/assets/js/tabsets.js @@ -6,8 +6,7 @@ const TABSET_CLOSE_COMMENT = 'tabs-close' const TABPANEL_HEADING_NODENAME = 'H3' const TABSET_CONTAINER_CLASS = 'tabset' -window.addEventListener('swup:page:view', initialize) -initialize() +window.addEventListener('exdoc:loaded', initialize) function initialize () { /** @type {[Node, [NodeList, HTMLElement[]][]][]} */ diff --git a/assets/js/tooltips/tooltips.js b/assets/js/tooltips/tooltips.js index b37b756a7..8bb5ef1b5 100644 --- a/assets/js/tooltips/tooltips.js +++ b/assets/js/tooltips/tooltips.js @@ -40,8 +40,7 @@ const state = { * Initializes tooltips handling. */ -window.addEventListener('swup:page:view', initialize) -initialize() +window.addEventListener('exdoc:loaded', initialize) function initialize () { qsAll(TOOLTIP_ACTIVATORS_SELECTOR).forEach(element => {