mirror of
https://github.com/hugo-fixit/FixIt.git
synced 2026-08-25 07:48:54 +00:00
♻️ Refactor: Mermaid theme switching again (#623)
This commit is contained in:
@@ -4,7 +4,7 @@ code {
|
||||
}
|
||||
|
||||
// indented code
|
||||
pre:not(.mermaid[data-processed]) {
|
||||
pre:not([data-processed]) {
|
||||
margin: 0;
|
||||
line-height: 1.45em;
|
||||
padding: 0.5rem;
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
.mermaid {
|
||||
.mermaid,
|
||||
.mermaid-dark,
|
||||
.mermaid-neutral {
|
||||
position: relative;
|
||||
overflow: hidden !important;
|
||||
|
||||
&[data-processed] {
|
||||
text-align: center;
|
||||
margin-block: 0.5rem;
|
||||
}
|
||||
|
||||
&:not([data-processed])::before {
|
||||
@@ -13,7 +16,7 @@
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
backdrop-filter: blur(0.5rem);
|
||||
backdrop-filter: blur(1rem);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-image: var(#{$rootPrefix}loading-img);
|
||||
@@ -25,3 +28,37 @@
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.mermaid {
|
||||
[data-theme='dark'] & {
|
||||
height: 0;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.mermaid-dark {
|
||||
height: 0;
|
||||
padding: 0 !important;
|
||||
|
||||
[data-theme='dark'] & {
|
||||
height: auto;
|
||||
padding: 0.5rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
// for print view
|
||||
.mermaid-neutral {
|
||||
height: 0;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
@media only print {
|
||||
.mermaid,
|
||||
.mermaid-dark {
|
||||
display: none;
|
||||
}
|
||||
.mermaid-neutral {
|
||||
height: auto;
|
||||
padding: 0.5rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
+101
-4
@@ -1,10 +1,107 @@
|
||||
{{- $mermaid := .Param "mermaid" -}}
|
||||
{{- $mermaidCDN := $mermaid.cdn | default "https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.esm.min.mjs" -}}
|
||||
|
||||
import mermaid from "{{ $mermaidCDN }}";
|
||||
import mermaid from "{{ $mermaidCDN }}"
|
||||
{{- with $mermaid.zenuml }}
|
||||
import zenuml from "{{ . }}";
|
||||
await mermaid.registerExternalDiagrams([zenuml]);
|
||||
import zenuml from "{{ . }}"
|
||||
await mermaid.registerExternalDiagrams([zenuml])
|
||||
{{- end }}
|
||||
mermaid.startOnLoad = false;
|
||||
window.mermaid = mermaid;
|
||||
const mermaidConfig = {{ $mermaid | jsonify }}
|
||||
let processing = false
|
||||
let delayTask = null
|
||||
|
||||
/**
|
||||
* Get current/next theme
|
||||
* @param {Boolean} [next] whether to get the next theme
|
||||
* @returns
|
||||
*/
|
||||
function getTheme(next) {
|
||||
const darkMode = document.documentElement.dataset.theme === 'dark'
|
||||
return (next ? !darkMode : darkMode)
|
||||
? mermaidConfig.themes[1]
|
||||
: mermaidConfig.themes[0]
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize Mermaid by loading the specified theme
|
||||
* @param {String} [theme] specific theme to load
|
||||
* @param {Boolean} [darkMode] whether to use dark mode
|
||||
* @param {String} [selector] specific selector for the elements to process
|
||||
* @returns
|
||||
*/
|
||||
async function loadMermaid({ theme, darkMode, selector }) {
|
||||
if (processing) {
|
||||
console.warn('Mermaid is still processing, delaying the reload.')
|
||||
delayTask = () => loadMermaid({ theme, darkMode, selector })
|
||||
return
|
||||
}
|
||||
const isDarkMode = darkMode ?? (document.documentElement.dataset.theme === 'dark')
|
||||
const currentTheme = theme ?? getTheme()
|
||||
const querySelector = selector ?? (isDarkMode ? '.mermaid-dark' : '.mermaid')
|
||||
const nodes = document.querySelectorAll(querySelector)
|
||||
|
||||
if (!nodes.length) return
|
||||
|
||||
console.time(`Loaded [${currentTheme}]`)
|
||||
processing = true
|
||||
nodes.forEach((node) => {
|
||||
node.toggleAttribute('data-processing', true)
|
||||
})
|
||||
|
||||
// https://mermaid.js.org/config/schema-docs/config.html
|
||||
mermaid.initialize({
|
||||
startOnLoad: false,
|
||||
darkMode: isDarkMode,
|
||||
theme: currentTheme,
|
||||
securityLevel: mermaidConfig.securityLevel,
|
||||
look: mermaidConfig.look,
|
||||
fontFamily: mermaidConfig.fontFamily,
|
||||
altFontFamily: mermaidConfig.fontFamily
|
||||
})
|
||||
// skip data-processed elements in Mermaid run function, so this won't re-render
|
||||
await mermaid.run({
|
||||
nodes,
|
||||
suppressErrors: true,
|
||||
postRenderCallback: (svgId) => {
|
||||
document.getElementById(svgId).parentElement.toggleAttribute('data-processing', false)
|
||||
},
|
||||
})
|
||||
processing = false
|
||||
console.timeEnd(`Loaded [${currentTheme}]`)
|
||||
|
||||
if (delayTask && typeof delayTask === 'function') {
|
||||
delayTask();
|
||||
delayTask = null;
|
||||
// console.log('Delayed task executed');
|
||||
}
|
||||
}
|
||||
|
||||
async function initMermaid() {
|
||||
const contentEl = document.getElementById('content');
|
||||
if (!contentEl || !contentEl.innerHTML) return
|
||||
const currentTheme = getTheme()
|
||||
const nextTheme = getTheme(true)
|
||||
const darkMode = document.documentElement.dataset.theme === 'dark'
|
||||
await loadMermaid({ theme: currentTheme, darkMode })
|
||||
await loadMermaid({ theme: nextTheme, darkMode: !darkMode })
|
||||
await loadMermaid({ theme: 'neutral', darkMode: false, selector: '.mermaid-neutral' })
|
||||
}
|
||||
|
||||
window.FixItMermaid = {
|
||||
config: mermaidConfig,
|
||||
load: loadMermaid,
|
||||
init: initMermaid,
|
||||
}
|
||||
window.mermaid = mermaid
|
||||
|
||||
console.log(
|
||||
`%c💫 FixIt Mermaid`,
|
||||
'color: #FF3670; font-weight: bold; font-size: 16px; text-shadow: 1px 1px 2px rgba(0,0,0,0.1);',
|
||||
)
|
||||
|
||||
if (document.readyState !== 'loading') {
|
||||
initMermaid()
|
||||
} else {
|
||||
document.addEventListener('DOMContentLoaded', initMermaid, false)
|
||||
}
|
||||
|
||||
+6
-73
@@ -523,11 +523,11 @@ class FixIt {
|
||||
* init diagram copy button
|
||||
*/
|
||||
initDiagramCopyBtn() {
|
||||
const stagingDOM = this.util.getStagingDOM()
|
||||
this.util.forEach(document.querySelectorAll('.diagram-copy-btn'), ($btn) => {
|
||||
$btn.addEventListener('click', () => {
|
||||
const _tempEl = document.createElement('div');
|
||||
_tempEl.appendChild($btn.parentElement.querySelector('template').content.cloneNode(true));
|
||||
const code = _tempEl.innerText.trim();
|
||||
stagingDOM.stage($btn.parentElement.querySelector('template').content.cloneNode(true))
|
||||
const code = stagingDOM.contentAsText();
|
||||
this.util.copyText(code).then(() => {
|
||||
$btn.toggleAttribute('data-copied', true);
|
||||
setTimeout(() => {
|
||||
@@ -538,6 +538,7 @@ class FixIt {
|
||||
});
|
||||
}, false);
|
||||
});
|
||||
stagingDOM.destroy();
|
||||
}
|
||||
|
||||
initTable(target = document) {
|
||||
@@ -656,73 +657,6 @@ class FixIt {
|
||||
});
|
||||
}
|
||||
}
|
||||
initMermaid() {
|
||||
if (!this.config.mermaid) return;
|
||||
|
||||
const themes = this.config.mermaid.themes ?? ['default', 'dark'];
|
||||
let processing = false;
|
||||
let delayTask = null;
|
||||
|
||||
const loadMermaid = async () => {
|
||||
processing = true;
|
||||
// https://mermaid.js.org/config/schema-docs/config.html
|
||||
window.mermaid.initialize({
|
||||
startOnLoad: false,
|
||||
darkMode: this.isDark,
|
||||
theme: this.isDark ? themes[1] : themes[0],
|
||||
securityLevel: this.config.mermaid.securityLevel,
|
||||
look: this.config.mermaid.look,
|
||||
fontFamily: this.config.mermaid.fontFamily,
|
||||
altFontFamily: this.config.mermaid.fontFamily
|
||||
});
|
||||
await window.mermaid.run({
|
||||
querySelector: '.mermaid',
|
||||
suppressErrors: true,
|
||||
});
|
||||
processing = false;
|
||||
if (delayTask && typeof delayTask === 'function') {
|
||||
delayTask();
|
||||
delayTask = null;
|
||||
// console.log('Delayed task executed');
|
||||
}
|
||||
};
|
||||
|
||||
const reloadMermaid = async () => {
|
||||
await this.util.forEach(document.querySelectorAll('.mermaid[data-processed]'), (el) => {
|
||||
el.removeAttribute('data-processed');
|
||||
el.parentElement.replaceChild(el.nextElementSibling.content.cloneNode(true), el);
|
||||
});
|
||||
await loadMermaid();
|
||||
};
|
||||
|
||||
const waitForMermaid = () => {
|
||||
return new Promise((resolve) => {
|
||||
const timer = setInterval(() => {
|
||||
if (window.mermaid && window.mermaid.initialize) {
|
||||
clearInterval(timer);
|
||||
resolve();
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
};
|
||||
|
||||
waitForMermaid().then(() => {
|
||||
loadMermaid();
|
||||
this.switchThemeEventSet.add(() => {
|
||||
if (processing) {
|
||||
console.warn('Mermaid is still processing, delaying the reload.');
|
||||
delayTask = reloadMermaid;
|
||||
return;
|
||||
}
|
||||
// console.log('reload immediately');
|
||||
reloadMermaid().catch(console.error);
|
||||
});
|
||||
|
||||
this.beforeprintEventSet.add(() => {
|
||||
// Optionally set theme to 'neutral' for printing if required
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
initEcharts() {
|
||||
if (!this.config.echarts) {
|
||||
@@ -1167,7 +1101,6 @@ class FixIt {
|
||||
this.initCodeWrapper();
|
||||
this.initDiagramCopyBtn();
|
||||
this.initTable();
|
||||
this.initMermaid();
|
||||
this.initEcharts();
|
||||
this.initTypeit();
|
||||
this.initMapbox();
|
||||
@@ -1176,6 +1109,7 @@ class FixIt {
|
||||
this.initTocListener();
|
||||
this.initPangu();
|
||||
this.initMathJax();
|
||||
window.FixItMermaid?.init?.();
|
||||
this.util.forEach(document.querySelectorAll('.encrypted-hidden'), ($element) => {
|
||||
$element.classList.replace('encrypted-hidden', 'decrypted-shown');
|
||||
});
|
||||
@@ -1187,12 +1121,12 @@ class FixIt {
|
||||
this.initCodeWrapper();
|
||||
this.initDiagramCopyBtn();
|
||||
this.initTable($content);
|
||||
this.initMermaid();
|
||||
this.initEcharts();
|
||||
this.initTypeit($content);
|
||||
this.initMapbox();
|
||||
this.initPangu();
|
||||
this.initMathJax();
|
||||
window.FixItMermaid?.init?.();
|
||||
this.util.forEach($content.querySelectorAll('.encrypted-hidden'), ($element) => {
|
||||
$element.classList.replace('encrypted-hidden', 'decrypted-shown');
|
||||
});
|
||||
@@ -1389,7 +1323,6 @@ class FixIt {
|
||||
this.initCodeWrapper();
|
||||
this.initDiagramCopyBtn();
|
||||
this.initTable();
|
||||
this.initMermaid();
|
||||
this.initEcharts();
|
||||
this.initTypeit();
|
||||
this.initMapbox();
|
||||
|
||||
@@ -129,13 +129,6 @@
|
||||
|
||||
{{- /* mermaid */ -}}
|
||||
{{- if .Store.Get "hasMermaid" -}}
|
||||
{{- $mermaid := .Param "mermaid" -}}
|
||||
{{- $config = dict
|
||||
"themes" $mermaid.themes
|
||||
"securityLevel" $mermaid.securityLevel
|
||||
"look" $mermaid.look
|
||||
"fontFamily" $mermaid.fontFamily
|
||||
| dict "mermaid" | merge $config -}}
|
||||
{{- $options := dict "Source" "js/lib/mermaid.js" "Template" "js/lib/mermaid.min.js" -}}
|
||||
{{- $options = dict "Context" . "Minify" true "Fingerprint" $fingerprint "Attr" `type="module"` | merge $options -}}
|
||||
{{- $options | dict "Page" $ "Data" | partial "store/script.html" -}}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
{{- /* Mermaid support for code fences extended and shortcodes. */ -}}
|
||||
<div class="diagram-container">
|
||||
{{- dict "Label" "Copy Mermaid code" | partial "plugin/diagram-copy-btn.html" -}}
|
||||
<pre class="mermaid">{{ .Inner | safeHTML }}</pre>
|
||||
<template><pre class="mermaid">{{ .Inner | safeHTML }}</pre></template>
|
||||
<pre class="mermaid-dark">{{ .Inner | safeHTML }}</pre>
|
||||
<pre class="mermaid-neutral">{{ .Inner | safeHTML }}</pre>
|
||||
{{- dict "Label" "Copy Mermaid code" | partial "plugin/diagram-copy-btn.html" -}}
|
||||
<template><pre>{{ .Inner | safeHTML }}</pre></template>
|
||||
</div>
|
||||
{{- /* EOF */ -}}
|
||||
|
||||
Reference in New Issue
Block a user