# Γοργόνα.js βαθιά κατάδυση: Πώς λειτουργεί πραγματικά και πώς να επεκταθεί

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

# Εισαγωγή

> ΣΗΜΕΙΩΣΗ: Αυτό είναι μέρος των πειραμάτων μου με AI / ένας τρόπος για να περάσετε $ 1000 Calude Code Web πιστώσεις. Έχω ταΐσει αυτό ένα BUNCH των εγγράφων, την κατανόησή μου, ερωτήσεις που έπρεπε να δημιουργήσω αυτό το άρθρο. Είναι διασκεδαστικό και γεμίζει ένα κενό που δεν έχω δει πουθενά αλλού.

> **Αυτή η δημοσίευση βασίζεται σε προηγούμενα άρθρα:** Αν δεν έχετε ήδη, ελέγξτε έξω [Προσθήκη γοργόνας.js με htmx](/blog/mermaidandhtmx), [Αλλαγή θεμάτων για τη Γοργόνα](/blog/switchingthemesformermaid), και [Ενίσχυση Διαγραμμάτων Γοργόνας με Pan/Zoom και Εξαγωγή](/blog/enhancingmermaiddiagramswithpanzoomandexport)Αυτή η βαθιά κατάδυση εξηγεί τα εσωτερικά πίσω από αυτές τις εφαρμογές.

Mermaid.js είναι πραγματικά λαμπρό. Γράψτε απλό κείμενο, να πάρετε όμορφα διαγράμματα. Τέρμα οι αστοχίες με Visio ή κλήρωση.io, χάνοντας αρχεία πηγή, ή τη διατήρηση ξεχωριστών αρχείων εικόνας.

Αλλά ήθελα να μάθω. *Πώς* Δουλεύει κάτω από την κουκούλα.

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

