@@ -379,6 +379,7 @@ export async function preParse(md, req) {
379379 let r = md ;
380380 r = await removeForbiddenContent ( r , req ) ;
381381 r = await preReplacePlantUml ( r , req ) ;
382+ r = await preReplaceMermaid ( r , req ) ;
382383 r = preMarkCode ( r ) ;
383384 r = preReplaceObsidianFileLinks ( r , req ) ;
384385 r = preMarkCallouts ( r ) ;
@@ -552,8 +553,6 @@ function postprocessFragments(html) {
552553 return document . body . innerHTML ;
553554}
554555
555-
556-
557556function preReplaceObsidianFileLinks ( html , req ) {
558557 const regex = / (?< ! \! ) \[ \[ ( [ ^ \] \n ] + ) \] \] / g;
559558
@@ -599,6 +598,20 @@ function preReplaceObsidianFileLinks(html, req) {
599598 } ) ;
600599}
601600
601+ export async function preReplaceMermaid ( md , req ) {
602+ let regex = / ^ \s * ` ` ` + \s * ( m e r m a i d ) $ / gim;
603+ let match ;
604+ while ( ( match = regex . exec ( md ) ) !== null ) {
605+ // PlantUML
606+ const start = match . index + match [ 0 ] . length ;
607+ const end = md . indexOf ( "```" , start ) ;
608+ const mermaid = md . substring ( start , end ) ;
609+ md = md . substring ( 0 , match . index ) + '<pre class="mermaid">' + mermaid + '</pre>' + md . substring ( end + 3 ) ;
610+ regex = / ^ \s * ` ` ` + \s * ( m e r m a i d ) $ / gim;
611+ }
612+ return md ;
613+ }
614+
602615export async function preReplacePlantUml ( md , req ) {
603616 let regex = / ^ \s * ` ` ` + \s * ( p l a n t u m l ) $ / gim;
604617 let match ;
@@ -1299,6 +1312,37 @@ async function getSideBar(startPage, req) {
12991312 ` ;
13001313}
13011314
1315+ function getMermaidScriptEntry ( ) {
1316+ return `<script type="module">
1317+ import mermaid from "/node_modules/mermaid/dist/mermaid.esm.min.mjs";
1318+
1319+ mermaid.initialize({
1320+ startOnLoad: false,
1321+ logLevel: 'debug'
1322+ });
1323+
1324+ function decodeEntities(str) {
1325+ const txt = document.createElement('textarea');
1326+ txt.innerHTML = str;
1327+ return txt.value;
1328+ }
1329+
1330+ // wenn Reveal „ready“ ist, oder einfach bei DOMContentLoaded
1331+ document.addEventListener("DOMContentLoaded", () => {
1332+ document.querySelectorAll("pre.mermaid").forEach(async (el, i) => {
1333+ const raw = el.textContent;
1334+ const code = decodeEntities(raw);
1335+ try {
1336+ const { svg } = await mermaid.render("m" + i, code);
1337+ el.innerHTML = svg;
1338+ } catch (e) {
1339+ console.error("Mermaid render failed", e);
1340+ }
1341+ });
1342+ });
1343+ </script>` ;
1344+ }
1345+
13021346export async function wrapInPage ( html , startPage , req ) {
13031347 const pre = `
13041348 <!DOCTYPE html>
@@ -1328,6 +1372,7 @@ export async function wrapInPage(html, startPage, req) {
13281372 </div>
13291373 </div>
13301374 <script src="/obsidian-page.js"></script>
1375+ ${ getMermaidScriptEntry ( ) }
13311376 <script lang="javascript">
13321377 initFonts('${ JSON . stringify ( mainFontsArray ) } ', '${ JSON . stringify (
13331378 navFontsArray
@@ -1362,6 +1407,7 @@ export async function wrapAsDocument(html, req) {
13621407 </div>
13631408 </div>
13641409 <script src="/obsidian-page.js"></script>
1410+ ${ getMermaidScriptEntry ( ) }
13651411 <script lang="javascript">
13661412 initFonts('${ JSON . stringify ( mainFontsArray ) } ', '${ JSON . stringify (
13671413 navFontsArray
@@ -1430,7 +1476,9 @@ export async function wrapInReveal(reveal, req) {
14301476 <!-- Theme used for syntax highlighting of code -->
14311477 <!-- <link rel="stylesheet" href="lib/css/zenburn.css"> -->
14321478 <!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/styles/tomorrow.min.css"> -->
1433-
1479+
1480+ ${ getMermaidScriptEntry ( ) }
1481+
14341482 <!-- Printing and PDF exports -->
14351483 <script>
14361484 var link = document.createElement('link');
0 commit comments