Files
prompts/docs/javascripts/mermaid-override.js
T
John Lancaster c3dc66b20f mermaid diagram
2026-06-18 21:49:08 -05:00

99 lines
2.3 KiB
JavaScript

let mermaidPromise;
async function getMermaid() {
if (!mermaidPromise) {
mermaidPromise = import("https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs").then(
(module) => {
const mermaid = module.default ?? module;
mermaid.initialize({ startOnLoad: false });
return mermaid;
},
);
}
return mermaidPromise;
}
function readDiagramSource(block) {
const code = block.querySelector("code");
return (code?.textContent ?? block.textContent ?? "").trim();
}
async function renderBlock(block) {
if (block.dataset.mermaidOverrideState) {
return;
}
const source = readDiagramSource(block);
if (!source) {
block.dataset.mermaidOverrideState = "empty";
return;
}
block.dataset.mermaidOverrideState = "pending";
try {
const mermaid = await getMermaid();
const replacement = document.createElement("div");
replacement.className = "mermaid";
replacement.textContent = source;
replacement.dataset.mermaidOverrideState = "rendered";
block.replaceWith(replacement);
await mermaid.run({ nodes: [replacement] });
} catch (error) {
block.dataset.mermaidOverrideState = "failed";
console.warn("Mermaid override failed", error);
}
}
function findBlocks(root = document) {
const blocks = [];
if (root instanceof Element && root.matches("pre.mermaid")) {
blocks.push(root);
}
if (root instanceof Document || root instanceof Element) {
blocks.push(...root.querySelectorAll("pre.mermaid"));
}
return blocks;
}
function renderAll(root = document) {
for (const block of findBlocks(root)) {
void renderBlock(block);
}
}
function installObserver() {
if (!(document.body instanceof HTMLBodyElement)) {
return;
}
const observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
for (const node of mutation.addedNodes) {
if (node instanceof Element) {
renderAll(node);
}
}
}
});
observer.observe(document.body, { childList: true, subtree: true });
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", () => {
renderAll();
installObserver();
});
} else {
renderAll();
installObserver();
}
window.addEventListener("pageshow", () => renderAll());
window.addEventListener("popstate", () => renderAll());