...γίνετε ένα πραγματικό SVG; Και το πιο σημαντικό, πώς μπορείτε να συνδέσετε σε αυτό για να προσθέσετε χαρακτηριστικά όπως το pan / ζουμ, αλλαγή θέματος, και εξαγωγή λειτουργικότητα που έφτιαξα για αυτό το site (τώρα διαθέσιμο ως [@mostly διαυγής/mermaid-enhancements](https://www.npmjs.com/package/@mostlylucid/mermaid-enhancements))?

Μετά από πολύ σκάψιμο μέσω του πηγαίου κώδικα της Γοργόνας και την κατασκευή πραγματικών επεκτάσεων, εδώ είναι όλα όσα έμαθα σχετικά με το πώς η Γοργόνα λειτουργεί εσωτερικά και πώς να επεκταθεί σωστά.

[TOC]

# Τι είναι η Γοργόνα;

Η Γοργόνα μετατρέπει τους ορισμούς κειμένου σε διαγράμματα.

**Ο παλιός τρόπος:**

1. Ανοικτό εργαλείο διαγραμματισμού
2. Δημιουργία διαγράμματος
3. Εξαγωγή ως PNG
4. Ενσωμάτωση σε γιατρούς
5. Βρείτε το αρχείο πηγής, επεξεργασία, επανεξαγωγή, αντικατάσταση εικόνας...

**Ο τρόπος της Γοργόνας:**

1. Γράψτε το διάγραμμα στο κείμενο
2. Έγινε.

Ενημέρωσέ το; Απλά επεξεργάζεσαι το κείμενο.

## Τύποι διαγραμμάτων

Η Γοργόνα υποστηρίζει έναν γελοίο αριθμό τύπων διαγραμμάτων:

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

Βλέπεις; [Οι Γιατροί της Γοργόνας](https://mermaid.js.org/intro/) για την πλήρη λίστα.

# Πώς Λειτουργεί Πράγματι η Γοργόνα: Ο αγωγός

Να τι συμβαίνει όταν η Γοργόνα κάνει ένα διάγραμμα:

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

Ας σπάσουμε κάθε βήμα.

## Βήμα 1: Ορισμός κειμένου

Τα πάντα ξεκινούν με το κείμενο. Γράφετε διαγράμματα στο DSL της Γοργόνας (demain-special language):

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

## Βήμα 2: Λεξική Ανάλυση

Ο lexer σπάει το κείμενο σε μάρκες. Για παράδειγμα, αυτή η γραμμή:

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

Γίνεται μάρκες όπως:

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

## Βήμα 3: Γενιά ανάλυσης και AST

Ο parser καταναλώνει μάρκες και δημιουργεί ένα αφηρημένο δέντρο σύνταξης (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' }
    ]
}
```

Η Γοργόνα χρησιμοποιεί διαφορετικούς πίνακες για κάθε τύπο διαγράμματος. [Τζίσον](https://github.com/zaach/jison) (όπως Yacc/Bison για JavaScript).

## Βήμα 4: Ανίχνευση διαγράμματος

Γοργόνα ανιχνεύει τον τύπο διαγράμματος από την πρώτη γραμμή:

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

## Βήμα 5: Εκχώρηση τύπου-ειδικού τύπου

Κάθε τύπος διαγράμματος έχει το δικό του depter. Ο depter παίρνει το AST και παράγει στοιχεία SVG.

Για charts ροής, η Γοργόνα χρησιμοποιεί το [ΝτάγκρεCity name (optional, probably does not need a translation)](https://github.com/dagrejs/dagre) βιβλιοθήκη για τη διάταξη γραφημάτων. Για άλλους, χρησιμοποιεί προσαρμοσμένους αλγόριθμους ή βιβλιοθήκες όπως το 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);
};
```

## Βήμα 6: SVG Generation

Ο εκτελεστής παράγει 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>
```

## Βήμα 7: Εισαγωγή DOM

Η Γοργόνα τα βρίσκει όλα. `.mermaid` στοιχεία και τα αντικαθιστά με 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;
    }
};
```

## Βήμα 8: Μετα-Επεξεργασία (Πού Έρχεστε)

Αφού η Γοργόνα εισάγει το SVG, μπορείτε να το ενισχύσετε.

- Λειτουργία Pan/zoom
- Κουμπιά ελέγχου
- Εξαγωγικές δυνατότητες
- Αλλαγή θέματος

Περισσότερα γι' αυτό από κάτω.

# Επεκτεινόμενη Γοργόνα: Τα Σημεία Επέκτασης

Τώρα που ξέρουμε πώς λειτουργεί η Γοργόνα, ας εξερευνήσουμε πώς να την επεκτείνουμε.

## 1. Ρύθμιση

Η πιο βασική επέκταση είναι η διαμόρφωση:

```javascript
import mermaid from 'mermaid';

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

## 2. Προσαρμογή θέματος

I covered this extensionly in [Αλλαγή θεμάτων για τη Γοργόνα](/blog/switchingthemesformermaid), αλλά εδώ είναι η βασική εφαρμογή:

### Το Πρόβλημα με την Αλλαγή Θέματος

Γοργόνα πρέπει να αρχικοποιηθεί με ένα θέμα, και δεν μπορείτε να το αλλάξετε μετά. *δεν αποθηκεύει στο DOM*.

### Η Λύση

Αποθηκεύστε το αρχικό περιεχόμενο πριν από την απόδοση, στη συνέχεια αποκαταστήστε και εκ νέου κατά την αλλαγή θεμάτων:

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

**Μέθοδοι ανίχνευσης πολλαπλών θεμάτων** (τοποθεσίες χειρίζονται θέματα διαφορετικά):

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

Βλέπεις; [τον πλήρη κωδικό διακόπτη θέματος](https://github.com/scottgal/mostlylucidweb/blob/main/Mostlylucid/src/js/memmaid_theme_switch.js) για λεπτομέρειες.

## 3. Βελτιώσεις μετά τον αποστολέα

Αυτό είναι όπου η πραγματική μαγεία συμβαίνει. Αφού η Γοργόνα αποδίδει, μπορείτε να προσθέσετε διαδραστικά χαρακτηριστικά.

I covered this extensionly in [Ενίσχυση Διαγραμμάτων Γοργόνας με Pan/Zoom και Εξαγωγή](/blog/enhancingmermaiddiagramswithpanzoomandexport)Οπότε θα επισημάνω τις βασικές τεχνικές εδώ.

### Διαγράμματα περιτύλιξης

Δημιουργήστε ένα δοχείο περιτυλίγματος για τα χειριστήρια:

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

Χρήση [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;
}
```

### Κουμπιά ελέγχου

Δημιουργία πλωτού πίνακα ελέγχου:

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

### Αντιπροσωπεία event (Performance!)

Μην επισυνάψετε ακροατές σε κάθε κουμπί.

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

### Εξαγωγή Λειτουργικότητας

**Η πρόκληση:** Τα στοιχεία SVG έχουν δυναμικό μέγεθος, το παν/ζωύφιο μεταμορφώνει, και κληρονομημένο στυλ. Για να εξαγάγετε σωστά, θα πρέπει να:

1. Clone the SVG
2. Διατηρήστε τις διαστάσεις
3. Αφαίρεση μεταμορφώσεων
4. Μετάτρεψε σε PNG ή SVG

Χρήση [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);
}
```

**Κρίσιμες λεπτομέρειες:**

- **Διατηρήστε την προβολήBox** - Συλλαμβάνει ολόκληρο το διάγραμμα, όχι μόνο ορατό τμήμα
- **Απόδοση εκτός οθόνης** - Αποφύγετε την επίδραση του διαγράμματος που εμφανίζεται
- **pixelRatio: 2** - Υψηλή DPI για τραγανές εξαγωγές PNG

Βλέπεις; [τον πλήρη κωδικό εξαγωγής](https://github.com/scottgal/mostlylucidweb/blob/main/Mostlylucid/src/js/mermaid_enhancements.js#L148) για περισσότερες λεπτομέρειες.

# Το Πακέτο Πλήρης Ενίσχυση

Πακετάρισα όλες αυτές τις βελτιώσεις ως [@mostly διαυγής/mermaid-enhancements](https://www.npmjs.com/package/@mostlylucid/mermaid-enhancements)- Βλέπεις; [Publishing Mermaid Βελτιώσεις ως ένα πακέτο npm](/blog/publishingmermaidenhancementsnpm) για πλήρεις λεπτομέρειες.

Εδώ είναι πώς όλα ταιριάζουν μεταξύ τους:

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

## Χρήση

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

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

await init();
```

Τα διαγράμματα της Γοργόνας σας έχουν τώρα:

- Διαδραστικό παν/ζωύφιο
- Φωτεινό κουτί πλήρους οθόνης
- Εξαγωγή PNG/SVG
- Αυτόματη αλλαγή θέματος
- Επιταχυντικός σχεδιασμός

# Ενσωμάτωση με HTMX

Όπως καλύπτομαι [Προσθήκη γοργόνας.js με htmx](/blog/mermaidandhtmx), θα πρέπει να επανεκκινήσετε την Γοργόνα μετά τις ανταλλαγές περιεχομένου 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();
});
```

Με το πακέτο βελτιώσεων:

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

# Βέλτιστες Πρακτικές που Έμαθα

Μετά την κατασκευή αυτού του πράγματος και την αποσφαλμάτωση περίεργες ακραίες περιπτώσεις, εδώ είναι τι λειτουργεί:

## 1. Αποθηκεύστε πάντα το αρχικό περιεχόμενο

Η Γοργόνα δεν διατηρεί την αρχική πηγή διαγράμματος μετά την απόδοση.

```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. Καθαρές υποθέσεις

