# Sirmaid.js Plongée profonde: comment cela fonctionne réellement et comment l'étendre

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

# Présentation

> REMARQUE: Ceci fait partie de mes expériences avec l'IA / un moyen de dépenser 1000 $ Code Calude crédits Web. J'ai alimenté ceci un BUNCH de papiers, ma compréhension, questions que j'ai dû générer cet article. C'est amusant et comble un vide que je n'ai pas vu comblé nulle part ailleurs.

> **Ce post s'appuie sur les articles précédents:** Si tu ne l'as pas encore fait, regarde. [Ajouter sirmaid.js avec htmx](/blog/mermaidandhtmx), [Thèmes de commutation pour sirène](/blog/switchingthemesformermaid), et [Améliorer les diagrammes de sirène avec Pan/Zoom et Export](/blog/enhancingmermaiddiagramswithpanzoomandexport). Cette plongée profonde explique les internes derrière ces implémentations.

Sirmaid.js est vraiment brillant. Ecrivez du texte simple, obtenez de beaux diagrammes. Plus de trébuchement avec Visio ou draw.io, perdre des fichiers sources, ou maintenir des fichiers d'image séparés. Tout vit en balisage, contrôlé en version à côté de votre code.

Mais je voulais savoir. *Comment* En fait, ça marche sous le capot.

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

...devenir un SVG réel? Et plus important, comment pouvez-vous l'accrocher pour ajouter des fonctionnalités comme le pan/zoom, le changement de thème, et la fonctionnalité d'exportation que j'ai construit pour ce site (maintenant disponible comme [@mostlylucide/mermaid-enhancements](https://www.npmjs.com/package/@mostlylucid/mermaid-enhancements))?

Après beaucoup de recherches dans le code source de Sirmaid et de construction de vraies extensions, voici tout ce que j'ai appris sur le fonctionnement interne de Sirmaid et comment l'étendre correctement.

[TOC]

# Qu'est-ce que Sirmaid.js ?

Sirène transforme les définitions de texte en diagrammes. Pensez "Marquage pour les diagrammes."

**L'ancienne façon :**

1. Ouvrir l'outil de diagramme
2. Créer un diagramme
3. Exportation en tant que PNG
4. Intégré dans les docs
5. Besoin de mettre à jour? Trouver le fichier source, éditer, réexporter, remplacer l'image...

**La manière de la sirène :**

1. Écrire le diagramme dans le texte
2. Fait

Mettre à jour? Il suffit de modifier le texte. Contrôle de la version? C'est juste du texte! Fonctionne en balisage? Oui!

## Types de diagrammes

La sirène supporte un nombre ridicule de types de diagrammes :

```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...]
```

Voir [les documents de sirène](https://mermaid.js.org/intro/) pour la liste complète.

# Comment fonctionne réellement la sirène : le pipeline

Voici ce qui se passe quand Sirmaid rend un diagramme :

```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
```

Découpons chaque pas.

## Étape 1: Définition du texte

Tout commence par du texte. Vous écrivez des diagrammes dans le DSL de Sirmaid (langue spécifique au domaine):

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

## Étape 2 : Analyse lexique

Le lexer brise le texte en jetons. Par exemple, cette ligne :

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

Devient des jetons comme:

```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 { }
]
```

## Étape 3 : Parsing et génération d'AST

L'analyseur consomme des jetons et construit un 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' }
    ]
}
```

Sirène utilise différents parseurs pour chaque type de diagramme. Ceux-ci sont souvent générés à partir de fichiers de grammaire en utilisant [Jison](https://github.com/zaach/jison) (comme Yacc/Bison pour JavaScript).

## Étape 4: Détection des diagrammes

Sirène détecte le type de diagramme à partir de la première ligne:

```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
```

## Étape 5: Délivrance spécifique au type

Chaque type de diagramme a son propre rendeur. Le rendeur prend l'AST et génère des éléments SVG.

Pour les diagrammes de flux, Mermaid utilise [M. Dagre](https://github.com/dagrejs/dagre) bibliothèque pour la mise en page graphique. Pour d'autres, il utilise des algorithmes personnalisés ou des bibliothèques comme 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);
};
```

## Étape 6: Génération SVG

Le rendu produit le balisage SVG :

```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>
```

## Étape 7: Insertion DOM

La sirène trouve tout `.mermaid` les éléments et les remplace par SVG rendu:

```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;
    }
};
```

## Étape 8: Post-processing (où vous entrez)

