Skip to content

Commit e6e4e66

Browse files
deploy: 343e939
1 parent c7ae1d3 commit e6e4e66

4 files changed

Lines changed: 222 additions & 582 deletions

File tree

.doctrees/environment.pickle

31 Bytes
Binary file not shown.

genindex.html

Lines changed: 74 additions & 194 deletions
Original file line numberDiff line numberDiff line change
@@ -344,179 +344,13 @@ <h2>T</h2>
344344
import elkLayouts from "https://cdn.jsdelivr.net/npm/@mermaid-js/layout-elk@0.2.0/dist/mermaid-layout-elk.esm.min.mjs"
345345

346346

347-
348-
import zenumlLayouts from "https://cdn.jsdelivr.net/npm/@mermaid-js/mermaid-zenuml@0.2.2/dist/mermaid-zenuml.esm.min.mjs"
349-
350-
351347
const initStyles = () => {
352348
const defaultStyle = document.createElement('style');
353-
defaultStyle.textContent = `pre.mermaid {
354-
/* Same as .mermaid-container > pre */
355-
display: block;
356-
width: 100%;
357-
}
358-
359-
pre.mermaid > svg {
360-
/* Same as .mermaid-container > pre > svg */
361-
height: 500px;
362-
width: 100%;
363-
max-width: 100% !important;
364-
}`;
349+
defaultStyle.textContent = "pre.mermaid {\n /* Same as .mermaid-container > pre */\n display: block;\n width: 100%;\n}\n\npre.mermaid > svg {\n /* Same as .mermaid-container > pre > svg */\n height: 500px;\n width: 100%;\n max-width: 100% !important;\n}";
365350
document.head.appendChild(defaultStyle);
366351

367352
const fullscreenStyle = document.createElement('style');
368-
fullscreenStyle.textContent = `.mermaid-container {
369-
display: flex;
370-
flex-direction: row;
371-
width: 100%;
372-
}
373-
374-
.mermaid-container > pre {
375-
display: block;
376-
width: 100%;
377-
}
378-
379-
.mermaid-container > pre > svg {
380-
height: 500px;
381-
width: 100%;
382-
max-width: 100% !important;
383-
}
384-
385-
.mermaid-fullscreen-btn {
386-
width: 28px;
387-
height: 28px;
388-
background: rgba(255, 255, 255, 0.95);
389-
border: 1px solid rgba(0, 0, 0, 0.3);
390-
border-radius: 4px;
391-
cursor: pointer;
392-
display: flex;
393-
align-items: center;
394-
justify-content: center;
395-
transition: all 0.2s;
396-
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
397-
font-size: 14px;
398-
line-height: 1;
399-
padding: 0;
400-
color: #333;
401-
}
402-
403-
.mermaid-fullscreen-btn:hover {
404-
opacity: 100% !important;
405-
background: rgba(255, 255, 255, 1);
406-
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.3);
407-
transform: scale(1.1);
408-
}
409-
410-
.mermaid-fullscreen-btn.dark-theme {
411-
background: rgba(50, 50, 50, 0.95);
412-
border: 1px solid rgba(255, 255, 255, 0.3);
413-
color: #e0e0e0;
414-
}
415-
416-
.mermaid-fullscreen-btn.dark-theme:hover {
417-
background: rgba(60, 60, 60, 1);
418-
box-shadow: 0 3px 10px rgba(255, 255, 255, 0.2);
419-
}
420-
421-
.mermaid-fullscreen-modal {
422-
display: none;
423-
position: fixed !important;
424-
top: 0 !important;
425-
left: 0 !important;
426-
width: 95vw;
427-
height: 100vh;
428-
background: rgba(255, 255, 255, 0.98);
429-
z-index: 9999;
430-
padding: 20px;
431-
overflow: auto;
432-
}
433-
434-
.mermaid-fullscreen-modal.dark-theme {
435-
background: rgba(0, 0, 0, 0.98);
436-
}
437-
438-
.mermaid-fullscreen-modal.active {
439-
display: flex;
440-
align-items: center;
441-
justify-content: center;
442-
}
443-
444-
.mermaid-container-fullscreen {
445-
position: relative;
446-
width: 95vw;
447-
height: 90vh;
448-
max-width: 95vw;
449-
max-height: 90vh;
450-
background: white;
451-
border-radius: 8px;
452-
padding: 20px;
453-
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
454-
overflow: auto;
455-
display: flex;
456-
align-items: center;
457-
justify-content: center;
458-
}
459-
460-
.mermaid-container-fullscreen.dark-theme {
461-
background: #1a1a1a;
462-
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.8);
463-
}
464-
465-
.mermaid-container-fullscreen pre.mermaid {
466-
width: 100%;
467-
height: 100%;
468-
display: flex;
469-
align-items: center;
470-
justify-content: center;
471-
}
472-
473-
.mermaid-container-fullscreen .mermaid svg {
474-
height: 100% !important;
475-
width: 100% !important;
476-
cursor: grab;
477-
}
478-
479-
.mermaid-fullscreen-close {
480-
position: fixed !important;
481-
top: 20px !important;
482-
right: 20px !important;
483-
width: 40px;
484-
height: 40px;
485-
background: rgba(255, 255, 255, 0.95);
486-
border: 1px solid rgba(0, 0, 0, 0.2);
487-
border-radius: 50%;
488-
cursor: pointer;
489-
z-index: 10000;
490-
display: flex;
491-
align-items: center;
492-
justify-content: center;
493-
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
494-
transition: all 0.2s;
495-
font-size: 24px;
496-
line-height: 1;
497-
color: #333;
498-
}
499-
500-
.mermaid-fullscreen-close:hover {
501-
background: white;
502-
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);
503-
transform: scale(1.1);
504-
}
505-
506-
.mermaid-fullscreen-close.dark-theme {
507-
background: rgba(50, 50, 50, 0.95);
508-
border: 1px solid rgba(255, 255, 255, 0.2);
509-
color: #e0e0e0;
510-
}
511-
512-
.mermaid-fullscreen-close.dark-theme:hover {
513-
background: rgba(60, 60, 60, 1);
514-
box-shadow: 0 6px 16px rgba(255, 255, 255, 0.2);
515-
}
516-
517-
.mermaid-fullscreen-modal .mermaid-fullscreen-btn {
518-
display: none !important;
519-
}`;
353+
fullscreenStyle.textContent = ".mermaid-container {\n position: relative;\n display: flex;\n flex-direction: row;\n width: 100%;\n}\n\n.mermaid-container > pre {\n display: block;\n width: 100%;\n}\n\n.mermaid-container > pre > svg {\n height: 500px;\n width: 100%;\n max-width: 100% !important;\n}\n\n.mermaid-fullscreen-btn {\n position: absolute;\n width: 28px;\n height: 28px;\n background: rgba(255, 255, 255, 0.95);\n border: 1px solid rgba(0, 0, 0, 0.3);\n border-radius: 4px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);\n font-size: 14px;\n line-height: 1;\n padding: 0;\n color: #333;\n}\n\n.mermaid-fullscreen-btn:hover {\n opacity: 100% !important;\n background: rgba(255, 255, 255, 1);\n box-shadow: 0 3px 10px rgba(0, 0, 0, 0.3);\n transform: scale(1.1);\n}\n\n.mermaid-fullscreen-btn.dark-theme {\n background: rgba(50, 50, 50, 0.95);\n border: 1px solid rgba(255, 255, 255, 0.3);\n color: #e0e0e0;\n}\n\n.mermaid-fullscreen-btn.dark-theme:hover {\n background: rgba(60, 60, 60, 1);\n box-shadow: 0 3px 10px rgba(255, 255, 255, 0.2);\n}\n\n.mermaid-fullscreen-modal {\n display: none;\n position: fixed !important;\n top: 0 !important;\n left: 0 !important;\n width: 95vw;\n height: 100vh;\n background: rgba(255, 255, 255, 0.98);\n z-index: 9999;\n padding: 20px;\n overflow: auto;\n}\n\n.mermaid-fullscreen-modal.dark-theme {\n background: rgba(0, 0, 0, 0.98);\n}\n\n.mermaid-fullscreen-modal.active {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.mermaid-container-fullscreen {\n position: relative;\n width: 95vw;\n height: 90vh;\n max-width: 95vw;\n max-height: 90vh;\n background: white;\n border-radius: 8px;\n padding: 20px;\n box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);\n overflow: auto;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.mermaid-container-fullscreen.dark-theme {\n background: #1a1a1a;\n box-shadow: 0 10px 40px rgba(0, 0, 0, 0.8);\n}\n\n.mermaid-container-fullscreen pre.mermaid {\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.mermaid-container-fullscreen .mermaid svg {\n height: 100% !important;\n width: 100% !important;\n cursor: grab;\n}\n\n.mermaid-fullscreen-close {\n position: fixed !important;\n top: 20px !important;\n right: 20px !important;\n width: 40px;\n height: 40px;\n background: rgba(255, 255, 255, 0.95);\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 50%;\n cursor: pointer;\n z-index: 10000;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n transition: all 0.2s;\n font-size: 24px;\n line-height: 1;\n color: #333;\n}\n\n.mermaid-fullscreen-close:hover {\n background: white;\n box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);\n transform: scale(1.1);\n}\n\n.mermaid-fullscreen-close.dark-theme {\n background: rgba(50, 50, 50, 0.95);\n border: 1px solid rgba(255, 255, 255, 0.2);\n color: #e0e0e0;\n}\n\n.mermaid-fullscreen-close.dark-theme:hover {\n background: rgba(60, 60, 60, 1);\n box-shadow: 0 6px 16px rgba(255, 255, 255, 0.2);\n}\n\n.mermaid-fullscreen-modal .mermaid-fullscreen-btn {\n display: none !important;\n}";
520354
document.head.appendChild(fullscreenStyle);
521355
}
522356

