# Δημοσιεύω ένα πακέτο NPM!! Publishing Mermaid Βελτιώσεις ως ένα πακέτο npm

<!--category-- JavaScript, TypeScript, Mermaid, npm -->
<datetime class="hidden">2025-11-07T16:00</datetime>

# Εισαγωγή

Εγώ... ένας τύπος από το .net βρήκε επιτέλους το κουράγιο να βουτήξει τα δάχτυλα των ποδιών μου στον κόσμο των πακέτων!
Γοργόνα.js είναι αρκετά σκοτεινό και αρκετά περίεργο ότι θα μπορούσα πραγματικά να παραδώσει κάτι χρήσιμο!

Μετά την κατασκευή κάποιων πραγματικά χρήσιμες βελτιώσεις για διαγράμματα Mermaid.js (διαδραστικό pan/zoom, fullscreen lightbox, εξαγωγή σε PNG/SVG, και αυτόματη αλλαγή θέματος), αποφάσισα ότι ήταν καιρός να τα συσκευάσει σωστά και να τα μοιραστούν με την κοινότητα. `@mostlylucid/mermaid-enhancements` ως πακέτο παραγωγής-έτοιμο npm.

> ΣΗΜΕΙΩΣΗ: Εξακολουθεί να εργάζεται για την απελευθέρωση. Μείνετε συντονισμένοι (το πρώτο πακέτο μου npm έτσι παίρνει λίγο)

[TOC]

