Mermaidin teemat vaihtaminen (UpdatedM SK1
Esitys
Käytän Mermaidia.js luodakseni ne huumausainediagrammat, joita näette muutamassa julkaisussaM SK1 Kuten jäljempänä olevassa Minua kuitenkin häiritsee se, että se ei reagoi aiheiden vaihtamiseen: (, "dark" ja "light". Näyttää siltä, että tämän tavoitteen saavuttamisesta on olemassa hyvin huonoja tietoja.
Tämä on tulosta muutaman tunnin kaivauksesta ja siitä, että yritetään selvittää, miten tämä tehdään.
Mdeswitcherin lähde löytyy täältä: mdeswitcher.js.
PANEE MERKILLE: Olen ajantasaistanut tätä merkittävästi
Diagrammi
graph LR
A[Start] --> B[Initialize Mermaid with Theme]
B --> C{Are there any elements matching 'div.mermaid'?}
C --> |No| D[Exit]
C --> |Yes| E[Save Original Data]
E --> F{Did saving data succeed?}
F --> |No| D[Exit]
F --> |Yes| G[Set up Theme Event Listeners]
G --> H[Check Local Storage for Dark Mode]
H --> I{Is Dark Mode enabled?}
I --> |Yes| J[Load Mermaid with Dark Theme]
I --> |No| K[Load Mermaid with Default Theme]
J --> L[Wait for Events]
K --> L[Wait for Events]
L --> M{Event Triggered?}
M --> |Dark Theme Set| N[Reset Processed Data]
N --> O[Load Mermaid with Dark Theme]
M --> |Light Theme Set| P[Reset Processed Data]
P --> Q[Load Mermaid with Default Theme]
O --> L
Q --> L
L --> D[Exit]
Ongelma
Ongelmana on se, että Mermaid-aihetta on initialisoitava ja sen jälkeen sitä ei voida muuttaa.
Ratkaisu
Näin ollen sen jälkeen, kun tutkiin paljon ja yritin selvittää, miten tämä tehdään, löysin ratkaisun tämä GitHubin issue post
Siinä oli kuitenkin vielä joitakin ongelmia, joten minun oli muutettava sitä hieman, jotta se toimisi.
Aiheet
Tämä sivusto perustuu Tailwind teema, joka tuli melko hirvittävän teeman vaihtaja.
Huomaatte, että tämä tekee erilaisia asioita vaihtaessa aihetta, ottamalla käyttöön aihetta siitä, mikä on tallennettu paikalliseen varastoon M SK2 muuttamalla paria stylesheeriä simplemde-järjestelmälle & korostamaan.js ja sitten soveltamalla aihetta
export function globalSetup() {
const lightStylesheet = document.getElementById('light-mode');
const darkStylesheet = document.getElementById('dark-mode');
const simpleMdeDarkStylesheet = document.getElementById('simplemde-dark');
const simpleMdeLightStylesheet = document.getElementById('simplemde-light');
return {
isMobileMenuOpen: false,
isDarkMode: false,
// Function to initialize the theme based on localStorage or system preference
themeInit() {
if (
localStorage.theme === "dark" ||
(!("theme" in localStorage) &&
window.matchMedia("(prefers-color-scheme: dark)").matches)
) {
localStorage.theme = "dark";
document.documentElement.classList.add("dark");
document.documentElement.classList.remove("light");
this.isDarkMode = true;
this.applyTheme(); // Apply dark theme stylesheets
} else {
localStorage.theme = "base";
document.documentElement.classList.remove("dark");
document.documentElement.classList.add("light");
this.isDarkMode = false;
this.applyTheme(); // Apply light theme stylesheets
}
},
// Function to switch the theme and update the stylesheets accordingly
themeSwitch() {
if (localStorage.theme === "dark") {
localStorage.theme = "light";
document.body.dispatchEvent(new CustomEvent('light-theme-set'));
document.documentElement.classList.remove("dark");
document.documentElement.classList.add("light");
this.isDarkMode = false;
} else {
localStorage.theme = "dark";
document.body.dispatchEvent(new CustomEvent('dark-theme-set'));
document.documentElement.classList.add("dark");
document.documentElement.classList.remove("light");
this.isDarkMode = true;
}
this.applyTheme(); // Apply the theme stylesheets after switching
},
// Function to apply the appropriate stylesheets based on isDarkMode
applyTheme() {
if (this.isDarkMode) {
// Enable dark mode stylesheets
lightStylesheet.disabled = true;
darkStylesheet.disabled = false;
simpleMdeLightStylesheet.disabled = true;
simpleMdeDarkStylesheet.disabled = false;
} else {
// Enable light mode stylesheets
lightStylesheet.disabled = false;
darkStylesheet.disabled = true;
simpleMdeLightStylesheet.disabled = false;
simpleMdeDarkStylesheet.disabled = true;
}
}
};
}
Järjestelmä
Tärkeimmät lisäykset Mermaid theme switcher ovat seuraavat:
document.body.dispatchEvent(new CustomEvent('dark-theme-set'));
document.body.dispatchEvent(new CustomEvent('light-theme-set'));
Näitä kahta tapahtumaa käytetään ThemeSwitcher-komponenttina Mermaid -diagrammien elvyttämiseksi.
OnLoad / htmx:afterSwap
Minun main.js asiakirjan laatiminen theme switcher. myös maahantuo mdeswitch asiakirja, joka sisältää koodin aiheiden vaihtamiseksi.
//Important: Memraid will ALWAYS intialize on window.onload, so we need to make sure we disable this behaviour:
import mermaid from "mermaid";
window.mermaid=mermaid;
mermaid.initialize({startOnLoad:false});
window.mermaidinit = function() {
mermaid.initialize({ startOnLoad: false });
try {
window.initMermaid().then(r => console.log('Mermaid initialized'));
} catch (e) {
console.error('Failed to initialize Mermaid:', e);
}
}
document.body.addEventListener('htmx:afterSwap', function(evt) {
mermaidinit();
//This should be called after the mermaid diagrams have been rendered.
hljs.highlightAll();
});
window.onload = function(ev) {
if(document.readyState === 'complete') {
mermaidinit();
hljs.highlightAll();
}
};
MDESwtich
Tämä on tiedosto, joka sisältää koodin Mermaidin teemajen vaihtamiseksi. (Huottava taulukko edellä osoittaa sellaisten tapahtumien ketjun, jotka tapahtuvat, kun teemaa muutetaan)
(function(window) {
'use strict';
const elementCode = 'div.mermaid';
const loadMermaid = async (theme) => {
mermaid.initialize({startOnLoad: false, theme: theme });
console.log("Loading mermaid with theme:", theme);
await mermaid.run({
querySelector: elementCode,
});
};
const saveOriginalData = async () => {
try {
console.log("Saving original data");
const elements = document.querySelectorAll(elementCode);
const count = elements.length;
if (count === 0) return;
const promises = Array.from(elements).map((element) => {
if (element.getAttribute('data-processed') != null) {
console.log("Element already processed");
return;
}
element.setAttribute('data-original-code', element.innerHTML);
});
await Promise.all(promises);
} catch (error) {
console.error(error);
throw error;
}
};
const resetProcessed = async () => {
try {
console.log("Resetting processed data");
const elements = document.querySelectorAll(elementCode);
const count = elements.length;
if (count === 0) return;
const promises = Array.from(elements).map((element) => {
if (element.getAttribute('data-original-code') != null) {
element.removeAttribute('data-processed');
element.innerHTML = element.getAttribute('data-original-code');
}
else {
console.log("Element already reset");
}
});
await Promise.all(promises);
} catch (error) {
console.error(error);
throw error;
}
};
window.initMermaid = async () => {
const mermaidElements = document.querySelectorAll(elementCode);
if (mermaidElements.length === 0) return;
try {
await saveOriginalData();
} catch (error) {
console.error("Error saving original data:", error);
return; // Early exit if saveOriginalData fails
}
const handleDarkThemeSet = async () => {
try {
await resetProcessed();
await loadMermaid('dark');
console.log("Dark theme set");
} catch (error) {
console.error("Error during dark theme set:", error);
}
};
const handleLightThemeSet = async () => {
try {
await resetProcessed();
await loadMermaid('default');
console.log("Light theme set");
} catch (error) {
console.error("Error during light theme set:", error);
}
};
document.body.removeEventListener('dark-theme-set', handleDarkThemeSet);
document.body.removeEventListener('light-theme-set', handleLightThemeSet);
document.body.addEventListener('dark-theme-set', handleDarkThemeSet);
document.body.addEventListener('light-theme-set', handleLightThemeSet);
const isDarkMode = localStorage.theme === 'dark';
await loadMermaid(isDarkMode ? 'dark' : 'default').then(r => console.log('Initial load complete'));
};
})(window);
Siihen pääsemme hieman alaspäin..
init- on päätehtävä, joka kutsutaan, kun sivua laaditaan
Ensinnäkin se säilyttää mermaid-diagrammien alkuperäisen sisällön; tämä oli kysymys versiossani, joka kopioin.
Sen jälkeen siihen lisätään kaksi tapahtuman kuuntelijaa dark-theme-set ja light-theme-set events. Kun nämä tapahtumat käynnistetään, se palauttaa uudelleen käsiteltyjä tietoja ja käynnistää uudelleen Mermaid-diagrammat uudella teemalla.
Sen jälkeen se tarkistaa teeman paikallisen varastoinnin ja käynnistää Mermaid-diagrammat asianmukaisella teemalla.
let isDarkMode = localStorage.theme === 'dark';
if(isDarkMode) {
loadMermaid('dark');
}
else{
loadMermaid('default')
}
Säädä alkuperäiset tiedot
Avain tähän koko asiaan on varastointi ja sen jälkeen sisällön palauttaminen, joka sisältyy esitettyyn <div class="mermaid"><div> jotka sisältävät mermaid markup-merkintöjä postistamme.
Huomaatte, että tämä vain perustaa lupauksen, joka kiertää kaikkia osatekijöitä ja tallentaa alkuperäisen sisällön data-original-code ominaisuuksia.
const saveOriginalData = async () => {
try {
console.log("Saving original data");
const elements = document.querySelectorAll(elementCode);
const count = elements.length;
if (count === 0) return;
const promises = Array.from(elements).map((element) => {
if (element.getAttribute('data-processed') != null) {
console.log("Element already processed");
return;
}
element.setAttribute('data-original-code', element.innerHTML);
});
await Promise.all(promises);
} catch (error) {
console.error(error);
throw error;
}
};
resetProcessed on sama lukuun ottamatta käännekohtaa, jossa se ottaa merkintä data-original-code ja palauttaa sen elementtiin.
Init
Nyt meillä on kaikki nämä tiedot voimme käynnistää mermaid soveltaa uutta teemaamme ja rerender SVG-diagrammaa HTML -tulokseen
const elementCode = 'div.mermaid';
const loadMermaid = async (theme) => {
mermaid.initialize({startOnLoad: false, theme: theme });
console.log("Loading mermaid with theme:", theme);
await mermaid.run({
querySelector: elementCode,
});
};
Päätelmissä
Tämä oli hieman hankalaa ymmärtää, mutta olen iloinen siitä. Toivon, että tämä auttaa muita, jotka yrittävät tehdä samoin.