@@ -563,6 +397,13 @@ <h2>T</h2>
563397
let previousScrollOffset = [window.scrollX, window.scrollY];
564398
let _lazyObserver = null;
565399
let _renderQueue = Promise.resolve();
400+
let closeModal = () => {};
401+
402+
document.addEventListener('keydown', (e) => {
403+
if (e.key === 'Escape' && modal?.classList.contains('active')) {
404+
closeModal();
405+
}
406+
});
566407

567408
// Apply d3 zoom to each SVG. Idempotent: an SVG already wrapped is skipped,
568409
// so this is safe to call both for the initial batch and for diagrams that
@@ -659,8 +500,10 @@ <h2>T</h2>
659500
el.removeAttribute('data-mermaid-deferred');
660501
// Apply zoom to the now-rendered diagram, matching
661502
// the decoration visible diagrams receive.
662-
if ("True" === "True") {
663-
addZoomToSvgs(d3.selectAll(".mermaid svg"));
503+
if (true) {
504+
addZoomToSvgs(d3.selectAll(".mermaid").select(function() {
505+
return this.querySelector("svg");
506+
}));
664507
}
665508
} catch (e) {
666509
console.error("Mermaid deferred rendering failed:", e);
@@ -681,10 +524,12 @@ <h2>T</h2>
681524
const mermaids_active = document.querySelectorAll(".mermaid:not([data-mermaid-deferred]):not([data-mermaid-render-failed])");
682525
const mermaids_processed = document.querySelectorAll(".mermaid:not([data-mermaid-deferred]):not([data-mermaid-render-failed])[data-processed='true']");
683526

684-
if ("True" === "True") {
527+
if (true) {
685528
const mermaids_to_add_zoom = -1 === -1 ? mermaids_active.length : -1;
686529
if(mermaids_to_add_zoom > 0) {
687-
var svgs = d3.selectAll(".mermaid svg");
530+
var svgs = d3.selectAll(".mermaid").select(function() {
531+
return this.querySelector("svg");
532+
});
688533
// Wait until every active (visible) diagram has rendered. Deferred
689534
// diagrams are excluded, so a fixed d3_node_count that counts a
690535
// hidden diagram no longer loops forever waiting for its SVG.
@@ -701,7 +546,7 @@ <h2>T</h2>
701546
}
702547

703548
// Stop here if not adding fullscreen capability
704-
if ("True" !== "True") return;
549+
if (!true) return;
705550

706551
if (modal !== null ) {
707552
// Destroy existing modal
@@ -724,7 +569,7 @@ <h2>T</h2>
724569
modalContent = modal.querySelector('.mermaid-container-fullscreen');
725570
const closeBtn = modal.querySelector('.mermaid-fullscreen-close');
726571

727-
const closeModal = () => {
572+
closeModal = () => {
728573
modal.classList.remove('active');
729574
modalContent.innerHTML = '';
730575
document.body.style.overflow = ''
@@ -735,12 +580,6 @@ <h2>T</h2>
735580
modal.addEventListener('click', (e) => {
736581
if (e.target === modal) closeModal();
737582
});
738-
document.addEventListener('keydown', (e) => {
739-
if (e.key === 'Escape' && modal.classList.contains('active')) {
740-
closeModal();
741-
}
742-
});
743-
744583
document.querySelectorAll('.mermaid').forEach((mermaidDiv) => {
745584
if (mermaidDiv.parentNode.classList.contains('mermaid-container') ||
746585
mermaidDiv.closest('.mermaid-fullscreen-modal')) {
@@ -760,8 +599,8 @@ <h2>T</h2>
760599
const fullscreenBtn = document.createElement('button');
761600
fullscreenBtn.className = 'mermaid-fullscreen-btn' + (darkTheme ? ' dark-theme' : '');
762601
fullscreenBtn.setAttribute('aria-label', 'View diagram in fullscreen');
763-
fullscreenBtn.textContent = '⛶';
764-
fullscreenBtn.style.opacity = '50%';
602+
fullscreenBtn.textContent = "\u26f6";
603+
fullscreenBtn.style.opacity = "50%";
765604

766605
// Calculate dynamic position based on diagram's margin and padding
767606
const diagramStyle = window.getComputedStyle(mermaidDiv);
@@ -773,7 +612,7 @@ <h2>T</h2>
773612
fullscreenBtn.style.right = `${marginRight + paddingRight + 4}px`;
774613

775614
fullscreenBtn.addEventListener('click', () => {
776-
previousScrollOffset = [window.scroll, window.scrollY];
615+
previousScrollOffset = [window.scrollX, window.scrollY];
777616
const clone = mermaidDiv.cloneNode(true);
778617
modalContent.innerHTML = '';
779618
modalContent.appendChild(clone);
@@ -785,9 +624,9 @@ <h2>T</h2>
785624
svg.style.width = '100%';
786625
svg.style.height = 'auto';
787626
svg.style.maxWidth = '100%';
788-
svg.style.sdisplay = 'block';
627+
svg.style.display = 'block';
789628

790-
if ("True" === "True") {
629+
if (true) {
791630
setTimeout(() => {
792631
const g = svg.querySelector('g');
793632
if (g) {
@@ -810,9 +649,27 @@ <h2>T</h2>
810649
});
811650
};
812651

652+
653+
// Resolves once the lazily-loaded zenuml plugin has registered (or immediately
654+
// when the page has no zenuml diagram). `load` awaits this before rendering.
655+
let zenumlReady = Promise.resolve();
656+
const pageHasZenuml = () => [...document.querySelectorAll(".mermaid")].some((el) => {
657+
const code = el.getAttribute("data-original-code") || el.textContent || "";
658+
const diagram = code
659+
.replace(/^\s*---\s*\n[^]*?\n---\s*/, "")
660+
.replace(/^\s*%%\{[^]*?\}%%\s*/, "");
661+
return /^\s*zenuml\b/i.test(diagram);
662+
});
663+
664+
813665
const load = async () => {
814666
initStyles();
815667

668+
669+
// Wait for the zenuml plugin (loaded lazily below) to finish registering
670+
// before rendering, so zenuml diagrams are recognised.
671+
await zenumlReady;
672+
816673
await runMermaid(true);
817674

818675
const reRunIfThemeChanges = async () => {
@@ -821,10 +678,8 @@ <h2>T</h2>
821678
darkTheme = newDarkTheme;
822679
console.log("Theme change detected, re-running mermaid with", darkTheme ? "dark" : "default", "theme");
823680
await mermaid.initialize(
824-
{...JSON.parse(
825-
`{"startOnLoad": false}`
826-
),
827-
...{ darkMode: darkTheme, theme: darkTheme ? 'dark' : 'default' },
681+
{...{"startOnLoad": false},
682+
...{ darkMode: darkTheme, theme: darkTheme ? "dark" : "default" },
828683
}
829684
);
830685
await runMermaid(true);
@@ -848,15 +703,40 @@ <h2>T</h2>
848703

849704

850705

851-
mermaid.registerExternalDiagrams([zenumlLayouts]);
706+
// Only load and register the zenuml plugin when the page actually contains a
707+
// zenuml diagram. This avoids fetching the (large) zenuml bundle on every page,
708+
// and avoids its side effects where they are not needed. The import is kept off
709+
// the module's top level (no top-level await) so the "load" listener below is
710+
// still registered synchronously; `load` awaits `zenumlReady` before rendering.
711+
if (pageHasZenuml()) {
712+
// The zenuml bundle injects a stylesheet that declares generic design tokens
713+
// (--background, --border, --white, ...) on :root, clobbering identically-named
714+
// tokens in the host theme (sphinxawesome, shibuya, ...) and causing a flash of
715+
// restyled page content. Confine those declarations to the zenuml diagram
716+
// subtree so they no longer leak onto the host page.
717+
const descopeZenumlStyle = (node) => {
718+
if (!node || node.tagName !== "STYLE" || node.hasAttribute("data-zenuml-descoped")) return;
719+
const css = node.textContent || "";
720+
if (!css.includes("--occurance-border")) return; // zenuml stylesheet signature
721+
node.setAttribute("data-zenuml-descoped", "true");
722+
node.textContent = css.replace(/:root\b/g, ".zenuml");
723+
};
724+
new MutationObserver((records) => {
725+
for (const rec of records) {
726+
for (const node of rec.addedNodes) descopeZenumlStyle(node);
727+
}
728+
}).observe(document.head, { childList: true });
729+
730+
zenumlReady = import("https://cdn.jsdelivr.net/npm/@mermaid-js/mermaid-zenuml@0.2.2/dist/mermaid-zenuml.esm.min.mjs").then(({ default: zenumlLayouts }) => {
731+
mermaid.registerExternalDiagrams([zenumlLayouts]);
732+
});
733+
}
852734

853735

854736
console.log("Initializing mermaid with", darkTheme ? "dark" : "default", "theme");
855737
mermaid.initialize(
856-
{...JSON.parse(
857-
`{"startOnLoad": false}`
858-
),
859-
...{ darkMode: darkTheme, theme: darkTheme ? 'dark' : 'default' },
738+
{...{"startOnLoad": false},
739+
...{ darkMode: darkTheme, theme: darkTheme ? "dark" : "default" },
860740
}
861741
);
862742

0 commit comments

Comments
 (0)