# Mermaid.js Deep Dive: hoe het eigenlijk werkt en hoe het uit te breiden

<!--category-- Mermaid, JavaScript, SVG, Diagrams -->
<datetime class="hidden">2025-11-09T16:00</datetime>

# Inleiding

> OPMERKING: Dit is onderdeel van mijn experimenten met AI / een manier om $1000 Calude Code Web credits uit te geven. Ik heb dit een BUNCH van papieren, mijn begrip, vragen die ik moest genereren van dit artikel. Het is leuk en vult een gat dat ik niet ergens anders heb gezien gevuld.

> **Dit artikel bouwt voort op eerdere artikelen:** Als je dat nog niet gedaan hebt, kijk dan. [Meermin.js toevoegen met htmx](/blog/mermaidandhtmx), [Thema's voor Mermaid wisselen](/blog/switchingthemesformermaid), en [Meerminnendiagrammen verbeteren met Pan/Zoom en Export](/blog/enhancingmermaiddiagramswithpanzoomandexport). Deze diepe duik verklaart de binnenkant achter die implementaties.

Mermaid.js is echt briljant. Schrijf eenvoudige tekst, krijg mooie diagrammen. Geen gerommel meer met Visio of draw.io, verlies bronbestanden, of behoud van aparte beeldbestanden. Alles leeft in markdown, versiegestuurd naast uw code.

Maar ik wilde het weten. *hoe* Het werkt eigenlijk onder de motorkap.

```mermaid
graph LR
    A[Text] --> B[Magic?]
    B --> C[Beautiful Diagram]
```

...worden een echte SVG? En nog belangrijker, hoe kun je haak in het toe te voegen functies zoals de pan/zoom, thema switching, en export functionaliteit die ik voor deze site (nu beschikbaar als [@mostlylucid/mermaid-enhancements](https://www.npmjs.com/package/@mostlylucid/mermaid-enhancements))?

Na veel graven door Mermaid's broncode en het bouwen van echte extensies, hier is alles wat ik heb geleerd over hoe Mermaid intern werkt en hoe om het goed uit te breiden.

[TOC]

# Wat is Mermaid.js?

Mermaid verandert tekstdefinities in diagrammen. Denk aan "Markdown for diagrammen."

**De oude manier:**

1. Open diagrammen tool
2. diagram aanmaken
3. Exporteren als PNG
4. Invoegen in documenten
5. Moeten updaten? Het bronbestand zoeken, bewerken, opnieuw exporteren, afbeelding vervangen...

**De Zeemeermin manier:**

1. diagram in tekst schrijven
2. Klaar

Updaten? Gewoon de tekst bewerken. Versie controle? Het is gewoon tekst! Werkt in markdown? Yep!

## Diagramtypes

Mermaid ondersteunt een belachelijk aantal diagram types:

```mermaid
graph LR
    A[Flowcharts] --> B[Sequence Diagrams]
    B --> C[Class Diagrams]
    C --> D[State Diagrams]
    D --> E[ER Diagrams]
    E --> F[Gantt Charts]
    F --> G[Pie Charts]
    G --> H[Git Graphs]
    H --> I[User Journeys]
    I --> J[And many more...]
```

Zie [de Zeemeermin docs](https://mermaid.js.org/intro/) voor de volledige lijst.

# Hoe Mermaid werkt eigenlijk: De Pipeline

Dit is wat er gebeurt als Mermaid een diagram geeft:

```mermaid
graph TD
    A[Text Definition] --> B[Lexer/Tokenizer]
    B --> C[Parser]
    C --> D[AST Built]
    D --> E[Diagram Type Detected]
    E --> F[Type-Specific Renderer]
    F --> G[SVG Generated]
    G --> H[Inserted into DOM]
    H --> I[Your Enhancements Run]

    style A stroke:#059669,stroke-width:3px,color:#10b981
    style D stroke:#2563eb,stroke-width:3px,color:#3b82f6
    style G stroke:#7c3aed,stroke-width:3px,color:#8b5cf6
    style I stroke:#d97706,stroke-width:3px,color:#f59e0b
```

Laten we elke stap afbreken.

## Stap 1: Tekstdefinitie

Alles begint met tekst. Je schrijft diagrammen in Mermaid's DSL (domeinspecifieke taal):

```javascript
// Flowchart
const diagram = `
graph TD
    A[Start] --> B{Is it working?}
    B -->|Yes| C[Great!]
    B -->|No| D[Debug time]
`;
```

## Stap 2: Lexical Analysis

De lexer breekt tekst in tokens. Bijvoorbeeld deze regel:

```
A[Start] --> B{Decision}
```

Wordt tokens als:

```javascript
[
    { type: 'NODE_ID', value: 'A' },
    { type: 'NODE_TEXT', value: 'Start' },
    { type: 'ARROW', value: '-->' },
    { type: 'NODE_ID', value: 'B' },
    { type: 'NODE_TEXT', value: 'Decision' },
    { type: 'NODE_SHAPE', value: 'diamond' }  // from { }
]
```

## Stap 3: Ontleden en AST-generatie

De parser verbruikt tokens en bouwt een Abstract Syntax Tree (AST):

```javascript
// Simplified AST structure
{
    type: 'flowchart',
    direction: 'TD',
    nodes: [
        { id: 'A', text: 'Start', shape: 'rect' },
        { id: 'B', text: 'Decision', shape: 'diamond' }
    ],
    edges: [
        { from: 'A', to: 'B', type: 'arrow' }
    ]
}
```

Mermaid gebruikt verschillende parsers voor elk diagram type. Deze worden vaak gegenereerd uit grammatica bestanden met behulp van [Jison](https://github.com/zaach/jison) (zoals Yacc/Bison voor JavaScript).

## Stap 4: Diagramdetectie

Mermaid detecteert diagram type vanaf de eerste regel:

```javascript
// Simplified detection logic
if (text.match(/^\s*graph/)) return 'flowchart';
if (text.match(/^\s*sequenceDiagram/)) return 'sequence';
if (text.match(/^\s*classDiagram/)) return 'class';
// ... etc
```

## Stap 5: Typespecifieke rendering

Elk diagramtype heeft zijn eigen renderer. De renderer neemt de AST en genereert SVG elementen.

Voor stroomschema's gebruikt Mermaid de [Dagre](https://github.com/dagrejs/dagre) bibliotheek voor grafische indeling. Voor anderen maakt het gebruik van aangepaste algoritmen of bibliotheken zoals Cytoscape.

```javascript
// Simplified flowchart renderer
export const draw = function (text, id, version, diagObj) {
    const graph = diagObj.db;  // The AST
    const svg = d3.select(`#${id}`);

    // Render nodes
    graph.getVertices().forEach(vertex => {
        drawNode(svg, vertex);
    });

    // Render edges
    graph.getEdges().forEach(edge => {
        drawEdge(svg, edge);
    });

    // Apply layout algorithm
    dagre.layout(graph);
};
```

## Stap 6: SVG Generation

De renderer produceert SVG markup:

```xml
<svg xmlns="http://www.w3.org/2000/svg">
    <g class="node">
        <rect x="0" y="0" width="100" height="50"/>
        <text x="50" y="25">Start</text>
    </g>
    <g class="edge">
        <path d="M 100 25 L 200 25" stroke="#333"/>
    </g>
</svg>
```

## Stap 7: DOM-invoeging

Zeemeermin vindt alles `.mermaid` elementen en vervangt ze door weergegeven SVG:

```javascript
// From mermaid.ts
export const init = async function (config, nodes) {
    const nodesToProcess = nodes || document.querySelectorAll('.mermaid');

    for (const node of nodesToProcess) {
        const id = `mermaid-${Date.now()}-${Math.random()}`;
        const txt = node.textContent;

        const { svg } = await render(id, txt);
        node.innerHTML = svg;
    }
};
```

## Stap 8: Post-Processing (Where You Come In)

Nadat Mermaid de SVG invoegt, kunt u het verbeteren. Dit is waar al mijn verbeteringen haak in:

- Pan/zoomfunctionaliteit
- Bedieningsknoppen
- Exportmogelijkheden
- Thema wisselen

Meer hierover hieronder.

# Uitbreiding van Mermaid: De Extension Points

Nu we weten hoe Mermaid werkt, laten we onderzoeken hoe het uit te breiden.

## 1. Configuratie

De meest elementaire uitbreiding is configuratie:

```javascript
import mermaid from 'mermaid';

mermaid.initialize({
    startOnLoad: true,
    theme: 'dark',
    securityLevel: 'loose',
    flowchart: {
        curve: 'basis',
        padding: 15
    }
});
```

## 2. Themaaanpassing

Ik heb dit uitgebreid behandeld in [Thema's voor Mermaid wisselen](/blog/switchingthemesformermaid), maar hier is de belangrijkste implementatie:

### Het probleem met thema wisselen

Mermaid moet worden geïnitialiseerd met een thema, en je kunt het niet veranderen na. MAAR als je wilt her-render diagrammen met een nieuw thema, moet je de originele diagram bron ..die Mermaid *slaat niet op in de DOM*.

### De oplossing

Bewaar de oorspronkelijke inhoud voor het renderen, herstel en re-render bij het schakelen van thema's:

```javascript
// From my theme-switcher implementation
const originalData = new Map();

// Save original content before first render
const saveOriginalData = async () => {
    const elements = document.querySelectorAll('.mermaid');
    elements.forEach(element => {
        const id = element.id || `mermaid-${Date.now()}`;
        element.id = id;

        // Store the original diagram source
        if (!originalData.has(id)) {
            originalData.set(id, element.textContent?.trim());
        }
    });
};

// When theme changes, restore and re-render
const loadMermaid = async (theme) => {
    mermaid.initialize({
        startOnLoad: false,
        theme: theme
    });

    const elements = document.querySelectorAll('.mermaid');
    for (const element of elements) {
        const source = originalData.get(element.id);
        if (source) {
            element.innerHTML = '';  // Clear
            element.removeAttribute('data-processed');

            const { svg } = await mermaid.render(
                `mermaid-svg-${element.id}`,
                source
            );
            element.innerHTML = svg;
        }
    }
};
```

**Meerdere detectiemethoden voor thema's** (sites behandelen thema's anders):

```javascript
function detectTheme() {
    // Check various sources
    if (typeof window.__themeState !== 'undefined') {
        return window.__themeState;
    }
    if (localStorage.theme) {
        return localStorage.theme;
    }
    if (document.documentElement.classList.contains('dark')) {
        return 'dark';
    }
    if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
        return 'dark';
    }
    return 'light';
}
```

Zie [de volledige thema switcher code](https://github.com/scottgal/mostlylucidweb/blob/main/Mostlylucid/src/js/memmaid_theme_switch.js) voor details.

## 3. Verbeteringen na het renderen

Dit is waar de echte magie gebeurt. Na Mermaid renders, kunt u interactieve functies toevoegen.

Ik heb dit uitgebreid behandeld in [Meerminnendiagrammen verbeteren met Pan/Zoom en Export](/blog/enhancingmermaiddiagramswithpanzoomandexport), dus ik zal de belangrijkste technieken hier markeren.

### Inpakdiagrammen

Maak een wikkelcontainer aan voor bedieningselementen:

```javascript
function wrapDiagram(element) {
    if (element.closest('.mermaid-wrapper')) {
        return element.closest('.mermaid-wrapper');
    }

    const wrapper = document.createElement('div');
    wrapper.className = 'mermaid-wrapper';
    wrapper.id = `wrapper-${element.id}`;

    element.parentNode.insertBefore(wrapper, element);
    wrapper.appendChild(element);

    return wrapper;
}
```

### Pan/Zoom toevoegen

Gebruik [svg-pan-zoom](https://github.com/bumbu/svg-pan-zoom):

```javascript
import svgPanZoom from 'svg-pan-zoom';

const panZoomInstances = new Map();

function initPanZoom(svgElement, diagramId) {
    // Clean up existing instance
    if (panZoomInstances.has(diagramId)) {
        panZoomInstances.get(diagramId).destroy();
        panZoomInstances.delete(diagramId);
    }

    const instance = svgPanZoom(svgElement, {
        zoomEnabled: true,
        controlIconsEnabled: false,
        fit: true,
        center: true,
        minZoom: 0.1,
        maxZoom: 10
    });

    panZoomInstances.set(diagramId, instance);
    return instance;
}
```

### Controleknoppen

Zwevend bedieningspaneel aanmaken:

```javascript
function createControlButtons(container, diagramId) {
    const controlsDiv = document.createElement('div');
    controlsDiv.className = 'mermaid-controls';

    const buttons = [
        { icon: 'bx-fullscreen', title: 'Fullscreen', action: 'fullscreen' },
        { icon: 'bx-zoom-in', title: 'Zoom In', action: 'zoomIn' },
        { icon: 'bx-zoom-out', title: 'Zoom Out', action: 'zoomOut' },
        { icon: 'bx-reset', title: 'Reset', action: 'reset' },
        { icon: 'bx-move', title: 'Pan', action: 'pan' },
        { icon: 'bx-image', title: 'Export PNG', action: 'exportPng' },
        { icon: 'bx-code-alt', title: 'Export SVG', action: 'exportSvg' }
    ];

    buttons.forEach(btn => {
        const button = document.createElement('button');
        button.className = `mermaid-control-btn bx ${btn.icon}`;
        button.setAttribute('data-action', btn.action);
        button.setAttribute('data-diagram-id', diagramId);
        controlsDiv.appendChild(button);
    });

    container.appendChild(controlsDiv);
}
```

### Delegatie van evenementen (Prestatie!)

Verbind geen luisteraars aan elke knop.

```javascript
document.addEventListener('click', (e) => {
    const target = e.target;
    if (!target.classList.contains('mermaid-control-btn')) return;

    const action = target.getAttribute('data-action');
    const diagramId = target.getAttribute('data-diagram-id');
    const panZoom = panZoomInstances.get(diagramId);

    switch (action) {
        case 'zoomIn': panZoom?.zoomIn(); break;
        case 'zoomOut': panZoom?.zoomOut(); break;
        case 'reset': panZoom?.reset(); break;
        // ... etc
    }
});
```

### Exportfunctionaliteit

**De uitdaging:** SVG elementen hebben dynamische grootte, pan/zoom transformeert, en geërfde stijlen. Om goed te exporteren, moet je:

1. Kloon de SVG
2. Dimensie behouden
3. Transformaties verwijderen
4. Converteren naar PNG of SVG

Gebruik [html-to-image](https://github.com/bubkoo/html-to-image):

```javascript
import { toPng, toSvg } from 'html-to-image';

async function exportDiagram(container, format, diagramId) {
    const svgElement = container.querySelector('svg');
    if (!svgElement) return;

    // Clone to avoid modifying original
    const clonedSvg = svgElement.cloneNode(true);

    // Get or calculate viewBox
    let viewBox = clonedSvg.getAttribute('viewBox');
    if (!viewBox) {
        const bbox = svgElement.getBBox();
        viewBox = `${bbox.x} ${bbox.y} ${bbox.width} ${bbox.height}`;
        clonedSvg.setAttribute('viewBox', viewBox);
    }

    // Set explicit dimensions
    const [, , width, height] = viewBox.split(' ').map(Number);
    clonedSvg.setAttribute('width', width);
    clonedSvg.setAttribute('height', height);

    // Remove pan-zoom transforms
    clonedSvg.removeAttribute('style');

    // Create off-screen container
    const temp = document.createElement('div');
    temp.style.position = 'absolute';
    temp.style.left = '-9999px';
    temp.appendChild(clonedSvg);
    document.body.appendChild(temp);

    // Export
    const dataUrl = format === 'png'
        ? await toPng(clonedSvg, { pixelRatio: 2 })
        : await toSvg(clonedSvg);

    downloadFile(dataUrl, `diagram-${Date.now()}.${format}`);

    // Cleanup
    document.body.removeChild(temp);
}
```

**Kritische details:**

- **Weergavebox behouden** - Legt het hele diagram vast, niet alleen zichtbaar gedeelte
- **Off-screen rendering** - Vermijd invloed op het weergegeven diagram
- **pixelRatio: 2** - High-DPI voor scherpe PNG export

Zie [de volledige uitvoercode](https://github.com/scottgal/mostlylucidweb/blob/main/Mostlylucid/src/js/mermaid_enhancements.js#L148) voor meer details.

# Het volledige enhancementspakket

Ik verpakte al deze verbeteringen als [@mostlylucid/mermaid-enhancements](https://www.npmjs.com/package/@mostlylucid/mermaid-enhancements). Zie [Publishing Mermaid Enhancements as an npm Package](/blog/publishingmermaidenhancementsnpm) voor alle details.

Dit is hoe het allemaal bij elkaar past:

```mermaid
graph TB
    A[User Initializes] --> B[init Function]
    B --> C[initMermaid]
    B --> D[enhanceMermaidDiagrams]

    C --> E[Theme Detection]
    C --> F[Event Listeners]
    C --> G[Mermaid Rendering]

    E --> E1[Global State]
    E --> E2[LocalStorage]
    E --> E3[DOM Class]
    E --> E4[OS Preference]

    F --> F1[Custom Events]
    F --> F2[Media Query]

    G --> H[Apply Enhancements]
    D --> H

    H --> I[Wrap Diagrams]
    H --> J[Init Pan/Zoom]
    H --> K[Add Controls]

    I --> L[Interactive Diagram]
    J --> L
    K --> L

    L --> M[User Interactions]
    M --> M1[Zoom In/Out]
    M --> M2[Pan]
    M --> M3[Fullscreen]
    M --> M4[Export PNG/SVG]

    style A stroke:#059669,stroke-width:3px,color:#10b981
    style L stroke:#2563eb,stroke-width:3px,color:#3b82f6
    style M stroke:#7c3aed,stroke-width:3px,color:#8b5cf6
```

## Gebruik

```bash
npm install @mostlylucid/mermaid-enhancements
```

```typescript
import { init } from '@mostlylucid/mermaid-enhancements';
import '@mostlylucid/mermaid-enhancements/styles.css';

await init();
```

Je zeemeermin diagrammen hebben nu:

- Interactieve pan/zoom
- Full screen lightbox
- PNG/SVG-export
- Automatische thema switch
- Reagerend design

# Integratie met HTMX

Als ik bedekt in [Meermin.js toevoegen met htmx](/blog/mermaidandhtmx), moet je Mermaid opnieuw initialiseren na HTMX content swaps:

```javascript
// On page load
document.addEventListener('DOMContentLoaded', function () {
    mermaid.initialize({ startOnLoad: true });
});

// After HTMX swaps content
document.body.addEventListener('htmx:afterSwap', function(evt) {
    mermaid.run();
});
```

Met het uitbreidingspakket:

```javascript
import { init, enhanceMermaidDiagrams } from '@mostlylucid/mermaid-enhancements';

// Initial load
await init();

// After HTMX swap
document.body.addEventListener('htmx:afterSwap', async function() {
    await init();  // Re-init Mermaid with current theme
    enhanceMermaidDiagrams();  // Re-apply enhancements
});
```

# Beste praktijken die ik heb geleerd

Na het bouwen van dit spul en het debuggen van rare rand gevallen, hier is wat werkt:

## 1. Bewaar altijd originele inhoud

Mermaid bewaart de originele diagrambron niet na het renderen. U MOET het zelf opslaan:

```javascript
const originalData = new Map();

// Before first render
element.setAttribute('data-original-code', element.textContent);
originalData.set(element.id, element.textContent);

// When re-rendering
element.innerHTML = originalData.get(element.id);
```

## 2. Opruimen Instances

Geheugenlekken zijn echt. Vernietig instanties voordat er nieuwe worden gemaakt:

```javascript
if (panZoomInstances.has(id)) {
    try {
        panZoomInstances.get(id).destroy();
    } catch (e) {
        console.warn('Failed to destroy:', e);
    }
    panZoomInstances.delete(id);
}
```

## 3. Gebeurtenisdelegatie gebruiken

Koppel geen luisteraars aan individuele knoppen:

```javascript
// ❌ Don't do this
buttons.forEach(btn => {
    btn.addEventListener('click', handler);
});

// ✅ Do this
document.addEventListener('click', (e) => {
    if (e.target.matches('.mermaid-control-btn')) {
        handleClick(e.target);
    }
});
```

## 4. Handle Cloudflare Raketlader

Raketlader vertraagt JavaScript-uitvoering. Wacht op afhankelijkheden:

```javascript
function waitForDependencies(maxAttempts = 50) {
    return new Promise((resolve) => {
        let attempts = 0;

        const check = () => {
            if (window.mermaid && window.htmx && window.Alpine) {
                resolve();
            } else if (attempts >= maxAttempts) {
                resolve();  // Give up
            } else {
                attempts++;
                setTimeout(check, Math.min(50 * Math.pow(1.2, attempts), 500));
            }
        };

        check();
    });
}
```

En sluit je hoofdscript uit van Rocket Loader:

```html
<script src="main.js" data-cfasync="false"></script>
```

## 5. Timing is alles

Gebruik `requestAnimationFrame` voor een betere timing dan willekeurig `setTimeout`:

```javascript
// After Mermaid renders
await mermaid.run();

// Wait for paint before enhancing
await new Promise(resolve => {
    requestAnimationFrame(() => {
        requestAnimationFrame(() => {
            enhanceMermaidDiagrams();
            resolve();
        });
    });
});
```

## 6. Defensive SVG Handling

SVG's kunnen raar zijn. Controleer altijd:

```javascript
const svgElement = container.querySelector('svg');
if (!svgElement) {
    console.warn('No SVG found');
    return;
}

// Clone before modifying
const cloned = svgElement.cloneNode(true);

// Ensure viewBox exists
let viewBox = cloned.getAttribute('viewBox');
if (!viewBox) {
    const bbox = svgElement.getBBox();
    viewBox = `${bbox.x} ${bbox.y} ${bbox.width} ${bbox.height}`;
}
```

# Tips voor debuggen

## Console-uitvoer

Met de juiste initialisatie, moet je zien:

```
Saving original data
Loading mermaid with theme: dark
Mermaid initialized
Enhanced 3 diagrams
```

## Controlelijst testen

Na de implementatie van verbeteringen:

- [ ] Diagramweergave op paginabelasting
- [ ] Werk van pan/zoombesturingen
- [ ] Volledig scherm opent/sluit (X, klik buiten, ESC)
- [ ] PNG export vangt volledig diagram
- [ ] SVG export bewaart vectoren
- [ ] Werkt na HTMX content swap
- [ ] Thema's die correct overschakelen
- [ ] Mobiel responsief
- [ ] Donkere modus styling
- [ ] Bereikbaarheid toetsenbord

## Gemeenschappelijke vraagstukken

**Diagram niet weergeven:**

- Controleer browserconsole op fouten
- Controleer of Mermaid geladen is (`window.mermaid`)
- diagram syntaxis controleren

**Pan/zoom werkt niet:**

- Svg-pan-zoom geïnitialiseerd verifiëren
- Controle op tegenstrijdige CSS (`pointer-events: none`)
- Inspecteer instance map

**Export vangt alleen hoek:**

- Ontbrekende viewBox bewaring
- Niet verwijderd transformeren
- Kloonlogica controleren

**Thema niet schakelen:**

- Originele gegevens niet opgeslagen
- `data-processed` niet opnieuw ingesteld
- Gebeurtenisluisteraars niet geregistreerd

# Prestatieoverwegingen

## Luie initialisatie

Laad geen verbeteringen totdat nodig:

```javascript
let enhancementsLoaded = false;

async function loadEnhancements() {
    if (enhancementsLoaded) return;

    const { enhanceMermaidDiagrams } = await import('./enhancements.js');
    enhanceMermaidDiagrams();
    enhancementsLoaded = true;
}

// Load on first interaction
document.addEventListener('click', (e) => {
    if (e.target.closest('.mermaid')) {
        loadEnhancements();
    }
}, { once: true });
```

## Intersectie-waarnemer

Schema's alleen renderen als ze zichtbaar zijn:

```javascript
const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
        if (entry.isIntersecting) {
            renderDiagram(entry.target);
            observer.unobserve(entry.target);
        }
    });
}, { rootMargin: '100px' });

