From 9e3e711646e3db281da11aeb08fc7a10a8dd3be4 Mon Sep 17 00:00:00 2001
From: Jacky Zhao <j.zhao2k19@gmail.com>
Date: Mon, 10 Mar 2025 23:20:08 +0000
Subject: [PATCH] fix: mermaid script load order

---
 quartz/components/renderPage.tsx            |   16 ++++----
 quartz/components/scripts/spa.inline.ts     |   29 +++++++++-----
 quartz/components/scripts/callout.inline.ts |   14 +++----
 docs/index.md                               |    4 +-
 4 files changed, 34 insertions(+), 29 deletions(-)

diff --git a/docs/index.md b/docs/index.md
index e41c171..d4a751a 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -31,13 +31,13 @@
 
 ## 🔧 Features
 
-- [[Obsidian compatibility]], [[full-text search]], [[graph view]], note transclusion, [[wikilinks]], [[backlinks]], [[features/Latex|Latex]], [[syntax highlighting]], [[popover previews]], [[Docker Support]], [[i18n|internationalization]], [[comments]] and [many more](./features) right out of the box
+- [[Obsidian compatibility]], [[full-text search]], [[graph view]], note transclusion, [[wikilinks]], [[backlinks]], [[features/Latex|Latex]], [[syntax highlighting]], [[popover previews]], [[Docker Support]], [[i18n|internationalization]], [[comments]] and [many more](./features/) right out of the box
 - Hot-reload for both configuration and content
 - Simple JSX layouts and [[creating components|page components]]
 - [[SPA Routing|Ridiculously fast page loads]] and tiny bundle sizes
 - Fully-customizable parsing, filtering, and page generation through [[making plugins|plugins]]
 
-For a comprehensive list of features, visit the [features page](/features). You can read more about the _why_ behind these features on the [[philosophy]] page and a technical overview on the [[architecture]] page.
+For a comprehensive list of features, visit the [features page](./features/). You can read more about the _why_ behind these features on the [[philosophy]] page and a technical overview on the [[architecture]] page.
 
 ### 🚧 Troubleshooting + Updating
 
diff --git a/quartz/components/renderPage.tsx b/quartz/components/renderPage.tsx
index 75ef82b..cbf4af4 100644
--- a/quartz/components/renderPage.tsx
+++ b/quartz/components/renderPage.tsx
@@ -58,6 +58,14 @@
     additionalHead: staticResources.additionalHead,
   }
 
+  resources.js.push({
+    src: joinSegments(baseDir, "postscript.js"),
+    loadTime: "afterDOMReady",
+    moduleType: "module",
+    contentType: "external",
+  })
+
+  // dynamic afterDOMReady must come after postscript.js
   if (fileData.hasMermaidDiagram) {
     resources.js.push({
       script: mermaidScript,
@@ -68,14 +76,6 @@
     resources.css.push({ content: mermaidStyle, inline: true })
   }
 
-  // NOTE: we have to put this last to make sure spa.inline.ts is the last item.
-  resources.js.push({
-    src: joinSegments(baseDir, "postscript.js"),
-    loadTime: "afterDOMReady",
-    moduleType: "module",
-    contentType: "external",
-  })
-
   return resources
 }
 
diff --git a/quartz/components/scripts/callout.inline.ts b/quartz/components/scripts/callout.inline.ts
index 8f63df3..3b7e16d 100644
--- a/quartz/components/scripts/callout.inline.ts
+++ b/quartz/components/scripts/callout.inline.ts
@@ -28,17 +28,15 @@
   ) as HTMLCollectionOf<HTMLElement>
   for (const div of collapsible) {
     const title = div.firstElementChild
+    if (!title) continue
 
-    if (title) {
-      title.addEventListener("click", toggleCallout)
-      window.addCleanup(() => title.removeEventListener("click", toggleCallout))
+    title.addEventListener("click", toggleCallout)
+    window.addCleanup(() => title.removeEventListener("click", toggleCallout))
 
-      const collapsed = div.classList.contains("is-collapsed")
-      const height = collapsed ? title.scrollHeight : div.scrollHeight
-      div.style.maxHeight = height + "px"
-    }
+    const collapsed = div.classList.contains("is-collapsed")
+    const height = collapsed ? title.scrollHeight : div.scrollHeight
+    div.style.maxHeight = height + "px"
   }
 }
 
 document.addEventListener("nav", setupCallout)
-window.addEventListener("resize", setupCallout)
diff --git a/quartz/components/scripts/spa.inline.ts b/quartz/components/scripts/spa.inline.ts
index 77900a6..22fcd72 100644
--- a/quartz/components/scripts/spa.inline.ts
+++ b/quartz/components/scripts/spa.inline.ts
@@ -56,8 +56,10 @@
   }, 100)
 }
 
+let isNavigating = false
 let p: DOMParser
-async function navigate(url: URL, isBack: boolean = false) {
+async function _navigate(url: URL, isBack: boolean = false) {
+  isNavigating = true
   startLoading()
   p = p || new DOMParser()
   const contents = await fetchCanonical(url)
@@ -128,6 +130,19 @@
   delete announcer.dataset.persist
 }
 
+async function navigate(url: URL, isBack: boolean = false) {
+  if (isNavigating) return
+  isNavigating = true
+  try {
+    await _navigate(url, isBack)
+  } catch (e) {
+    console.error(e)
+    window.location.assign(url)
+  } finally {
+    isNavigating = false
+  }
+}
+
 window.spaNavigate = navigate
 
 function createRouter() {
@@ -145,21 +160,13 @@
         return
       }
 
-      try {
-        navigate(url, false)
-      } catch (e) {
-        window.location.assign(url)
-      }
+      navigate(url, false)
     })
 
     window.addEventListener("popstate", (event) => {
       const { url } = getOpts(event) ?? {}
       if (window.location.hash && window.location.pathname === url?.pathname) return
-      try {
-        navigate(new URL(window.location.toString()), true)
-      } catch (e) {
-        window.location.reload()
-      }
+      navigate(new URL(window.location.toString()), true)
       return
     })
   }

--
Gitblit v1.10.0