Οι διαρροές μνήμης είναι πραγματικές. Καταστρέψτε περιπτώσεις πριν από τη δημιουργία νέων:

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

## 3. Χρησιμοποιήστε την Αντιπροσωπεία Γεγονότων

Μην επισυνάψετε ακροατές σε μεμονωμένα κουμπιά:

```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. Λαβή Cloudflare Rocket Loader

Rocket Loader καθυστερεί JavaScript εκτέλεση. Περιμένετε για εξαρτήσεις:

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

Και αποκλείστε το σενάριό σας από το Rocket Loader:

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

## 5. Ο συγχρονισμός είναι τα πάντα

Χρήση `requestAnimationFrame` για καλύτερο συγχρονισμό από τον αυθαίρετο `setTimeout`:

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

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

## 6. Αμυντικός χειρισμός SVG

Το SVGs μπορεί να είναι παράξενο.

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

# Συμβουλές αποσφαλμάτωσης

## Έξοδος κονσόλας

Με την κατάλληλη αρχικοποίηση, θα πρέπει να δείτε:

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

## Κατάλογος ελέγχου δοκιμών

Μετά την εφαρμογή των βελτιώσεων:

- [ ] Τα διαγράμματα αποδίδουν στο φορτίο σελίδας
- [ ] Εργασίες ελέγχου Pan/zoom
- [ ] Πλήρης οθόνη ανοίγει / κλείνει (X, κάντε κλικ έξω, ESC)
- [ ] PNG εξαγωγή συλλαμβάνει πλήρες διάγραμμα
- [ ] SVG εξαγωγή διατηρεί φορείς
- [ ] Λειτουργεί μετά από ανταλλαγή περιεχομένου HTMX
- [ ] Μετατροπή θέματος σωστά
- [ ] Mobile responsible
- [ ] Dark mode styling
- [ ] Προσβασιμότητα πληκτρολογίου

## Κοινά θέματα

**Διάγραμμα χωρίς απόδοση:**

- Έλεγχος κονσόλας προγράμματος περιήγησης για σφάλματα
- Επιβεβαίωση φορτωμένης Γοργόνας (`window.mermaid`)
- Έλεγχος σύνταξης διαγράμματος

**Παν/ζωύφιο που δεν λειτουργεί:**

- Επιβεβαίωση αρχικοποίησης svg-pan-zoom
- Έλεγχος για αντικρουόμενες CSS (`pointer-events: none`)
- Εποπτικό παράδειγμα χάρτη

**Εξαγωγή συλλαμβάνει μόνο γωνία:**

- Χαμένη προβολήName
- Μετασχηματιστής μη αφαιρούμενος
- Έλεγχος λογικής κλωνοποίησης

**Θέμα που δεν αλλάζει:**

- Τα αρχικά δεδομένα δεν αποθηκεύτηκαν
- `data-processed` Δεν αναστοιχειώνεται
- Δεν είναι εγγεγραμμένοι ακροατές εκδηλώσεων

# Εκτιμήσεις Απόδοσης

## Τεμπέλης Αρχικοποίησης

Μην φορτώνετε τις βελτιώσεις μέχρι να χρειαστεί:

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

## Παρατηρητής διατομής

Αποδώστε διαγράμματα μόνο όταν είναι ορατά:

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

## Αναβοσβήνει τους επαναδιανομείς

Για αλλαγή μεγέθους ή θέματος:

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

# Συμπέρασμα

Η Mermaid.js είναι φανταστική έξω από το κουτί, αλλά η κατανόηση πώς λειτουργεί εσωτερικά σας επιτρέπει να χτίσει μερικές πραγματικά δροσερό βελτιώσεις.

1. **Σωλήνας αποστολής**→ Lexer → Parser → AST → Renderer → SVG
2. **Σημεία επέκτασης**: Config, θέματα, μετεγχειρητικές βελτιώσεις
3. **Αποθηκεύστε τα αρχικά δεδομένα**Η Γοργόνα δεν το κάνει για σένα.
4. **Καθαρισμός πόρων**: Οι διαρροές μνήμης είναι πραγματικές
5. **Αντιπρόσωπο γεγονότων**: Καλύτερη απόδοση
6. **Πολλαπλές πηγές θέματος**: Οι ιστοσελίδες χειρίζονται διαφορετικά θέματα
7. **Θέματα Χρονολόγησης**: Χρήση `requestAnimationFrame`

Όλες οι τεχνικές που έχω καλύψει εδώ χρησιμοποιούνται στην παραγωγή σε αυτό το site και συσκευάζονται σε [@mostly διαυγής/mermaid-enhancements](https://www.npmjs.com/package/@mostlylucid/mermaid-enhancements). Η πλήρης πηγή είναι διαθέσιμη στο [ως επί το πλείστον διαυγής ιστός/ ως επί το πλείστον διαυγής-χρήστης](https://github.com/scottgal/mostlylucidweb/tree/main/mostlylucid-mermaid).

## Σχετικές Δημοσιεύσεις

- [Προσθήκη γοργόνας.js με htmx](/blog/mermaidandhtmx)
- [Αλλαγή θεμάτων για τη Γοργόνα](/blog/switchingthemesformermaid)
- [Ενίσχυση Διαγραμμάτων Γοργόνας με Pan/Zoom και Εξαγωγή](/blog/enhancingmermaiddiagramswithpanzoomandexport)
- [Publishing Mermaid Βελτιώσεις ως ένα πακέτο npm](/blog/publishingmermaidenhancementsnpm)

## Πόροι

- [Γοργόνα.js Documentation](https://mermaid.js.org/)
- [Γοργόνα ΓκίτχουμπCity name (optional, probably does not need a translation)](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)
- [Το πακέτο μου για τις Βελτιώσεις της Γοργόνας](https://www.npmjs.com/package/@mostlylucid/mermaid-enhancements)

Δοκιμάστε τα χειριστήρια στα διαγράμματα παραπάνω!