document.querySelectorAll('.mermaid').forEach(el => {
    observer.observe(el);
});
```

## Renders ongedaan maken

Bij verandering van grootte of thema:

```javascript
let timeout;
window.addEventListener('resize', () => {
    clearTimeout(timeout);
    timeout = setTimeout(() => {
        panZoomInstances.forEach(instance => {
            instance.resize();
            instance.fit();
        });
    }, 250);
});
```

# Conclusie

Mermaid.js is fantastisch uit de doos, maar begrijpen hoe het intern werkt laat je een aantal echt coole verbeteringen bouwen. De belangrijkste inzichten:

1. **Pijpleiding renderen**: Tekst → Lexer → Parser → AST → Renderer → SVG
2. **Extensiepunten**: Config, thema's, verbeteringen na render
3. **Originele gegevens opslaan**Mermaid doet het niet voor jou.
4. **Hulpbronnen opruimen**: Geheugenlekken zijn echt
5. **Delegatie van evenementen**: Betere prestaties
6. **Meerdere themabronnen**: Sites behandelen thema's anders
7. **Timing**Gebruik `requestAnimationFrame`

Alle technieken die ik hier heb behandeld worden gebruikt in de productie op deze site en verpakt in [@mostlylucid/mermaid-enhancements](https://www.npmjs.com/package/@mostlylucid/mermaid-enhancements). De volledige bron is beschikbaar op [meestal lucidweb/meestal lucid-meermin](https://github.com/scottgal/mostlylucidweb/tree/main/mostlylucid-mermaid).

## Gerelateerde berichten

- [Meermin.js toevoegen met htmx](/blog/mermaidandhtmx)
- [Thema's voor Mermaid wisselen](/blog/switchingthemesformermaid)
- [Meerminnendiagrammen verbeteren met Pan/Zoom en Export](/blog/enhancingmermaiddiagramswithpanzoomandexport)
- [Publishing Mermaid Enhancements as an npm Package](/blog/publishingmermaidenhancementsnpm)

## Middelen

- [Mermaid.js Documentatie](https://mermaid.js.org/)
- [Zeemeermin GitHub](https://github.com/mermaid-js/mermaid)
- [svg-pan-zoom](https://github.com/bumbu/svg-pan-zoom)
- [html-to-image](https://github.com/bubkoo/html-to-image)
- [Mijn Mermaid Enhancements Pakket](https://www.npmjs.com/package/@mostlylucid/mermaid-enhancements)

Probeer de knoppen op de diagrammen hierboven!