Après la sirène insère le SVG, vous pouvez l'améliorer. C'est là que toutes mes améliorations s'accrochent:

- Fonctions Pan/zoom
- Boutons de commande
- Capacités d'exportation
- Changement de thème

Plus sur ceci ci-dessous.

# Sirène d'extension : les points d'extension

Maintenant que nous savons comment fonctionne la sirène, nous allons explorer comment l'étendre.

## 1. Configuration

L'extension la plus basique est la configuration:

```javascript
import mermaid from 'mermaid';

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

## 2. Personnalisation des thèmes

J'ai largement couvert cette question en [Thèmes de commutation pour sirène](/blog/switchingthemesformermaid), mais voici la mise en œuvre clé:

### Le problème avec le changement de thème

La sirène a besoin d'être initialisée avec un thème, et vous ne pouvez pas le changer après. MAIS si vous voulez rendre des diagrammes avec un nouveau thème, vous avez besoin de la source du diagramme original — qui Mermaid *ne stocke pas dans les DOM*.

### La solution

Conservez le contenu original avant le rendu, puis restaurez et renvoyez lors de la commutation des thèmes :

```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;
        }
    }
};
```

**Méthodes de détection de thèmes multiples** (les sites traitent les thèmes différemment):

```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';
}
```

Voir [le code du commutateur de thème complet](https://github.com/scottgal/mostlylucidweb/blob/main/Mostlylucid/src/js/memmaid_theme_switch.js) pour plus de détails.

## 3. Améliorations postérieures à l ' appel d ' offres

C'est là que se produit la vraie magie. Après les rendus de Sirmaid, vous pouvez ajouter des fonctionnalités interactives.

J'ai largement couvert cette question en [Améliorer les diagrammes de sirène avec Pan/Zoom et Export](/blog/enhancingmermaiddiagramswithpanzoomandexport), donc je vais mettre en évidence les techniques clés ici.

### Diagrammes d'emballage

Créer un conteneur d'emballage pour les commandes :

```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;
}
```

### Ajouter Pan/Zoom

Utilisation [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;
}
```

### Boutons de contrôle

Créer un panneau de commande flottant :

```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);
}
```

### Délégation de l'événement (Performance!)

N'attachez pas les auditeurs à chaque bouton. Utilisez la délégation d'événement:

```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
    }
});
```

### Fonctionnalité de l'exportation

**Le défi :** Les éléments SVG ont un dimensionnement dynamique, des transformations pan/zoom et des styles hérités. Pour exporter correctement, vous devez :

1. Clone le SVG
2. Préserver les dimensions
3. Supprimer les transformations
4. Convertir en PNG ou SVG

Utilisation [html-à-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);
}
```

**Détails critiques:**

- **Préserver la fenêtre** - Capture l'ensemble du diagramme, pas seulement la partie visible
- **Affichage hors écran** - Évitez d'affecter le diagramme affiché
- **pixelRatio: 2** - IDP élevé pour les exportations nettes de PNG

Voir [le code d'exportation complet](https://github.com/scottgal/mostlylucidweb/blob/main/Mostlylucid/src/js/mermaid_enhancements.js#L148) pour plus de détails.

# L'ensemble complet de mesures d'amélioration

J'ai emballé toutes ces améliorations comme [@mostlylucide/mermaid-enhancements](https://www.npmjs.com/package/@mostlylucid/mermaid-enhancements)Voir [Édition Sirène Améliorations en tant que paquet npm](/blog/publishingmermaidenhancementsnpm) pour plus de détails.

Voici comment tout s'harmonise :

```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
```

## Utilisation

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

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

await init();
```

Vos diagrammes de Sirène ont maintenant :

- Pan/zoom interactif
- Boîte à lumière plein écran
- Exportation de PNG/SVG
- Interrupteur automatique du thème
- Conception sensible

# Intégration avec HTMX

Comme je l'ai couvert [Ajouter sirmaid.js avec htmx](/blog/mermaidandhtmx), vous devez réinitialiser la sirène après les swaps de contenu HTMX:

```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();
});
```

Avec le paquet d'améliorations:

```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
});
```

# Meilleures pratiques que j'ai apprises

Après avoir construit ce truc et débogé des cas bizarres de bord, voici ce qui fonctionne:

## 1. Toujours conserver le contenu original

Sirène ne conserve pas la source du diagramme d'origine après le rendu. Vous devez le stocker vous-même:

