From 31bbd140878a12f9004be11d9c2a4ee0ed93cf5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Fri, 24 Jan 2025 19:49:45 +0100 Subject: [PATCH 1/7] Add exdoc:loaded event --- README.md | 40 ++++++++++++++++++----------- assets/js/content.js | 2 +- assets/js/copy-button.js | 2 +- assets/js/makeup.js | 2 +- assets/js/quick-switch.js | 2 +- assets/js/search-bar.js | 2 +- assets/js/search-page.js | 2 +- assets/js/settings.js | 2 +- assets/js/sidebar/sidebar-drawer.js | 2 +- assets/js/sidebar/sidebar-list.js | 2 +- assets/js/swup.js | 9 +++++++ assets/js/tabsets.js | 2 +- assets/js/tooltips/tooltips.js | 2 +- 13 files changed, 45 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index e110c8a5c..215bc3dc6 100644 --- a/README.md +++ b/README.md @@ -381,13 +381,17 @@ If you write TeX-style math in your Markdown, such as `$\sum_{i}^{N} x_i$`, it e - + + + ``` @@ -402,7 +406,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..f8e4b8ac6 100644 --- a/assets/js/content.js +++ b/assets/js/content.js @@ -6,7 +6,7 @@ import { settingsStore } from './settings-store' * corresponding to the current documentation page. */ -window.addEventListener('swup:page:view', initialize) +window.addEventListener('exdoc:loaded', initialize) initialize() function initialize () { diff --git a/assets/js/copy-button.js b/assets/js/copy-button.js index 2272d3546..ed420b8e8 100644 --- a/assets/js/copy-button.js +++ b/assets/js/copy-button.js @@ -8,7 +8,7 @@ let buttonTemplate * Initializes copy buttons. */ -window.addEventListener('swup:page:view', initialize) +window.addEventListener('exdoc:loaded', initialize) initialize() function initialize () { diff --git a/assets/js/makeup.js b/assets/js/makeup.js index cb867aa44..99009b58a 100644 --- a/assets/js/makeup.js +++ b/assets/js/makeup.js @@ -6,7 +6,7 @@ const HIGHLIGHT_CLASS = 'hll' * Sets up dynamic behaviour for code blocks processed with *makeup*. */ -window.addEventListener('swup:page:view', initialize) +window.addEventListener('exdoc:loaded', initialize) initialize() export function initialize () { diff --git a/assets/js/quick-switch.js b/assets/js/quick-switch.js index c36ef034a..4aaef5a15 100644 --- a/assets/js/quick-switch.js +++ b/assets/js/quick-switch.js @@ -74,7 +74,7 @@ const state = { */ if (!isEmbedded) { - window.addEventListener('swup:page:view', initialize) + window.addEventListener('exdoc:loaded', initialize) initialize() } diff --git a/assets/js/search-bar.js b/assets/js/search-bar.js index 25e555c97..9d123fa7b 100644 --- a/assets/js/search-bar.js +++ b/assets/js/search-bar.js @@ -21,7 +21,7 @@ const SEARCH_CLOSE_BUTTON_SELECTOR = 'form.search-bar .search-close-button' */ if (!isEmbedded) { - window.addEventListener('swup:page:view', initialize) + window.addEventListener('exdoc:loaded', initialize) initialize() } diff --git a/assets/js/search-page.js b/assets/js/search-page.js index a60b95c72..4df9b281f 100644 --- a/assets/js/search-page.js +++ b/assets/js/search-page.js @@ -20,7 +20,7 @@ lunr.Pipeline.registerFunction(docTrimmerFunction, 'docTrimmer') * Activates only on the `/search.html` page. */ -window.addEventListener('swup:page:view', initialize) +window.addEventListener('exdoc:loaded', initialize) initialize() function initialize () { diff --git a/assets/js/settings.js b/assets/js/settings.js index e77cee4d7..b46823ae0 100644 --- a/assets/js/settings.js +++ b/assets/js/settings.js @@ -26,7 +26,7 @@ const modalTabs = [ * Sets up the settings modal. */ -window.addEventListener('swup:page:view', initialize) +window.addEventListener('exdoc:loaded', initialize) initialize() function initialize () { diff --git a/assets/js/sidebar/sidebar-drawer.js b/assets/js/sidebar/sidebar-drawer.js index 00bb25130..f0262bb6d 100644 --- a/assets/js/sidebar/sidebar-drawer.js +++ b/assets/js/sidebar/sidebar-drawer.js @@ -13,7 +13,7 @@ const smallScreenQuery = window.matchMedia(`screen and (max-width: ${SMALL_SCREE 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) diff --git a/assets/js/sidebar/sidebar-list.js b/assets/js/sidebar/sidebar-list.js index 5838d61f3..54515d9b3 100644 --- a/assets/js/sidebar/sidebar-list.js +++ b/assets/js/sidebar/sidebar-list.js @@ -89,7 +89,7 @@ export function initialize () { }) window.addEventListener('hashchange', markCurrentHashInSidebar) - window.addEventListener('swup:page:view', markCurrentHashInSidebar) + window.addEventListener('exdoc:loaded', markCurrentHashInSidebar) markCurrentHashInSidebar() // Triggers layout, defer. diff --git a/assets/js/swup.js b/assets/js/swup.js index b56789733..12b661185 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,9 @@ 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..7c7c2002b 100644 --- a/assets/js/tabsets.js +++ b/assets/js/tabsets.js @@ -6,7 +6,7 @@ const TABSET_CLOSE_COMMENT = 'tabs-close' const TABPANEL_HEADING_NODENAME = 'H3' const TABSET_CONTAINER_CLASS = 'tabset' -window.addEventListener('swup:page:view', initialize) +window.addEventListener('exdoc:loaded', initialize) initialize() function initialize () { diff --git a/assets/js/tooltips/tooltips.js b/assets/js/tooltips/tooltips.js index b37b756a7..cdd9fcf9e 100644 --- a/assets/js/tooltips/tooltips.js +++ b/assets/js/tooltips/tooltips.js @@ -40,7 +40,7 @@ const state = { * Initializes tooltips handling. */ -window.addEventListener('swup:page:view', initialize) +window.addEventListener('exdoc:loaded', initialize) initialize() function initialize () { From 59633519a3612616fdd7508e4d0396fc5d8eb428 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Fri, 24 Jan 2025 19:51:49 +0100 Subject: [PATCH 2/7] Fix lint --- assets/js/swup.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/assets/js/swup.js b/assets/js/swup.js index 12b661185..6f9fccd6b 100644 --- a/assets/js/swup.js +++ b/assets/js/swup.js @@ -21,7 +21,6 @@ if (!isEmbedded && window.location.protocol !== 'file:') { }) window.addEventListener('swup:page:view', () => { - window.dispatchEvent(new Event('exdoc:loaded')); + window.dispatchEvent(new Event('exdoc:loaded')) }) } - From e2c8e93c24cc9556fc0386170cee56d7d51ac0d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Fri, 24 Jan 2025 20:03:56 +0100 Subject: [PATCH 3/7] Remove duped initialize --- assets/js/content.js | 1 - assets/js/copy-button.js | 1 - assets/js/makeup.js | 1 - assets/js/quick-switch.js | 1 - assets/js/search-bar.js | 1 - assets/js/search-page.js | 1 - assets/js/settings.js | 1 - assets/js/tabsets.js | 1 - assets/js/tooltips/tooltips.js | 1 - 9 files changed, 9 deletions(-) diff --git a/assets/js/content.js b/assets/js/content.js index f8e4b8ac6..e04f09eb0 100644 --- a/assets/js/content.js +++ b/assets/js/content.js @@ -7,7 +7,6 @@ import { settingsStore } from './settings-store' */ window.addEventListener('exdoc:loaded', initialize) -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 ed420b8e8..a3171e9dd 100644 --- a/assets/js/copy-button.js +++ b/assets/js/copy-button.js @@ -9,7 +9,6 @@ let buttonTemplate */ window.addEventListener('exdoc:loaded', initialize) -initialize() function initialize () { if (!('clipboard' in navigator)) return diff --git a/assets/js/makeup.js b/assets/js/makeup.js index 99009b58a..758255af2 100644 --- a/assets/js/makeup.js +++ b/assets/js/makeup.js @@ -7,7 +7,6 @@ const HIGHLIGHT_CLASS = 'hll' */ window.addEventListener('exdoc:loaded', initialize) -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 4aaef5a15..08ab4b340 100644 --- a/assets/js/quick-switch.js +++ b/assets/js/quick-switch.js @@ -75,7 +75,6 @@ const state = { if (!isEmbedded) { window.addEventListener('exdoc:loaded', initialize) - initialize() } function initialize () { diff --git a/assets/js/search-bar.js b/assets/js/search-bar.js index 9d123fa7b..2e50e04e4 100644 --- a/assets/js/search-bar.js +++ b/assets/js/search-bar.js @@ -22,7 +22,6 @@ const SEARCH_CLOSE_BUTTON_SELECTOR = 'form.search-bar .search-close-button' if (!isEmbedded) { window.addEventListener('exdoc:loaded', initialize) - initialize() } function initialize () { diff --git a/assets/js/search-page.js b/assets/js/search-page.js index 4df9b281f..7f647b4bd 100644 --- a/assets/js/search-page.js +++ b/assets/js/search-page.js @@ -21,7 +21,6 @@ lunr.Pipeline.registerFunction(docTrimmerFunction, 'docTrimmer') */ window.addEventListener('exdoc:loaded', initialize) -initialize() function initialize () { const pathname = window.location.pathname diff --git a/assets/js/settings.js b/assets/js/settings.js index b46823ae0..4e21d82fe 100644 --- a/assets/js/settings.js +++ b/assets/js/settings.js @@ -27,7 +27,6 @@ const modalTabs = [ */ window.addEventListener('exdoc:loaded', initialize) -initialize() function initialize () { qsAll(SETTINGS_LINK_SELECTOR).forEach(element => { diff --git a/assets/js/tabsets.js b/assets/js/tabsets.js index 7c7c2002b..6d60eb142 100644 --- a/assets/js/tabsets.js +++ b/assets/js/tabsets.js @@ -7,7 +7,6 @@ const TABPANEL_HEADING_NODENAME = 'H3' const TABSET_CONTAINER_CLASS = 'tabset' window.addEventListener('exdoc:loaded', initialize) -initialize() function initialize () { /** @type {[Node, [NodeList, HTMLElement[]][]][]} */ diff --git a/assets/js/tooltips/tooltips.js b/assets/js/tooltips/tooltips.js index cdd9fcf9e..8bb5ef1b5 100644 --- a/assets/js/tooltips/tooltips.js +++ b/assets/js/tooltips/tooltips.js @@ -41,7 +41,6 @@ const state = { */ window.addEventListener('exdoc:loaded', initialize) -initialize() function initialize () { qsAll(TOOLTIP_ACTIVATORS_SELECTOR).forEach(element => { From 4096b992b93dd853157d49d54d1c5ab8d711a1ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Fri, 24 Jan 2025 20:06:57 +0100 Subject: [PATCH 4/7] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 215bc3dc6..69212f646 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 `def`, 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: From 35908f4646d2b61a546fb889634475b8b6b12313 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Fri, 24 Jan 2025 20:17:50 +0100 Subject: [PATCH 5/7] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jonatan KÅ‚osko --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 69212f646..ee9bb8c34 100644 --- a/README.md +++ b/README.md @@ -370,7 +370,7 @@ 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 `def`, not async, as shown in the examples below. +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 From 2b8fe60ab29ec8abdad63aa900530de10676a6f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 25 Jan 2025 10:14:56 +0100 Subject: [PATCH 6/7] Remove duplication --- assets/js/sidebar/sidebar-drawer.js | 2 -- assets/js/sidebar/sidebar-list.js | 1 - 2 files changed, 3 deletions(-) diff --git a/assets/js/sidebar/sidebar-drawer.js b/assets/js/sidebar/sidebar-drawer.js index f0262bb6d..bb9206108 100644 --- a/assets/js/sidebar/sidebar-drawer.js +++ b/assets/js/sidebar/sidebar-drawer.js @@ -11,8 +11,6 @@ const SIDEBAR_TOGGLE_SELECTOR = '.sidebar-toggle' const smallScreenQuery = window.matchMedia(`screen and (max-width: ${SMALL_SCREEN_BREAKPOINT}px)`) if (!isEmbedded) { - setDefaultSidebarState() - window.addEventListener('exdoc:loaded', setDefaultSidebarState) const sidebar = document.getElementById('sidebar') diff --git a/assets/js/sidebar/sidebar-list.js b/assets/js/sidebar/sidebar-list.js index 54515d9b3..716ddbda3 100644 --- a/assets/js/sidebar/sidebar-list.js +++ b/assets/js/sidebar/sidebar-list.js @@ -91,7 +91,6 @@ export function initialize () { window.addEventListener('hashchange', markCurrentHashInSidebar) window.addEventListener('exdoc:loaded', markCurrentHashInSidebar) - markCurrentHashInSidebar() // Triggers layout, defer. requestAnimationFrame(scrollNodeListToCurrentCategory) } From 0916d53212cc60953a118fe171f23eb82a63852e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 25 Jan 2025 10:24:29 +0100 Subject: [PATCH 7/7] Revert to swup on list --- assets/js/sidebar/sidebar-drawer.js | 1 + assets/js/sidebar/sidebar-list.js | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/assets/js/sidebar/sidebar-drawer.js b/assets/js/sidebar/sidebar-drawer.js index bb9206108..b6f0022c8 100644 --- a/assets/js/sidebar/sidebar-drawer.js +++ b/assets/js/sidebar/sidebar-drawer.js @@ -47,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 716ddbda3..a76b0dfdf 100644 --- a/assets/js/sidebar/sidebar-list.js +++ b/assets/js/sidebar/sidebar-list.js @@ -89,7 +89,11 @@ export function initialize () { }) window.addEventListener('hashchange', markCurrentHashInSidebar) - window.addEventListener('exdoc:loaded', 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)