11// Mermaid diagram renderer for XOOPS Docs
22// Loaded as a static asset — no build step, no npm dependency.
3+ //
34// Starlight uses expressive-code, which renders mermaid blocks as:
45// <div class="expressive-code">
5- // <figure><pre data-language="mermaid"><code>...</code></pre></figure>
6+ // <figure><pre data-language="mermaid"><code>
7+ // <div class="ec-line"><div class="code">...</div></div>
8+ // ...
9+ // </code></pre></figure>
610// </div>
7- // We target that structure, extract the raw source via textContent,
8- // replace the whole expressive-code container with the rendered SVG,
9- // and re-render when the user toggles dark/light mode.
11+ //
12+ // IMPORTANT: textContent on the <code> element concatenates ec-line divs
13+ // without newlines, producing invalid Mermaid source. We must join each
14+ // .ec-line's textContent with '\n' to reconstruct the original diagram.
1015
1116import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs' ;
1217
@@ -16,14 +21,24 @@ function currentTheme() {
1621 : 'dark' ;
1722}
1823
24+ function extractSource ( code ) {
25+ // expressive-code wraps each line in .ec-line; join them to restore newlines
26+ const lines = code . querySelectorAll ( '.ec-line' ) ;
27+ if ( lines . length ) {
28+ return Array . from ( lines ) . map ( l => l . textContent ) . join ( '\n' ) . trim ( ) ;
29+ }
30+ // Fallback for plain <code> blocks (no expressive-code)
31+ return code . textContent . trim ( ) ;
32+ }
33+
1934async function renderMermaid ( ) {
2035 const codeBlocks = document . querySelectorAll ( 'pre[data-language="mermaid"] code' ) ;
2136 if ( ! codeBlocks . length ) return ;
2237
2338 mermaid . initialize ( { startOnLoad : false , theme : currentTheme ( ) } ) ;
2439
2540 for ( const code of codeBlocks ) {
26- const src = code . textContent . trim ( ) ;
41+ const src = extractSource ( code ) ;
2742 // Replace the whole expressive-code wrapper, falling back to the <pre>
2843 const container = code . closest ( '.expressive-code' ) || code . closest ( 'pre' ) ;
2944 const wrapper = document . createElement ( 'div' ) ;
@@ -34,7 +49,8 @@ async function renderMermaid() {
3449 const id = 'mmd-' + Math . random ( ) . toString ( 36 ) . slice ( 2 , 9 ) ;
3550 const { svg } = await mermaid . render ( id , src ) ;
3651 wrapper . innerHTML = svg ;
37- } catch {
52+ } catch ( e ) {
53+ console . error ( 'Mermaid render error:' , e , '\nSource:\n' , src ) ;
3854 wrapper . textContent = src ;
3955 }
4056 container . replaceWith ( wrapper ) ;
0 commit comments