```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. Cas de nettoyage

Les fuites de mémoire sont réelles. Détruisez les instances avant de créer de nouvelles:

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

## 3. Utiliser la délégation d'événement

N'attachez pas d'auditeurs à des boutons individuels :

```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. Poignée de chargeuse de Rocket Cloudflare

Rocket Loader retarde l'exécution JavaScript. Attendez les dépendances :

```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();
    });
}
```

Et exclure votre script principal de Rocket Loader:

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

## 5. Le timing, c'est tout

Utilisation `requestAnimationFrame` pour un meilleur timing qu'arbitraire `setTimeout`:

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

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

## 6. Manipulation de SVG défensive

Les SVG peuvent être bizarres.

```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}`;
}
```

# Conseils de débogage

## Sortie de la console

Avec l'initialisation appropriée, vous devriez voir:

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

## Liste de contrôle des essais

Après la mise en œuvre des améliorations:

- [ ] Diagrammes rendus sur le chargement de la page
- [ ] Travail des commandes Pan/zoom
- [ ] Plein écran s'ouvre/ferme (X, cliquez à l'extérieur, ESC)
- [ ] L'exportation de PNG capture le diagramme complet
- [ ] L'exportation SVG préserve les vecteurs
- [ ] Fonctionne après l'échange de contenu HTMX
- [ ] Le changement de thème re-renders correctement
- [ ] Réceptif mobile
- [ ] Style en mode sombre
- [ ] Accessibilité du clavier

## Questions communes

**Diagramme non rendu:**

- Vérifier les erreurs de la console du navigateur
- Vérification de la sirène chargée (`window.mermaid`)
- Vérifier la syntaxe du diagramme

**Pan/zoom ne fonctionne pas:**

- Vérifier svg-pan-zoom initialisé
- Vérifier si le CSS est en conflit (`pointer-events: none`)
- Inspecter la carte de l'instance

**Captures à l'exportation seulement dans le coin :**

- Préservation de viewBox manquante
- La transformation n'a pas été enlevée
- Vérifier la logique du clonage

**Thème non commuté :**

- Données originales non enregistrées
- `data-processed` ne pas réinitialiser
- Auditeurs d'événements non enregistrés

# Considérations de performance

## Initialisation paresseuse

Ne chargez pas les améliorations jusqu'à ce qu'elles soient nécessaires :

```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 });
```

## Observateur intersectionnel

Diagrammes de rendu uniquement lorsqu'ils sont visibles:

```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);
});
```

## Dénoncer les renfloueurs

Sur redimensionnement ou changement de thème :

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

# En conclusion

Sirmaid.js est fantastique hors de la boîte, mais comprendre comment il fonctionne en interne vous permet de construire des améliorations vraiment cool.

1. **Pipeline d'appel d'offres**: Texte → Lexer → Parser → AST → Renderer → SVG
2. **Points d'extension**: Config, thèmes, améliorations post-render
3. **Stocker les données originales**: La sirène ne le fait pas pour toi
4. **Ressources de nettoyage**: Les fuites de mémoire sont réelles
5. **Délégation de l'événement**: Meilleure performance
6. **Sources de thèmes multiples**: Les sites traitent les thèmes différemment
7. **Questions relatives au calendrier**: Utilisation `requestAnimationFrame`

Toutes les techniques que j'ai couvertes ici sont utilisées en production sur ce site et emballées dans [@mostlylucide/mermaid-enhancements](https://www.npmjs.com/package/@mostlylucid/mermaid-enhancements). La source complète est disponible à l'adresse suivante: [principalementlucideweb/mermaid le pluslylucide](https://github.com/scottgal/mostlylucidweb/tree/main/mostlylucid-mermaid).

## Postes connexes

- [Ajouter sirmaid.js avec htmx](/blog/mermaidandhtmx)
- [Thèmes de commutation pour sirène](/blog/switchingthemesformermaid)
- [Améliorer les diagrammes de sirène avec Pan/Zoom et Export](/blog/enhancingmermaiddiagramswithpanzoomandexport)
- [Édition Sirène Améliorations en tant que paquet npm](/blog/publishingmermaidenhancementsnpm)

## Ressources

- [Sirmaid.js Documentation](https://mermaid.js.org/)
- [Sirène GitHub](https://github.com/mermaid-js/mermaid)
- [Svg-pan-zoom](https://github.com/bumbu/svg-pan-zoom)
- [html-à-image](https://github.com/bubkoo/html-to-image)
- [Ma trousse d'améliorations de sirène](https://www.npmjs.com/package/@mostlylucid/mermaid-enhancements)

Essayez les contrôles sur les diagrammes ci-dessus!