[![έκδοση npm](https://img.shields.io/npm/v/@mostlylucid/mermaid-enhancements.svg)](https://www.npmjs.com/package/@mostlylucid/mermaid-enhancements)
[![npm downloads](https://img.shields.io/npm/dm/@mostlylucid/mermaid-enhancements.svg)](https://www.npmjs.com/package/@mostlylucid/mermaid-enhancements)
[![Άδεια: Unlicense](https://img.shields.io/badge/License-Unlicense-green.svg)](https://opensource.org/licenses/MIT)
[![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
[![Μέγεθος bundleName](https://img.shields.io/bundlephobia/minzip/@mostlylucid/mermaid-enhancements)](https://bundlephobia.com/package/@mostlylucid/mermaid-enhancements)

# Γιατί το πακετάρετε;

Χρησιμοποιώ αυτές τις βελτιώσεις σε όλο το blog μου εδώ και λίγο καιρό, και έχουν γίνει απαραίτητες για να εργαστούν με σύνθετα διαγράμματα Γοργόνας. Τα χαρακτηριστικά περιλαμβάνουν:

- **Διαδραστικό Pan & ZoomName** - Πλοήγηση μεγάλων διαγραμμάτων ομαλά
- **Fullscreen Lightbox** - Immersive viewing experience
- **Εξαγωγή σε PNG/SVG** - Υψηλής ποιότητας λήψεις διαγραμμάτων
- **Αυτόματη εναλλαγή θέματος** - Αδιάβροχη υποστήριξη τρόπου φωτισμού/σκοτεινής κατάστασης
- **Αναπνευστικός σχεδιασμός** - Εργασίες σε κινητά και επιφάνεια εργασίας

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

# Δομή έργου

Έχω δημιουργήσει μια επαγγελματική δομή πακέτου με την υποστήριξη TypeScript:

```
mostlylucid-mermaid/
├── src/
│   ├── index.ts              # Main entry point
│   ├── enhancements.ts       # Pan/zoom/export functionality
│   ├── theme-switcher.ts     # Theme switching logic
│   ├── types.ts              # TypeScript type definitions
│   └── styles.css            # Complete styling
├── examples/
│   └── demo.html             # Full-featured demo
├── dist/                     # Built output (generated)
├── package.json
├── tsconfig.json
├── README.md
├── QUICKSTART.md
├── PUBLISHING.md
└── LICENSE
```

Το πακέτο χρησιμοποιεί το TypeScript για την ασφάλεια του τύπου και την καλύτερη εμπειρία του προγραμματιστή, αλλά καταρτίζει μέχρι JavaScript για μέγιστη συμβατότητα.

# Η Αρχιτεκτονική

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

## Έτσι φαίνεται!

Έτσι βλέπετε ότι είναι αρκετά συμπαγής και έχει κάποια χρήσιμη λειτουργικότητα πέρα από απλά στατικά διαγράμματα. Πάντα με ενοχλούσε το πώς MASSIVE ήταν στη σελίδα, έτσι ώστε αυτό φαινόταν μια λογική προσέγγιση στο μέγεθος refuckng διατηρώντας τη χρησιμότητα.

```mermaid
graph TD
    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
```

# Βασική εφαρμογή

## Ορισμοί τύπου

Πρώτον, ορίζω τους ολοκληρωμένους τύπους TypeScript:

```typescript
// src/types.ts
export interface PanZoomInstance {
    zoom(scale: number): void;
    zoomIn(): void;
    zoomOut(): void;
    reset(): void;
    fit(): void;
    center(): void;
    resize(): void;
    destroy(): void;
    isPanEnabled(): boolean;
    enablePan(enabled: boolean): void;
}

export type ExportFormat = 'png' | 'svg';
export type Theme = 'dark' | 'default';
export type ControlAction = 'fullscreen' | 'zoomIn' | 'zoomOut' |
                           'reset' | 'pan' | 'exportPng' | 'exportSvg';

export interface EnhancementConfig {
    icons?: IconConfig;
    controls?: {
        fullscreen?: boolean;
        zoom?: boolean;
        pan?: boolean;
        export?: boolean;
    };
}
```

## Κύριο σημείο εισόδου

Το κύριο σημείο εισόδου είναι απλό:

```typescript
// src/index.ts
export {
    enhanceMermaidDiagrams,
    cleanupMermaidEnhancements
} from './enhancements.js';

export {
    initMermaid
} from './theme-switcher.js';

export async function init() {
    await initMermaid();
}

export default {
    init,
    initMermaid,
    enhanceMermaidDiagrams,
};
```

## Εφαρμογή Pan/Zoom

Η λογική ενίσχυσης τυλίγει κάθε διάγραμμα με χειριστήρια και αρχικοποιεί svg-pan-zoom:

```typescript
// src/enhancements.ts
import svgPanZoom from 'svg-pan-zoom';
import { toPng, toSvg } from 'html-to-image';

const panZoomInstances = new Map();

function initPanZoom(svgElement: SVGElement, diagramId: string) {
    // Clean up existing instance if present
    if (panZoomInstances.has(diagramId)) {
        try {
            panZoomInstances.get(diagramId).destroy();
        } catch (e) {
            console.warn('Failed to destroy existing pan-zoom instance:', e);
        }
        panZoomInstances.delete(diagramId);
    }

    try {
        const panZoomInstance = svgPanZoom(svgElement, {
            zoomEnabled: true,
            controlIconsEnabled: false,
            fit: true,
            center: true,
            minZoom: 0.1,
            maxZoom: 10,
            zoomScaleSensitivity: 0.3,
            dblClickZoomEnabled: true,
            mouseWheelZoomEnabled: true,
            preventMouseEventsDefault: true,
            contain: false
        });

        panZoomInstances.set(diagramId, panZoomInstance);
        return panZoomInstance;
    } catch (error) {
        console.error('Failed to initialize pan-zoom:', error);
        return null;
    }
}
```

Τα κουμπιά ελέγχου δημιουργούνται δυναμικά:

```typescript
function createControlButtons(container: HTMLElement, diagramId: string) {
    if (container.querySelector('.mermaid-controls')) {
        return;
    }

    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 View', action: 'reset' },
        { icon: 'bx-move', title: 'Pan', action: 'pan' },
        { icon: 'bx-image', title: 'Export as PNG', action: 'exportPng' },
        { icon: 'bx-code-alt', title: 'Export as SVG', action: 'exportSvg' }
    ];

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

    container.appendChild(controlsDiv);
}
```

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

Η εφαρμογή των εξαγωγών κλωνοποιεί το SVG, διατηρεί το viewBox και χρησιμοποιεί html-to-image:

```typescript
async function exportDiagram(
    container: HTMLElement,
    format: ExportFormat,
    diagramId: string
) {
    try {
        const svgElement = container.querySelector('svg');
        if (!svgElement) {
            console.warn('No diagram found to export');
            return;
        }

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

        // 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 for proper export
        const [, , vbWidth, vbHeight] = viewBox.split(' ').map(Number);
        clonedSvg.setAttribute('width', vbWidth.toString());
        clonedSvg.setAttribute('height', vbHeight.toString());

        // Remove pan-zoom transforms
        clonedSvg.removeAttribute('style');
        clonedSvg.style.backgroundColor = 'transparent';
        clonedSvg.style.maxWidth = 'none';

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

        const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
        const filename = `mermaid-diagram-${timestamp}`;

        if (format === 'png') {
            const dataUrl = await toPng(clonedSvg, {
                backgroundColor: 'white',
                pixelRatio: 2 // Higher quality
            });
            downloadFile(dataUrl, `${filename}.png`);
        } else {
            const dataUrl = await toSvg(clonedSvg, {
                backgroundColor: 'transparent'
            });
            downloadFile(dataUrl, `${filename}.svg`);
        }

        document.body.removeChild(tempDiv);
        console.log(`Diagram exported as ${format.toUpperCase()}`);
    } catch (error) {
        console.error('Failed to export diagram:', error);
    }
}
```

## Αλλαγή θέματος

Ο διακόπτης θέματος χειρίζεται μεθόδους πολλαπλής ανίχνευσης:

```typescript
// src/theme-switcher.ts
export async function initMermaid() {
    // Normalize code fences
    normalizeMermaidCodeFences();

    const mermaidElements = document.querySelectorAll(elementSelector);
    if (mermaidElements.length === 0) return;

    await saveOriginalData();

    // Set up theme change handlers
    const handleDarkThemeSet = async () => {
        await resetProcessed();
        await loadMermaid('dark');
    };

    const handleLightThemeSet = async () => {
        await resetProcessed();
        await loadMermaid('default');
    };

    // Listen for custom theme events
    document.body.addEventListener('dark-theme-set', handleDarkThemeSet);
    document.body.addEventListener('light-theme-set', handleLightThemeSet);

    // OS theme change listener
    if (typeof window.matchMedia === 'function') {
        const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
        mediaQuery.addEventListener('change', async (e) => {
            await resetProcessed();
            await loadMermaid(e.matches ? 'dark' : 'default');
        });
    }

    // Detect current theme with fallbacks
    let isDarkMode = false;
    if (typeof window.__themeState !== 'undefined') {
        isDarkMode = window.__themeState === 'dark';
    } else if (localStorage.theme) {
        isDarkMode = localStorage.theme === 'dark';
    } else if (document.documentElement.classList.contains('dark')) {
        isDarkMode = true;
    } else if (window.matchMedia?.('(prefers-color-scheme: dark)').matches) {
        isDarkMode = true;
    }

    await loadMermaid(isDarkMode ? 'dark' : 'default');
}
```

# Ρύθμιση πακέτων

## package.json

Το πακέτο.json ορίζει πολλαπλά σημεία εισόδου για διαφορετικές περιπτώσεις χρήσης:

```json
{
  "name": "@mostlylucid/mermaid-enhancements",
  "version": "1.0.0",
  "description": "Enhance Mermaid.js diagrams with interactive pan/zoom, fullscreen lightbox, export to PNG/SVG, and automatic theme switching",
  "main": "dist/index.js",
  "module": "src/index.ts",
  "types": "src/types.ts",
  "exports": {
    ".": {
      "types": "./src/types.ts",
      "import": "./src/index.ts",
      "require": "./dist/index.js"
    },
    "./min": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.min.js",
      "require": "./dist/index.min.js"
    },
    "./styles.css": "./src/styles.css"
  },
  "unpkg": "dist/index.min.js",
  "jsdelivr": "dist/index.min.js",
  "scripts": {
    "build": "tsc",
    "minify": "node scripts/minify.js",
    "build:all": "npm run build && npm run minify",
    "prepublishOnly": "npm run build:all",
    "dev": "cd examples && npx http-server -p 3000 -o"
  },
  "peerDependencies": {
    "mermaid": "^10.0.0 || ^11.0.0"
  },
  "dependencies": {
    "html-to-image": "^1.11.11",
    "svg-pan-zoom": "^3.6.1"
  }
}
```

## Ρύθμιση TypeScript

```json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "moduleResolution": "node"
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist", "examples"]
}
```

# Παραδείγματα χρήσης

## Βασική χρήση

Ο απλούστερος τρόπος χρήσης του πακέτου:

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

await init();
```

### Με το θέμα εναλλαγή

Για τοποθεσίες με φωτεινό/σκοτεινό τρόπο:

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

// Initialize
await init();

// When theme changes
function toggleTheme() {
    const isDark = document.body.classList.toggle('dark');
    document.documentElement.classList.toggle('dark', isDark);

    // Notify the enhancements
    const event = new Event(isDark ? 'dark-theme-set' : 'light-theme-set');
    document.body.dispatchEvent(event);
}
```

### Αντιδράστε στην Ενσωμάτωση

```tsx
import { useEffect } from 'react';
import { init, cleanupMermaidEnhancements } from '@mostlylucid/mermaid-enhancements';
import '@mostlylucid/mermaid-enhancements/styles.css';

function MermaidDiagram({ chart }: { chart: string }) {
    useEffect(() => {
        init();
        return () => cleanupMermaidEnhancements();
    }, [chart]);

    return (
        <div className="mermaid">
            {chart}
        </div>
    );
}
```

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

```html
<template>
    <div class="mermaid">{{ chart }}</div>
</template>

<script setup>
import { onMounted, onUnmounted } from 'vue';
import { init, cleanupMermaidEnhancements } from '@mostlylucid/mermaid-enhancements';
import '@mostlylucid/mermaid-enhancements/styles.css';

const props = defineProps(['chart']);

onMounted(async () => {
    await init();
});

onUnmounted(() => {
    cleanupMermaidEnhancements();
});
</script>
```

## Το Demo Page

Δημιούργησα μια ολοκληρωμένη σελίδα επίδειξης που δείχνει όλα τα χαρακτηριστικά:

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Mermaid Enhancements Demo</title>

    <!-- Boxicons for control button icons -->
    <link href="https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css" rel="stylesheet">

    <!-- Mermaid Enhancements CSS -->
    <link rel="stylesheet" href="../src/styles.css">
</head>
<body>
    <!-- Your diagrams -->
    <div class="mermaid">
graph TD
    A[Start] --> B{Is it working?}
    B -->|Yes| C[Great!]
    B -->|No| D[Check setup]
    C --> E[Zoom & Pan]
    D --> F[Read docs]
    E --> G[Export to PNG/SVG]
    </div>

    <!-- Load Mermaid -->
    <script type="module">
        import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
        window.mermaid = mermaid;
    </script>

    <!-- Initialize enhancements -->
    <script type="module">
        import { init } from '../dist/index.js';
        await init();
    </script>
</body>
</html>
```

# Διαδικασία έκδοσης

Εδώ είναι η ροή των εκδοτικών εργασιών:

```mermaid
sequenceDiagram
    participant Dev as Developer
    participant Git as Git Repo
    participant NPM as npm Registry
    participant CDN as unpkg/jsdelivr
    participant User as End User

    Dev->>Dev: Write code
    Dev->>Dev: npm run build:all
    Dev->>Dev: Test locally

    Dev->>Git: git commit & push
    Dev->>Git: Create version tag

    Dev->>NPM: npm login
    Dev->>NPM: npm publish --access public

    NPM-->>CDN: Sync package

    User->>NPM: npm install
    User->>CDN: Import from CDN

    NPM-->>User: Deliver package
    CDN-->>User: Serve files
```

## Βήμα προς βήμα

1. **Κατασκευή του πακέτου:**

```bash
npm run build:all  # Compiles TypeScript and minifies
```

2. **Δοκιμή τοπικά:**

```bash
npm run dev  # Opens demo at localhost:3000
```

3. **Ανατροπή έκδοσης:**

```bash
npm version patch  # or minor, or major
```

4. **Δημοσίευση:**

```bash
npm login
npm publish --access public
```

Το πακέτο διατίθεται τώρα μέσω:

- npm: `npm install @mostlylucid/mermaid-enhancements`
- unpkg CDN: `https://unpkg.com/@mostlylucid/mermaid-enhancements`
- CDN jsdelivr: `https://cdn.jsdelivr.net/npm/@mostlylucid/mermaid-enhancements`

## Στρατηγική ελαχιστοποίησης

Πρόσθεσα ένα σενάριο ευνουχισμού για να μειώσει το μέγεθος του πακέτου:

```javascript
// scripts/minify.js
const { minify } = require('terser');
const fs = require('fs');
const path = require('path');

async function minifyFile(inputPath, outputPath) {
    const code = fs.readFileSync(inputPath, 'utf8');

    const result = await minify(code, {
        compress: {
            dead_code: true,
            drop_console: false,
            drop_debugger: true,
            keep_classnames: true,
            keep_fnames: true,
        },
        mangle: {
            keep_classnames: true,
            keep_fnames: true,
        },
        format: {
            comments: false,
        },
    });

    fs.writeFileSync(outputPath, result.code);

    const originalSize = fs.statSync(inputPath).size;
    const minifiedSize = fs.statSync(outputPath).size;
    const reduction = ((1 - minifiedSize / originalSize) * 100).toFixed(1);

    console.log(`✓ ${path.basename(outputPath)}: ${originalSize} → ${minifiedSize} bytes (${reduction}% smaller)`);
}

// Minify main bundle
minifyFile(
    path.join(__dirname, '../dist/index.js'),
    path.join(__dirname, '../dist/index.min.js')
);
```

Αποτελέσματα:

- Κανονική: 23.46 KB
- Μειωμένη: 9.78 KB (58,3% μείωση!)

# Τεκμηρίωση

Δημιούργησα πλήρη τεκμηρίωση:

- **Readme.md** - Πλήρης αναφορά API, παραδείγματα, αντιμετώπιση προβλημάτων
- **QUICKSTART.md** - 5 λεπτά για να ξεκινήσετε τον οδηγό
- **ΕΚΔΙΔΟΝΤΑΣ. md** - οδηγίες δημοσίευσης
- **ΑΛΛΑΓΗ.md** - Ιστορία έκδοσης

# Στυλ

Το CSS ανταποκρίνεται πλήρως και υποστηρίζει τη σκοτεινή λειτουργία:

```css
/* Diagram wrapper */
.mermaid-wrapper {
    position: relative;
    border-radius: 0.5rem;
    overflow: hidden;
    width: 100%;
    margin: 1rem 0;
}

/* Control buttons */
.mermaid-controls {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    display: flex;
    gap: 0.25rem;
    z-index: 10;
    background: rgba(255, 255, 255, 0.9);
    border-radius: 0.5rem;
    padding: 0.25rem;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.dark .mermaid-controls {
    background: rgba(31, 41, 55, 0.95);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}

/* Individual buttons */
.mermaid-control-btn {
    padding: 0.5rem;
    border-radius: 0.25rem;
    cursor: pointer;
    transition: all 0.2s;
    background: transparent;
    border: none;
    color: #4b5563;
    font-size: 1.25rem;
}

.mermaid-control-btn:hover {
    background: rgba(37, 99, 235, 0.1);
    color: #2563eb;
    transform: scale(1.1);
}
```

# Μαθήματα που Έμαθαν

## 1. TypeScript είναι αξίζει τον κόπο

Ακόμη και για μια μικρή βιβλιοθήκη, το TypeScript έπιασε αρκετά σφάλματα κατά τη διάρκεια της ανάπτυξης και παρέχει εξαιρετική υποστήριξη IDE για τους χρήστες.

## 2. Πολλαπλά σημεία εισόδου θέμα

Υποστήριξη και των δύο `import` και `require`, συν την προσφορά μιας ψηφιοποιημένης έκδοσης, καθιστά το πακέτο πιο ευέλικτο:

```json
"exports": {
    ".": {
      "types": "./src/types.ts",
      "import": "./src/index.ts",
      "require": "./dist/index.js"
    },
    "./min": {
      "import": "./dist/index.min.js"
    }
}
```

## 3. Demo είναι ουσιαστικό

Η σελίδα demo με βοήθησε να πιάσω σφάλματα και χρησιμεύει ως ζωντανή τεκμηρίωση.

## 4. Ο καθαρισμός είναι σημαντικός

Πάντα να παρέχει λειτουργίες καθαρισμού για τη διαχείριση μνήμης:

```typescript
export function cleanupMermaidEnhancements() {
    panZoomInstances.forEach((instance, id) => {
        try {
            instance.destroy();
        } catch (e) {
            console.warn(`Failed to destroy pan-zoom instance ${id}:`, e);
        }
    });
    panZoomInstances.clear();
}
```

## 5. Η ανίχνευση θέματος χρειάζεται fallbacks

Διαφορετικές ιστοσελίδες χειρίζονται τα θέματα διαφορετικά, έτσι εφάρμοσα πολλαπλές μεθόδους ανίχνευσης:

1. Global state (`window.__themeState`)
2. Τοπική Αποθήκευση (`localStorage.theme`)
3. Κατηγορία DOM (`document.documentElement.classList`)
4. Προτιμήσεις OS (`prefers-color-scheme`)

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

Το πακέτο βελτιστοποιείται για την απόδοση:

- **Αντιπρόσωπο γεγονότων** - Ακροατής ενός γεγονότος για όλα τα κουμπιά ελέγχου
- **Τεμπέλης Αρχικοποίησης** - Το Pan/zoom αρχικοποιείται μόνο όταν απαιτείται
- **Καθαρισμός του Πρωτοδικείου** - Η σωστή διαχείριση μνήμης
- **Minimal Re-reders** - Διαγράμματα μόνο re-render για την αλλαγή θέματος
- **Αποτελεσματικές λειτουργίες DOM** - Χρήσεις `requestAnimationFrame` για ομαλές κινούμενες εικόνες

# Υποστήριξη προγράμματος περιήγησης

Δοκιμασμένος και εργάζονται σε:

- Chrome/Edge (τελευταίο)
- Firefox (τελευταία)
- Σαφάρι (τελευταίο)
- Κινητά προγράμματα περιήγησης (iOS Safari, Chrome Mobile)

# Μελλοντικές Βελτιώσεις

Ιδέες για μελλοντικές εκδόσεις:

- [ ] Ρύθμιση εικονιδίων κουμπί ελέγχου (υποστηρίξτε για Font Awesome, Υλικά εικονίδια)
- [ ] Συντόμευση πλήκτρων (π.χ., Ctrl+Plus για μεγέθυνση)
- [ ] χειρονομίες αφής στο κινητό (τσιμπήστε στο ζουμ)
- [ ] Αντιγράψτε το κουμπί πηγαίου κώδικα διαγράμματος
- [ ] Λειτουργία URL διαγράμματοςName
- [ ] Υποσημειώσεις διαγράμματος
- [ ] Πολλαπλές μορφές εξαγωγών (PDF, JPEG)

# Συμπέρασμα

Η συσκευασία των Βελτιώσεων της Γοργόνας ως μονάδα npm ήταν μια μεγάλη εμπειρία μάθησης. Το πακέτο είναι τώρα:

- Τύπος-ασφαλής με TypeScript
- Καλά τεκμηριωμένα
- Εύκολο στη χρήση
- Έτοιμη για την παραγωγή
- Αγνωστικό πλαίσιο
- Πλήρως δοκιμασμένη

Αν χρησιμοποιείτε Mermaid.js στα projects σας, να το δοκιμάσετε! Τα διαδραστικά pan/zoom και τα χαρακτηριστικά εξαγωγής κάνουν τη συνεργασία με σύνθετα διαγράμματα πολύ καλύτερα.

# Πόροι

- **GitHub Repository**: [ως επί το πλείστον διαυγής ιστός/ ως επί το πλείστον διαυγής-χρήστης](https://github.com/scottgal/mostlylucidweb/tree/main/mostlylucid-mermaid)
- **npm πακέτο**: [@mostly διαυγής/mermaid-enhancements](https://www.npmjs.com/package/@mostlylucid/mermaid-enhancements) (Έρχεται σύντομα)
- **DemoCity name (optional, probably does not need a translation)**: [Ζωντανό DemoCity name (optional, probably does not need a translation)](https://mostlylucid.net/mermaid-demo) (Έρχεται σύντομα)