# Mermaid Administrator & Developer Guide

## 1. Architecture Overview

Mermaid is a JavaScript-based diagramming and charting library that renders Markdown-inspired text definitions into SVG diagrams in the browser. It is distributed as an npm package (`mermaid` v11.14.0), operates entirely client-side, and exposes no server-side components, CLI commands, or API endpoints.

### 1.1 Monorepo Structure

The codebase is organized as a **pnpm monorepo** (root name `mermaid-monorepo` v10.2.4) containing eight packages:

| Package | npm Name | Version | Purpose |
|---------|----------|---------|---------|
| `packages/mermaid` | `mermaid` | 11.14.0 | Core library: parsing, rendering, config, themes |
| `packages/parser` | `@mermaid-js/parser` | 1.1.0 | Langium-based grammar parser for newer diagram types |
| `packages/mermaid-layout-elk` | `@mermaid-js/layout-elk` | 0.2.1 | ELK layout engine integration (elkjs) |
| `packages/mermaid-layout-tidy-tree` | `@mermaid-js/layout-tidy-tree` | 0.2.1 | Bidirectional tidy-tree layout for mindmaps |
| `packages/mermaid-zenuml` | `@mermaid-js/mermaid-zenuml` | 0.2.2 | ZenUML sequence diagram integration |
| `packages/mermaid-example-diagram` | `@mermaid-js/mermaid-example-diagram` | 9.3.0 | Reference implementation for external diagram plugins |
| `packages/examples` | `@mermaid-js/examples` | 1.2.0 | Diagram definition samples for all 27 types |
| `packages/tiny` | `@mermaid-js/tiny` | 11.14.0 | Minimal/tree-shaken build variant |

### 1.2 Core Rendering Pipeline

Every diagram flows through the same pipeline:

```
Text Input
  → detectType()           # regex-based diagram type detection
  → getDiagramLoader()     # lazy-load diagram module if not registered
  → Parser                 # jison (legacy) or langium (modern)
  → Diagram DB             # in-memory data store populated by parser
  → Renderer               # SVG generation using d3 + layout algorithm
  → SVG Output             # sanitized via DOMPurify
```

The pipeline is orchestrated by `Diagram.fromText()` (static factory in `packages/mermaid/src/Diagram.ts`), which detects the diagram type, loads the appropriate parser/db/renderer triplet, runs the parser, and returns a `Diagram` instance ready for rendering.

### 1.3 Key Source Modules

| Module | Path | Responsibility |
|--------|------|----------------|
| `mermaid.ts` | `packages/mermaid/src/mermaid.ts` | Public API: `initialize`, `run`, `parse`, `render`, `registerExternalDiagrams` |
| `mermaidAPI.ts` | `packages/mermaid/src/mermaidAPI.ts` | Internal API: `createCssStyles`, `putIntoIFrame`, `render`, `parse` |
| `Diagram.ts` | `packages/mermaid/src/Diagram.ts` | `Diagram` class with `fromText` static factory |
| `config.ts` | `packages/mermaid/src/config.ts` | Three-tier config management: default, site, current |
| `config.type.ts` | `packages/mermaid/src/config.type.ts` | TypeScript interfaces for all configuration (auto-generated from JSON Schema) |
| `defaultConfig.ts` | `packages/mermaid/src/defaultConfig.ts` | Default values loaded from `config.schema.yaml` |
| `detectType.ts` | `packages/mermaid/src/diagram-api/detectType.ts` | Regex-based diagram type detection and lazy-loader registry |
| `diagramAPI.ts` | `packages/mermaid/src/diagram-api/diagramAPI.ts` | Diagram registration and retrieval |
| `diagram-orchestration.ts` | `packages/mermaid/src/diagram-api/diagram-orchestration.ts` | Registers all built-in diagram types |
| `logger.ts` | `packages/mermaid/src/logger.ts` | Configurable log levels (trace through fatal) |
| `utils.ts` | `packages/mermaid/src/utils.ts` | Entity encoding, init detection, ID generation |
| `internals.ts` | `packages/mermaid/src/internals.ts` | Deprecated internal helpers for external diagram plugins |
| `errors.ts` | `packages/mermaid/src/errors.ts` | `UnknownDiagramError` class |

### 1.4 Diagram Type Architecture

Each of the 27 built-in diagram types follows a consistent module pattern within `packages/mermaid/src/diagrams/{type}/`:

| File | Role |
|------|------|
| `*Detector.ts` | Regex function to detect this diagram type from raw text |
| `*Diagram.ts` | Diagram definition export: `{ db, parser, renderer, styles }` |
| `*Db.ts` | Data store: parse results, getters/setters, `clear()` |
| `*Renderer.ts` | SVG rendering logic using d3 |
| Parser (`.jison` or `.langium`) | Grammar definition |
| `styles.ts`/`styles.js` | CSS generation functions for theming |

> [!NOTE]
> Older diagram types (flowchart, sequence, gantt, class, state, ER, pie, C4, requirement, user-journey, git graph) use **jison** parsers (`.jison` grammar files compiled to JavaScript). Newer types (packet, info, pie v2, gitGraph v2, radar, architecture, wardley, treemap, treeView, eventmodeling, venn) use **Langium** grammars (`.langium` files) via the `@mermaid-js/parser` package.

### 1.5 Supported Diagram Types (27)

flowchart, sequence, class, state, er, gantt, pie, mindmap, timeline, quadrant-chart, xychart, requirement, c4, sankey, packet, block, git graph, user-journey, architecture, ishikawa, kanban, radar, venn, treemap, tree-view, eventmodeling, wardley

---

## 2. System Requirements

### 2.1 Development Environment

| Requirement | Version |
|-------------|---------|
| **Node.js** | Version specified in `.node-version` file at repo root |
| **pnpm** | 10.30.3 (enforced via `packageManager` field with integrity hash) |
| **TypeScript** | ~5.8.0 |
| **OS** | Any platform supporting Node.js (Linux, macOS, Windows) |

### 2.2 Runtime Dependencies (Core Package)

| Dependency | Version | Purpose |
|------------|---------|---------|
| `d3` | ^7.9.0 | SVG rendering and DOM manipulation |
| `dagre-d3-es` | 7.0.14 | Default graph layout (dagre algorithm) |
| `dompurify` | ^3.3.1 | HTML/SVG sanitization (XSS prevention) |
| `cytoscape` | ^3.33.1 | Alternative layout engine |
| `cytoscape-cose-bilkent` | ^4.1.0 | CoSE-Bilkent layout for cytoscape |
| `cytoscape-fcose` | ^2.2.0 | fCoSE layout for cytoscape |
| `katex` | ^0.16.25 | LaTeX math rendering |
| `marked` | ^16.3.0 | Markdown parsing within diagrams |
| `roughjs` | ^4.6.6 | Hand-drawn style rendering |
| `dayjs` | ^1.11.19 | Date handling (gantt diagrams) |
| `@braintree/sanitize-url` | latest | URL sanitization |
| `khroma` | latest | Color manipulation for themes |
| `stylis` | latest | CSS processing |
| `uuid` | latest | ID generation |
| `ts-dedent` | latest | Template literal dedenting |

### 2.3 Runtime Dependencies (Satellite Packages)

| Package | Key Dependency | Version |
|---------|---------------|---------|
| `@mermaid-js/parser` | `langium` | ^4.0.0 |
| `@mermaid-js/layout-elk` | `elkjs` | ^0.9.3 |

### 2.4 Browser Requirements

Mermaid targets modern browsers with ES module support. The esbuild configuration targets the `modules` build output. No polyfills are included; consumers must provide them if targeting older browsers.

> [!IMPORTANT]
> Mermaid is a **browser-side library only**. It requires a DOM environment. Server-side rendering requires a DOM shim (e.g., jsdom) or a headless browser. The library auto-registers a `window.addEventListener('load', ...)` listener when `document` is defined.

---

## 3. Configuration Reference

Mermaid uses a **three-tier configuration architecture**:

1. **`defaultConfig`** -- Immutable baseline loaded from `config.schema.yaml` via a custom Vite plugin, frozen with `Object.freeze()`.
2. **`siteConfig`** -- Set via `mermaid.initialize(config)`. Merges onto `defaultConfig`. Persists across `reset()` calls. This is where site-wide defaults belong.
3. **`currentConfig`** -- Active config during rendering. Starts as a copy of `siteConfig`, then has directives applied on top. Reset between diagrams via `reset()`.

```
defaultConfig (frozen)
    └──► siteConfig (via initialize)
            └──► currentConfig (via directives)
```

### 3.1 Config API Functions

| Function | Description |
|----------|-------------|
| `setSiteConfig(conf)` | Sets siteConfig by merging `conf` onto defaultConfig. Recalculates theme variables. |
| `getSiteConfig()` | Returns a deep copy of siteConfig. |
| `setConfig(conf)` | Merges `conf` into currentConfig (sanitized against secure keys). |
| `getConfig()` | Returns a deep copy of currentConfig. |
| `reset(config?)` | Resets currentConfig to siteConfig (or provided config). Clears all directives. |
| `addDirective(directive)` | Pushes a directive, sanitizes it, and recalculates currentConfig. |
| `updateCurrentConfig(siteCfg, directives)` | Recalculates currentConfig from site config + accumulated directives. |
| `saveConfigFromInitialize(conf)` | Stores the config passed to `initialize()` for later reference. |
| `getUserDefinedConfig()` | Returns merged user config (initialize config + all directives). |
| `getEffectiveHtmlLabels(config)` | Resolves the effective `htmlLabels` value considering deprecated `flowchart.htmlLabels`. |
| `evaluate(val)` | Converts string/boolean to boolean (treats `'false'`, `'null'`, `'0'` as false). |

> [!WARNING]
> The `secure` array in config prevents certain keys from being overridden via directives. By default, `securityLevel`, `maxTextSize`, and other sensitive keys are in this array. Attempting to set a secure key via a `%%{init: {...}}%%` directive will silently fail with a debug log message.

### 3.2 Global Configuration (`MermaidConfig`)

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `theme` | `'default' \| 'base' \| 'dark' \| 'forest' \| 'neutral' \| 'neo' \| 'neo-dark' \| 'redux' \| 'redux-dark' \| 'redux-color' \| 'redux-dark-color' \| 'null'` | `'default'` | CSS theme for diagram rendering |
| `themeVariables` | `any` | (computed) | Theme variable overrides; processed by theme's `getThemeVariables()` |
| `themeCSS` | `string` | `undefined` | Raw CSS to override theme styles |
| `look` | `'classic' \| 'handDrawn' \| 'neo'` | `'classic'` | Visual style for diagram rendering |
| `handDrawnSeed` | `number` | `0` | Seed for hand-drawn style (0 = random). Set non-zero for deterministic output. |
| `layout` | `string` | `undefined` | Layout algorithm override (`'dagre'`, `'elk'`, etc.) |
| `maxTextSize` | `number` | 50000 | Maximum character length of input text |
| `maxEdges` | `number` | 500 | Maximum number of edges in a graph |
| `darkMode` | `boolean` | `false` | Enable dark mode theme adjustments |
| `htmlLabels` | `boolean` | `true` | Use HTML for rendering labels (enables richer formatting) |
| `fontFamily` | `string` | `'"trebuchet ms", verdana, arial, sans-serif'` | CSS font-family for diagrams |
| `altFontFamily` | `string` | `undefined` | Alternative font family |
| `fontSize` | `number` | `16` | Base font size in pixels |
| `logLevel` | `'trace' \| 0 \| 'debug' \| 1 \| 'info' \| 2 \| 'warn' \| 3 \| 'error' \| 4 \| 'fatal' \| 5` | `'fatal'` | Console log verbosity |
| `securityLevel` | `'strict' \| 'loose' \| 'antiscript' \| 'sandbox'` | `'strict'` | Security policy for rendering |
| `startOnLoad` | `boolean` | `true` | Auto-render diagrams when page loads |
| `arrowMarkerAbsolute` | `boolean` | `false` | Use absolute paths for arrow markers (needed with `<base>` tag) |
| `secure` | `string[]` | `['secure', 'securityLevel', 'startOnLoad', 'maxTextSize', 'maxEdges']` | Keys that cannot be overridden by directives |
| `legacyMathML` | `boolean` | `false` | Fall back to KaTeX rendering when MathML unsupported |
| `forceLegacyMathML` | `boolean` | `false` | Always use KaTeX (ignores `legacyMathML`) |
| `deterministicIds` | `boolean` | `false` | Generate deterministic SVG element IDs (for source control stability) |
| `deterministicIDSeed` | `string` | `undefined` | Seed string for deterministic IDs |
| `dompurifyConfig` | `DOMPurifyConfiguration` | `undefined` | Custom DOMPurify options |
| `wrap` | `boolean` | `undefined` | Enable text wrapping globally |
| `markdownAutoWrap` | `boolean` | `true` | Auto-wrap markdown text |
| `suppressErrorRendering` | `boolean` | `false` | Suppress "Syntax error" diagram insertion into DOM |

### 3.3 ELK Layout Configuration (`elk`)

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `elk.mergeEdges` | `boolean` | `false` | Allow edges to share paths |
| `elk.nodePlacementStrategy` | `'SIMPLE' \| 'NETWORK_SIMPLEX' \| 'LINEAR_SEGMENTS' \| 'BRANDES_KOEPF'` | `'BRANDES_KOEPF'` | Node placement algorithm |
| `elk.cycleBreakingStrategy` | `'GREEDY' \| 'DEPTH_FIRST' \| 'INTERACTIVE' \| 'MODEL_ORDER' \| 'GREEDY_MODEL_ORDER'` | (default) | Strategy for breaking graph cycles |
| `elk.forceNodeModelOrder` | `boolean` | `false` | Preserve model-order node positions during crossing minimization |
| `elk.considerModelOrder` | `'NONE' \| 'NODES_AND_EDGES' \| 'PREFER_EDGES' \| 'PREFER_NODES'` | `'NODES_AND_EDGES'` | How to preserve model ordering |

### 3.4 Flowchart Configuration (`flowchart`: `FlowchartDiagramConfig`)

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `titleTopMargin` | `number` | | Margin above diagram title |
| `subGraphTitleMargin` | `{top?: number, bottom?: number}` | | Margins around subgraph titles |
| `arrowMarkerAbsolute` | `boolean` | `false` | Absolute arrow marker paths |
| `diagramPadding` | `number` | `8` | Padding around entire diagram (px) |
| `htmlLabels` | `boolean \| null` | `true` | **Deprecated.** Use global `htmlLabels` instead. |
| `nodeSpacing` | `number` | `50` | Spacing between nodes on same level |
| `rankSpacing` | `number` | `50` | Spacing between nodes on different levels |
| `curve` | `'basis' \| 'bumpX' \| 'bumpY' \| 'cardinal' \| 'catmullRom' \| 'linear' \| 'monotoneX' \| 'monotoneY' \| 'natural' \| 'step' \| 'stepAfter' \| 'stepBefore' \| 'rounded'` | `'basis'` | Edge curve interpolation |
| `padding` | `number` | | Padding between labels and shapes |
| `defaultRenderer` | `'dagre-d3' \| 'dagre-wrapper' \| 'elk'` | `'dagre-wrapper'` | Rendering engine |
| `wrappingWidth` | `number` | `200` | Max text width before wrapping |
| `inheritDir` | `boolean` | `false` | Subgraphs inherit parent graph direction |
| `useMaxWidth` | `boolean` | `true` | Scale to container width |

### 3.5 Sequence Diagram Configuration (`sequence`: `SequenceDiagramConfig`)

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `arrowMarkerAbsolute` | `boolean` | `false` | Absolute arrow marker paths |
| `hideUnusedParticipants` | `boolean` | `false` | Hide participants not involved in messages |
| `activationWidth` | `number` | `10` | Width of activation rectangles |
| `diagramMarginX` | `number` | `50` | Left/right margin |
| `diagramMarginY` | `number` | `10` | Top/bottom margin |
| `actorMargin` | `number` | `50` | Spacing between actors |
| `width` | `number` | `150` | Actor box width |
| `height` | `number` | `65` | Actor box height |
| `boxMargin` | `number` | `10` | Margin around loop/alt/opt boxes |
| `boxTextMargin` | `number` | `5` | Text margin inside boxes |
| `noteMargin` | `number` | `10` | Margin around notes |
| `messageMargin` | `number` | `35` | Space between messages |
| `messageAlign` | `'left' \| 'center' \| 'right'` | `'center'` | Message text alignment |
| `mirrorActors` | `boolean` | `true` | Mirror actors below diagram |
| `forceMenus` | `boolean` | `false` | Always show actor popup menus |
| `bottomMarginAdj` | `number` | `1` | Bottom edge extension |
| `rightAngles` | `boolean` | `false` | Self-referencing arrows as right angles |
| `showSequenceNumbers` | `boolean` | `false` | Display sequence numbers |
| `actorFontSize` | `string \| number` | `14` | Actor label font size |
| `actorFontFamily` | `string` | `'"Open Sans", sans-serif'` | Actor label font |
| `actorFontWeight` | `string \| number` | `400` | Actor label font weight |
| `noteFontSize` | `string \| number` | `14` | Note font size |
| `noteFontFamily` | `string` | `'"trebuchet ms", verdana, arial, sans-serif'` | Note font family |
| `noteFontWeight` | `string \| number` | `400` | Note font weight |
| `noteAlign` | `'left' \| 'center' \| 'right'` | `'center'` | Note text alignment |
| `messageFontSize` | `string \| number` | `16` | Message font size |
| `messageFontFamily` | `string` | `'"trebuchet ms", verdana, arial, sans-serif'` | Message font family |
| `messageFontWeight` | `string \| number` | `400` | Message font weight |
| `wrap` | `boolean` | `false` | Enable auto-wrap |
| `wrapPadding` | `number` | `10` | Padding for wrapped text |
| `labelBoxWidth` | `number` | `50` | Loop/alt/opt label box width |
| `labelBoxHeight` | `number` | `20` | Loop/alt/opt label box height |

### 3.6 Gantt Diagram Configuration (`gantt`: `GanttDiagramConfig`)

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `titleTopMargin` | `number` | `25` | Top margin for title |
| `barHeight` | `number` | `20` | Height of task bars |
| `barGap` | `number` | `4` | Gap between bars |
| `topPadding` | `number` | `50` | Padding above chart |
| `rightPadding` | `number` | `75` | Right padding for section labels |
| `leftPadding` | `number` | `75` | Left padding for section labels |
| `gridLineStartPadding` | `number` | `35` | Grid line vertical start |
| `fontSize` | `number` | `11` | General font size |
| `sectionFontSize` | `string \| number` | `11` | Section label font size |
| `numberSectionStyles` | `number` | `4` | Number of alternating section styles |
| `axisFormat` | `string` | `'%Y-%m-%d'` | Date format for axis (d3 time format) |
| `tickInterval` | `string` | `undefined` | Axis tick interval (e.g., `'1day'`, `'1week'`) |
| `topAxis` | `boolean` | `false` | Show date labels on top |
| `displayMode` | `'' \| 'compact'` | `''` | Compact mode collapses vertical space |
| `weekday` | `'monday' \| ... \| 'sunday'` | `'sunday'` | Week start day |

### 3.7 Class Diagram Configuration (`class`: `ClassDiagramConfig`)

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `titleTopMargin` | `number` | `25` | Top margin for title |
| `arrowMarkerAbsolute` | `boolean` | `false` | Absolute arrow markers |
| `dividerMargin` | `number` | `10` | Margin around class dividers |
| `padding` | `number` | `5` | Padding inside class boxes |
| `textHeight` | `number` | `10` | Text line height |
| `defaultRenderer` | `'dagre-d3' \| 'dagre-wrapper' \| 'elk'` | `'dagre-wrapper'` | Rendering engine |
| `nodeSpacing` | `number` | `50` | Spacing between nodes |
| `rankSpacing` | `number` | `50` | Spacing between ranks |
| `diagramPadding` | `number` | `8` | Diagram padding |
| `htmlLabels` | `boolean` | `true` | HTML label rendering |
| `hideEmptyMembersBox` | `boolean` | `false` | Hide empty attribute/method sections |

### 3.8 State Diagram Configuration (`state`: `StateDiagramConfig`)

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `titleTopMargin` | `number` | `25` | Top margin for title |
| `dividerMargin` | `number` | `10` | Divider margin |
| `sizeUnit` | `number` | `5` | Base size unit |
| `padding` | `number` | `8` | Padding |
| `textHeight` | `number` | `10` | Text height |
| `titleShift` | `number` | `-15` | Title position shift |
| `noteMargin` | `number` | `10` | Note margin |
| `nodeSpacing` | `number` | `50` | Node spacing |
| `rankSpacing` | `number` | `50` | Rank spacing |
| `forkWidth` | `number` | `70` | Fork/join bar width |
| `forkHeight` | `number` | `7` | Fork/join bar height |
| `miniPadding` | `number` | `2` | Minimum padding |
| `fontSizeFactor` | `number` | `5.02` | Font factor for edge label width estimation |
| `fontSize` | `number` | `24` | Font size |
| `labelHeight` | `number` | `16` | Label height |
| `edgeLengthFactor` | `string` | `'20'` | Edge length factor |
| `compositTitleSize` | `number` | `35` | Composite state title size |
| `radius` | `number` | `5` | Corner radius |
| `defaultRenderer` | `'dagre-d3' \| 'dagre-wrapper' \| 'elk'` | `'dagre-wrapper'` | Rendering engine |

### 3.9 ER Diagram Configuration (`er`: `ErDiagramConfig`)

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `titleTopMargin` | `number` | `25` | Top margin for title |
| `diagramPadding` | `number` | `20` | Diagram padding |
| `layoutDirection` | `'TB' \| 'BT' \| 'LR' \| 'RL'` | `'TB'` | Layout direction |
| `minEntityWidth` | `number` | `100` | Minimum entity box width |
| `minEntityHeight` | `number` | `75` | Minimum entity box height |
| `entityPadding` | `number` | `15` | Entity internal padding |
| `nodeSpacing` | `number` | `80` | Node spacing |
| `rankSpacing` | `number` | `80` | Rank spacing |
| `stroke` | `string` | `'gray'` | Stroke color |
| `fill` | `string` | `'honeydew'` | Fill color |
| `fontSize` | `number` | `12` | Font size |

### 3.10 Pie Diagram Configuration (`pie`: `PieDiagramConfig`)

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `textPosition` | `number` | `0.75` | Label position (0=center, 1=edge) |
| `useMaxWidth` | `boolean` | `true` | Scale to container |

### 3.11 Quadrant Chart Configuration (`quadrantChart`: `QuadrantChartConfig`)

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `chartWidth` | `number` | `500` | Chart width |
| `chartHeight` | `number` | `500` | Chart height |
| `titleFontSize` | `number` | `20` | Title font size |
| `titlePadding` | `number` | `10` | Title padding |
| `quadrantPadding` | `number` | `5` | Quadrant square padding |
| `xAxisLabelPadding` | `number` | `5` | X-axis label padding |
| `yAxisLabelPadding` | `number` | `5` | Y-axis label padding |
| `xAxisLabelFontSize` | `number` | `16` | X-axis label font size |
| `yAxisLabelFontSize` | `number` | `16` | Y-axis label font size |
| `quadrantLabelFontSize` | `number` | `16` | Quadrant title font size |
| `quadrantTextTopPadding` | `number` | `5` | Quadrant title top padding |
| `pointTextPadding` | `number` | `5` | Point label padding |
| `pointLabelFontSize` | `number` | `12` | Point label font size |
| `pointRadius` | `number` | `5` | Point radius |
| `xAxisPosition` | `'top' \| 'bottom'` | `'top'` | X-axis label position |
| `yAxisPosition` | `'left' \| 'right'` | `'left'` | Y-axis label position |
| `quadrantInternalBorderStrokeWidth` | `number` | `1` | Internal border width |
| `quadrantExternalBorderStrokeWidth` | `number` | `2` | External border width |

### 3.12 XY Chart Configuration (`xyChart`: `XYChartConfig`)

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `width` | `number` | `700` | Chart width |
| `height` | `number` | `500` | Chart height |
| `titleFontSize` | `number` | `20` | Title font size |
| `titlePadding` | `number` | `10` | Title padding |
| `showDataLabel` | `boolean` | `false` | Show value labels on bars |
| `showDataLabelOutsideBar` | `boolean` | `false` | Place labels outside bars |
| `showTitle` | `boolean` | `true` | Display chart title |
| `chartOrientation` | `'vertical' \| 'horizontal'` | `'vertical'` | Plot orientation |
| `plotReservedSpacePercent` | `number` | `50` | Minimum % space for plot area |

**XY Chart Axis (`xAxis`/`yAxis`: `XYChartAxisConfig`)**:

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `showLabel` | `boolean` | `true` | Show axis tick labels |
| `labelFontSize` | `number` | `14` | Tick label font size |
| `labelPadding` | `number` | `5` | Tick label padding |
| `showTitle` | `boolean` | `true` | Show axis title |
| `titleFontSize` | `number` | `16` | Axis title font size |
| `titlePadding` | `number` | `5` | Axis title padding |
| `showTick` | `boolean` | `true` | Show tick marks |
| `tickLength` | `number` | `5` | Tick mark length |
| `tickWidth` | `number` | `2` | Tick mark width |
| `showAxisLine` | `boolean` | `true` | Show axis line |
| `axisLineWidth` | `number` | `2` | Axis line width |

### 3.13 Journey Diagram Configuration (`journey`: `JourneyDiagramConfig`)

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `diagramMarginX` | `number` | `50` | Horizontal margin |
| `diagramMarginY` | `number` | `10` | Vertical margin |
| `leftMargin` | `number` | `150` | Left margin for actor names |
| `maxLabelWidth` | `number` | `200` | Maximum actor label width |
| `width` | `number` | `150` | Actor box width |
| `height` | `number` | `50` | Actor box height |
| `boxMargin` | `number` | `10` | Box margin |
| `boxTextMargin` | `number` | `5` | Box text margin |
| `noteMargin` | `number` | `10` | Note margin |
| `messageMargin` | `number` | `35` | Message spacing |
| `messageAlign` | `'left' \| 'center' \| 'right'` | `'center'` | Message alignment |
| `bottomMarginAdj` | `number` | `1` | Bottom edge adjustment |
| `rightAngles` | `boolean` | `false` | Right-angle self-arrows |
| `taskFontSize` | `string \| number` | `14` | Task label font size |
| `taskFontFamily` | `string` | `'"Open Sans", sans-serif'` | Task font |
| `taskMargin` | `number` | `50` | Task margin |
| `activationWidth` | `number` | `10` | Activation box width |
| `textPlacement` | `string` | `'fo'` | Text rendering method |
| `actorColours` | `string[]` | | Actor color palette |
| `sectionFills` | `string[]` | | Section fill colors |
| `sectionColours` | `string[]` | | Section border colors |
| `titleColor` | `string` | `''` | Title text color |
| `titleFontFamily` | `string` | `''` | Title font family |
| `titleFontSize` | `string` | `''` | Title font size |

### 3.14 Timeline Diagram Configuration (`timeline`: `TimelineDiagramConfig`)

Shares the same structure as JourneyDiagramConfig with these additions:

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `padding` | `number` | | General padding |
| `disableMulticolor` | `boolean` | `false` | Disable multicolor sections |

### 3.15 Git Graph Configuration (`gitGraph`: `GitGraphDiagramConfig`)

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `titleTopMargin` | `number` | `25` | Top margin for title |
| `diagramPadding` | `number` | `8` | Diagram padding |
| `nodeLabel` | `{width, height, x, y}` | | Node label dimensions |
| `mainBranchName` | `string` | `'main'` | Default main branch name |
| `mainBranchOrder` | `number` | `0` | Main branch display order |
| `showCommitLabel` | `boolean` | `true` | Show commit labels |
| `showBranches` | `boolean` | `true` | Show branch lines |
| `rotateCommitLabel` | `boolean` | `true` | Rotate commit labels |
| `parallelCommits` | `boolean` | `false` | Display parallel commits |
| `arrowMarkerAbsolute` | `boolean` | `false` | Absolute arrow paths |

### 3.16 C4 Diagram Configuration (`c4`: `C4DiagramConfig`)

The C4 diagram configuration contains extensive font and color settings for every C4 element type (Person, System, Container, Component -- each with regular and external variants, plus DB and Queue subtypes). Key structural settings:

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `diagramMarginX` | `number` | `50` | Horizontal margin |
| `diagramMarginY` | `number` | `10` | Vertical margin |
| `c4ShapeMargin` | `number` | `50` | Margin between shapes |
| `c4ShapePadding` | `number` | `20` | Padding inside shapes |
| `width` | `number` | `216` | Person box width |
| `height` | `number` | `60` | Person box height |
| `boxMargin` | `number` | `10` | Box margin |
| `c4ShapeInRow` | `number` | `4` | Shapes per row |
| `c4BoundaryInRow` | `number` | `2` | Boundaries per row |
| `wrap` | `boolean` | `true` | Enable text wrapping |
| `wrapPadding` | `number` | `10` | Wrap padding |

Each element type has `*FontSize`, `*FontFamily`, `*FontWeight`, `*_bg_color`, `*_border_color`, and `*Font` (calculator function) settings. The naming pattern follows: `{element}FontSize`, `external_{element}FontSize`, etc.

### 3.17 Sankey Diagram Configuration (`sankey`: `SankeyDiagramConfig`)

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `width` | `number` | `600` | Diagram width |
| `height` | `number` | `400` | Diagram height |
| `linkColor` | `SankeyLinkColor \| string` | `'gradient'` | Link coloring: `'source'`, `'target'`, `'gradient'`, or CSS color |
| `nodeAlignment` | `'left' \| 'right' \| 'center' \| 'justify'` | `'justify'` | Node alignment (d3-sankey) |
| `showValues` | `boolean` | `true` | Show values alongside titles |
| `prefix` | `string` | `''` | Value prefix (e.g., `'$'`) |
| `suffix` | `string` | `''` | Value suffix (e.g., `'k'`) |
| `nodeWidth` | `number` | `15` | Node width |
| `nodePadding` | `number` | `10` | Vertical padding between nodes |
| `labelStyle` | `'legacy' \| 'outlined'` | `'legacy'` | Label rendering style |
| `nodeColors` | `Record<string, string>` | `{}` | Custom node color mapping |

### 3.18 Packet Diagram Configuration (`packet`: `PacketDiagramConfig`)

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `rowHeight` | `number` | `32` | Height per row |
| `bitWidth` | `number` | `20` | Width per bit |
| `bitsPerRow` | `number` | `32` | Bits displayed per row |
| `showBits` | `boolean` | `true` | Show bit numbers |
| `paddingX` | `number` | `5` | Horizontal padding |
| `paddingY` | `number` | `5` | Vertical padding |

### 3.19 Other Diagram Configurations

| Diagram | Config Key | Key Settings |
|---------|-----------|--------------|
| **Architecture** | `architecture` | `padding`, `iconSize`, `fontSize`, `randomize` (randomize initial node positions) |
| **Mindmap** | `mindmap` | `padding`, `maxNodeWidth`, `layoutAlgorithm` |
| **Ishikawa** | `ishikawa` | `diagramPadding`, `useMaxWidth` |
| **Kanban** | `kanban` | `padding`, `sectionWidth`, `ticketBaseUrl` |
| **Block** | `block` | `padding` |
| **Event Modeling** | `eventmodeling` | `padding`, `rowHeight` |
| **Tree View** | `treeView` | `rowIndent`, `paddingX`, `paddingY`, `lineThickness` |
| **Radar** | `radar` | `width`, `height`, `marginTop/Right/Bottom/Left`, `axisScaleFactor`, `axisLabelFactor`, `curveTension` |
| **Venn** | `venn` | `width`, `height`, `padding`, `useDebugLayout` |
| **Wardley** | `wardley-beta` | `width`, `height`, `padding`, `nodeRadius`, `nodeLabelOffset`, `axisFontSize`, `labelFontSize`, `showGrid` |
| **Requirement** | `requirement` | `rect_fill`, `text_color`, `rect_border_size/color`, `rect_min_width/height`, `fontSize`, `rect_padding`, `line_height` |

### 3.20 Base Diagram Config (`BaseDiagramConfig`)

All per-diagram configs extend `BaseDiagramConfig`:

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `useWidth` | `number` | `undefined` | Fixed width override |
| `useMaxWidth` | `boolean` | `true` | Scale to container width (responsive) |

---

## 4. Deployment & Scaling

### 4.1 Installation Methods

**npm/pnpm/yarn:**

```bash
npm install mermaid
# or
pnpm add mermaid
# or
yarn add mermaid
```

**CDN (ESM):**

```html
<script type="module">
  import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
  mermaid.initialize({ startOnLoad: true });
</script>
```

### 4.2 Build Outputs

The esbuild pipeline (`.esbuild/build.ts`) produces multiple distribution formats in `packages/mermaid/dist/`:

| File | Format | Use Case |
|------|--------|----------|
| `mermaid.esm.min.mjs` | ES Module (minified) | Modern bundlers, CDN |
| `mermaid.esm.mjs` | ES Module | Development |
| `mermaid.min.js` | IIFE (minified) | Script tag inclusion |
| `mermaid.js` | IIFE | Development |
| `mermaid.d.ts` | TypeScript declarations | IDE support |

### 4.3 Integration Patterns

**Auto-rendering (simplest):**

```html
<div class="mermaid">
  graph TD;
    A-->B;
</div>
<script type="module">
  import mermaid from '/path/to/mermaid.esm.min.mjs';
  mermaid.initialize({ startOnLoad: true });
</script>
```

**Programmatic rendering:**

```javascript
import mermaid from 'mermaid';

mermaid.initialize({ startOnLoad: false, theme: 'dark' });

const { svg, bindFunctions } = await mermaid.render('diagram-id', 'graph TD; A-->B');
document.getElementById('output').innerHTML = svg;
if (bindFunctions) {
  bindFunctions(document.getElementById('output'));
}
```

**Targeted node rendering:**

```javascript
await mermaid.run({
  nodes: [document.getElementById('my-diagram')],
  suppressErrors: true,
  postRenderCallback: (id) => console.log(`Rendered: ${id}`),
});
```

> [!TIP]
> When calling `mermaid.render()` or `mermaid.parse()` concurrently, Mermaid uses an internal execution queue to serialize calls. Each call is enqueued and processed sequentially, preventing race conditions in the shared diagram registry and config state.

### 4.4 Registering External Diagrams

Third-party diagram types integrate through the `ExternalDiagramDefinition` interface:

```typescript
await mermaid.registerExternalDiagrams([
  {
    id: 'custom-diagram',
    detector: (text) => text.startsWith('custom'),
    loader: () => import('./custom-diagram.js'),
  },
], { lazyLoad: true });  // lazyLoad: false loads immediately
```

The `mermaid-example-diagram` package serves as the reference implementation for building external diagram plugins.

### 4.5 Registering Layout Algorithms

Custom layout engines register through `registerLayoutLoaders`:

```typescript
import { registerLayoutLoaders } from 'mermaid';

registerLayoutLoaders([
  {
    name: 'custom-layout',
    loader: () => import('./custom-layout.js'),
  },
]);
```

### 4.6 Docker-Based Development

The repository includes Docker support for the documentation site (`packages/mermaid/src/docs/`). The docs dev server can run inside Docker using `pnpm dev:docker` which binds to all interfaces (host `0.0.0.0`) on port 3333.

---

## 5. Operations

### 5.1 Build Commands

| Command | Description |
|---------|-------------|
| `pnpm build` | Full build: esbuild + TypeScript declarations |
| `pnpm build:esbuild` | Run esbuild only (all packages) |
| `pnpm build:mermaid` | Build only the mermaid package |
| `pnpm build:viz` | Build with bundle visualization |
| `pnpm build:types` | Generate TypeScript declaration files |
| `pnpm build:types:watch` | Watch mode for type declarations |
| `pnpm dev` | Start esbuild dev server |
| `pnpm dev:vite` | Start Vite dev server (for e2e) |

### 5.2 Testing Commands

| Command | Description |
|---------|-------------|
| `pnpm test` | Lint + vitest run |
| `pnpm ci` | vitest run (CI mode) |
| `pnpm test:watch` | vitest watch mode |
| `pnpm test:coverage` | vitest with V8 coverage |
| `pnpm e2e` | Cypress end-to-end tests (starts dev server) |
| `pnpm cypress:open` | Interactive Cypress runner |
| `pnpm coverage` | Full coverage: unit + e2e + merge |

### 5.3 Lint Commands

| Command | Description |
|---------|-------------|
| `pnpm lint` | eslint + jison lint + prettier check |
| `pnpm lint:fix` | Auto-fix lint issues |
| `pnpm lint:jison` | Lint jison grammar files only |

### 5.4 Release Commands

| Command | Description |
|---------|-------------|
| `pnpm changeset:version` | Bump versions via changesets, rebuild, update docs |
| `pnpm changeset:publish` | Copy README to mermaid package and publish |
| `pnpm prepare` | husky setup + full build (runs on `npm install`) |

### 5.5 Log Levels

The logger (`packages/mermaid/src/logger.ts`) supports six levels:

| Level | Value | Console Method |
|-------|-------|----------------|
| `trace` | 0 | `console.debug` |
| `debug` | 1 | `console.debug` |
| `info` | 2 | `console.info` |
| `warn` | 3 | `console.warn` |
| `error` | 4 | `console.error` |
| `fatal` | 5 | `console.error` |

Set via `logLevel` config key or numerically. Default is `fatal` (5) -- only fatal errors appear in the console. Each log message is prefixed with a timestamp (`ss.SSS` format) and level name.

### 5.6 Error Handling

Mermaid defines two custom error classes:

- **`UnknownDiagramError`** -- Thrown when no detector matches the input text. Message: `"No diagram type detected matching given configuration for text: {text}"`.
- **`MermaidParseError`** -- Thrown by the Langium parser for syntax errors. Message: `"Unknown diagram type: {diagramType}"`.

When `suppressErrorRendering` is `false` (default), parse errors cause a "Syntax error" diagram to be rendered in place of the failed diagram. Set `suppressErrorRendering: true` to prevent this behavior.

The `setParseErrorHandler(fn)` method provides a global error callback:

```javascript
mermaid.setParseErrorHandler((err, hash) => {
  console.error('Mermaid parse error:', err);
});
```

---

## 6. Performance

### 6.1 Text Size Limits

The `maxTextSize` configuration (default: 50,000 characters) limits the input text length. The `maxEdges` configuration (default: 500) caps the number of edges in a single diagram. Both prevent denial-of-service through excessively large diagrams.

### 6.2 Layout Algorithm Selection

| Algorithm | Package | Best For | Tradeoffs |
|-----------|---------|----------|-----------|
| **dagre** (default) | Built-in (`dagre-d3-es`) | General-purpose graphs | Fast, but limited control over node positioning |
| **dagre-wrapper** | Built-in | Flowcharts, class, state | Enhanced dagre with cluster support and subgraph recursion |
| **ELK** | `@mermaid-js/layout-elk` | Complex graphs needing precise control | Better quality for large graphs; heavier (~200KB elkjs); configurable strategies |
| **CoSE-Bilkent** | Built-in (cytoscape) | Force-directed layouts | Good for organic layouts; less deterministic |
| **Tidy Tree** | `@mermaid-js/layout-tidy-tree` | Mindmaps | Bidirectional tree layout optimized for hierarchical data |

> [!TIP]
> For large flowcharts (100+ nodes), switching from dagre to ELK layout often produces better results. Set `layout: 'elk'` in the config or via directive: `%%{init: {"layout": "elk"}}%%`.

### 6.3 Lazy Loading

Diagram type modules are lazy-loaded by default. The `registerExternalDiagrams` function accepts a `lazyLoad` option (default: `true`). When lazy-loading is enabled, diagram code is only fetched when a matching diagram definition is first encountered.

### 6.4 Deterministic Rendering

For stable diffs in version-controlled SVG output, enable `deterministicIds: true` with an optional `deterministicIDSeed` string. This replaces random UUIDs with sequential, reproducible identifiers using the `InitIDGenerator` class.

### 6.5 Bundle Size Optimization

The `@mermaid-js/tiny` package (v11.14.0) provides a minimal build variant that excludes less-common diagram types. For applications needing only specific diagrams, tree-shaking with the tiny build significantly reduces bundle size.

---

## 7. Security

### 7.1 Security Levels

Mermaid provides four security levels, controlled by `securityLevel`:

| Level | Behavior |
|-------|----------|
| `strict` (default) | HTML tags in text are encoded. Click interactions disabled. All output sanitized. |
| `loose` | HTML tags rendered as-is. Click interactions enabled. Output still sanitized via DOMPurify. |
| `antiscript` | HTML tags allowed but script tags and event handlers stripped. |
| `sandbox` | Diagram rendered inside a sandboxed `<iframe>` with `sandbox` attribute. Maximum isolation. |

> [!CAUTION]
> Setting `securityLevel: 'loose'` allows HTML rendering in diagram labels. Only use this in environments where you fully control the diagram input. User-submitted diagrams with `loose` security can execute XSS attacks despite DOMPurify sanitization.

### 7.2 HTML Sanitization

All rendered HTML/SVG passes through **DOMPurify** (`dompurify` ^3.3.1). The `dompurifyConfig` option allows passing custom DOMPurify configuration if the defaults are too restrictive or not restrictive enough.

### 7.3 URL Sanitization

URLs in diagrams (links, click handlers) are sanitized via `@braintree/sanitize-url`, which blocks `javascript:`, `vbscript:`, and `data:` protocol URLs.

### 7.4 Config Sanitization (Directive Protection)

The `sanitize()` function in `config.ts` provides three layers of protection against malicious directives (`%%{init: {...}}%%`):

1. **Secure key enforcement** -- Keys in the `secure` array cannot be overridden by directives. By default: `secure`, `securityLevel`, `startOnLoad`, `maxTextSize`, `maxEdges`.

2. **Prototype pollution protection** -- Any key starting with `__` (double underscore) is silently deleted.

3. **XSS injection prevention** -- String values containing `<`, `>`, or `url(data:` are deleted. This prevents SVG/HTML injection via directive values.

```typescript
// Example: these directive values would be stripped
%%{init: {
  "fontFamily": "<script>alert('xss')</script>",  // stripped (contains <)
  "__proto__": {"polluted": true},                  // stripped (__ prefix)
  "securityLevel": "loose"                          // stripped (secure key)
}}%%
```

### 7.5 Additional Directive Sanitization

The `sanitizeDirective()` function (`packages/mermaid/src/utils/sanitizeDirective.ts`) provides a secondary sanitization pass for directives before they enter the config system, adding depth-limited traversal to prevent deeply nested attack payloads.

### 7.6 XSS Test Suite

The project maintains dedicated XSS tests:

- `cypress/integration/other/xss.spec.js` -- End-to-end XSS regression tests
- `cypress/platform/xss*.html` -- XSS test fixtures for manual and automated testing

> [!IMPORTANT]
> When integrating Mermaid into a CMS or user-facing application, always use `securityLevel: 'strict'` (the default) and ensure `maxTextSize` is set to a reasonable limit. Add the `secure` array to your `initialize()` call to lock down any additional config keys that users should not be able to override.

### 7.7 Content Security Policy (CSP)

When using `securityLevel: 'sandbox'`, Mermaid creates an `<iframe>` with the `sandbox` attribute. For strict CSP environments:

- `style-src 'unsafe-inline'` is required because Mermaid generates inline `<style>` elements for themes.
- `script-src` must allow the Mermaid library source.
- If using `htmlLabels: true`, `<foreignObject>` elements are inserted into SVG, which some CSP configurations may block.

---

## 8. Developer Internals

### 8.1 Diagram Plugin Architecture

To create a new diagram type, implement these four components:

```typescript
// 1. Detector: regex that identifies your diagram type
export const detector = (text: string, config?: MermaidConfig): boolean => {
  return /^\s*myDiagram/.test(text);
};

// 2. Database: parse state management
export const db = {
  clear: () => { /* reset state */ },
  setDiagramTitle: (title: string) => { /* store title */ },
  getDiagramTitle: () => string,
  // ... domain-specific getters/setters
};

// 3. Renderer: SVG generation
export const renderer = {
  draw: async (text: string, id: string, version: string, diagram: Diagram) => {
    // Use d3 to create SVG elements
  },
};

// 4. Styles: CSS generator
export const styles = (options: any): string => {
  return `.node { fill: ${options.primaryColor}; }`;
};

// Bundle as DiagramDefinition
export const diagram: DiagramDefinition = { db, parser, renderer, styles };
```

Register with the detection system:

```typescript
import { addDetector } from 'mermaid/diagram-api/detectType';

addDetector('myDiagram', detector, () =>
  import('./myDiagram').then(m => ({ id: 'myDiagram', diagram: m.diagram }))
);
```

### 8.2 Parser Architecture

**Jison parsers (legacy):**

Located in `packages/mermaid/src/diagrams/{type}/parser/*.jison`. These are Bison/Yacc-style grammars compiled to JavaScript at build time. The compiled parser attaches to `parser.parser.yy` which is set to the diagram's DB for direct state mutation during parsing.

**Langium parsers (modern):**

Located in `packages/parser/src/language/{type}/`. These use Langium's grammar language (`.langium` files) for type-safe AST generation. The `@mermaid-js/parser` package exports parser services for each diagram type. Langium parsers produce a typed AST rather than mutating a DB directly, then a transformer maps the AST to the DB format.

Current Langium-based diagrams: packet, info, pie (v2), gitGraph (v2), radar, architecture, wardley, treemap, treeView, eventmodeling, venn.

The common infrastructure shared between Langium parsers lives in `packages/parser/src/language/common/`:

- `CommonTokenBuilder` (extends `AbstractMermaidTokenBuilder`) -- Shared tokenization logic
- `CommonValueConverter` (extends `AbstractMermaidValueConverter`) -- Shared value conversion

### 8.3 Theme System

Mermaid ships 11 themes, implemented in `packages/mermaid/src/themes/`:

| Theme | Description |
|-------|-------------|
| `default` | Standard light theme |
| `base` | Bare-bones theme designed for customization via `themeVariables` |
| `dark` | Dark background with light text |
| `forest` | Green-tinted nature theme |
| `neutral` | Grayscale, suitable for printing |
| `neo` | Modern light design |
| `neo-dark` | Modern dark design |
| `redux` | Simplified light theme |
| `redux-dark` | Simplified dark theme |
| `redux-color` | Simplified with color accents |
| `redux-dark-color` | Dark with color accents |

Each theme module exports a `getThemeVariables(userOverrides?)` function that returns a complete set of CSS variables. The `base` theme is specifically designed as a customization foundation -- set `theme: 'base'` and provide `themeVariables` to create a fully custom look:

```javascript
mermaid.initialize({
  theme: 'base',
  themeVariables: {
    primaryColor: '#BB2528',
    primaryTextColor: '#fff',
    primaryBorderColor: '#7C0000',
    lineColor: '#F8B229',
    secondaryColor: '#006100',
    tertiaryColor: '#fff',
  },
});
```

Theme variables flow through the pipeline: `initialize()` passes `themeVariables` to the theme's `getThemeVariables()`, which computes derived colors (using the `khroma` library for color manipulation). The computed variables then feed into each diagram's `styles()` function to generate scoped CSS.

> [!NOTE]
> The `'null'` theme value (string "null") disables theming entirely. This is useful when you provide all styling via external CSS.

### 8.4 Layout System

The rendering pipeline supports pluggable layout algorithms through `LayoutLoaderDefinition`:

**Dagre (default):**
The dagre layout engine (`dagre-d3-es`) operates in two paths:
- **Legacy dagre-wrapper** (`packages/mermaid/src/dagre-wrapper/`) -- A recursive rendering implementation that handles subgraphs/clusters by recursively calling itself for nested graphs. This is the default for flowcharts, class diagrams, and state diagrams.
- **Unified layout path** (`packages/mermaid/src/rendering-util/layout-algorithms/dagre/`) -- A newer integration point used by the layout algorithm abstraction.

The dagre-wrapper's `recursiveRender()` function is notable: it inserts nodes into the DOM to measure their dimensions, then runs dagre layout on the abstract graph, and finally positions the DOM elements. For cluster nodes, it calls itself recursively.

**ELK (`@mermaid-js/layout-elk`):**
The ELK (Eclipse Layout Kernel) integration wraps `elkjs` for higher-quality layouts. It provides fine-grained control through the `elk` config namespace (node placement strategy, cycle breaking, model order preservation).

**CoSE-Bilkent** (`packages/mermaid/src/rendering-util/layout-algorithms/cose-bilkent/`):
A force-directed layout using the Cytoscape.js ecosystem. Produces organic, spring-like layouts.

**Tidy Tree** (`@mermaid-js/layout-tidy-tree`):
A bidirectional tree layout algorithm optimized for mindmaps and hierarchical data. Supports both top-down and left-right orientations.

### 8.5 Rendering Utilities

The `packages/mermaid/src/rendering-util/` directory contains shared rendering infrastructure:

- **`rendering-elements/`** -- Shape rendering functions for 50+ node shapes (rectangles, diamonds, circles, hexagons, stadiums, cylinders, etc.), edge rendering, cluster rendering, and marker insertion.
- **`layout-algorithms/`** -- Layout algorithm implementations and abstractions.
- **`render.ts`** -- Core render function and layout loader registry.
- **`icons.ts`** -- Icon pack registration system (sync and async loaders for custom icon sets).

### 8.6 Accessibility

Mermaid includes built-in accessibility support (`packages/mermaid/src/accessibility.ts`):

- SVG elements receive `role="graphics-document document"` (with ARIA 1.0 fallback).
- `aria-roledescription` is set to the diagram type name.
- `accTitle` and `accDescription` frontmatter directives generate `<title>` and `<desc>` elements with proper `aria-labelledby`/`aria-describedby` linkage.

### 8.7 Entity Encoding

Mermaid uses a custom entity encoding scheme to safely pass special characters through parsers. The `encodeEntities()` function in `utils.ts` converts HTML entities (e.g., `#9829;` for a heart) into an internal escape format (`ﬂ°°9829¶ß`), which survives parser transformations and is decoded back during rendering.

### 8.8 Testing Strategy

**Unit Tests (vitest):**

Located alongside source files as `*.spec.ts` and in `packages/parser/tests/`. Run with `pnpm test` or `pnpm ci`. Coverage via `@vitest/coverage-v8`.

Key test patterns:
- Config tests validate the three-tier config system, secure key enforcement, and directive handling.
- Diagram tests verify parser output and DB state for each diagram type.
- Accessibility tests use jsdom to verify SVG attributes.

**End-to-End Tests (Cypress):**

Located in `cypress/integration/`. Structure:
- `cypress/integration/rendering/` -- Visual regression tests for each diagram type.
- `cypress/integration/other/` -- XSS security tests, configuration tests.
- `cypress/platform/` -- HTML test fixtures including XSS regression pages.
- `cypress/helpers/` -- Shared test utilities.
- `cypress/support/` -- Cypress custom commands and setup.

Visual regression uses `cypress-image-snapshot` and Argos CI (`@argos-ci/cypress`) for screenshot comparison.

> [!TIP]
> The project uses `start-server-and-test` to coordinate dev server startup with Cypress test execution. Run `pnpm e2e` for the full flow, or `pnpm cypress:open` for interactive test development.

### 8.9 Contributing: Development Workflow

1. **Clone and install:**
   ```bash
   git clone https://github.com/mermaid-js/mermaid.git
   cd mermaid
   pnpm install
   ```

2. **Start dev server:**
   ```bash
   pnpm dev
   ```

3. **Make changes** in `packages/mermaid/src/` or other packages.

4. **Run tests:**
   ```bash
   pnpm test          # lint + unit tests
   pnpm e2e           # end-to-end tests
   ```

5. **Lint and format:**
   ```bash
   pnpm lint:fix       # auto-fix eslint + prettier
   ```

6. **Build for production:**
   ```bash
   pnpm build
   ```

Pre-commit hooks (managed by `husky` + `lint-staged`) automatically run linting on staged files.

### 8.10 State Management

The `ImperativeState` class (`packages/mermaid/src/utils/imperativeState.ts`) provides a pattern for diagram DB state that can be cleanly reset between renders. Each diagram DB uses this to maintain parse state (nodes, edges, actors, tasks, etc.) with a guaranteed-clean `clear()` method.

### 8.11 Interaction System

The `interactionDb.ts` module manages click handlers for interactive diagrams. Functions registered via `addFunction()` are executed by `attachFunctions()` after SVG insertion. In `strict` security level, click interactions are disabled.

### 8.12 Internal Helpers (Deprecated)

The `internalHelpers` export (`packages/mermaid/src/internals.ts`) exposes internal rendering functions for external diagram plugins. These are explicitly marked as deprecated and may change without notice:

```typescript
export const internalHelpers = {
  common, getConfig, insertCluster, insertEdge,
  insertEdgeLabel, insertMarkers, insertNode,
  interpolateToCurve, labelHelper, log, positionEdgeLabel,
};
```

> [!CAUTION]
> External diagram plugins currently depend on `internalHelpers` for rendering primitives. This coupling is a known technical debt. The mermaid team plans to provide a stable rendering API in a future version.

---

## 9. Integration Points

### 9.1 Public API Summary

The `mermaid` default export provides these methods:

| Method | Signature | Description |
|--------|-----------|-------------|
| `initialize` | `(config: MermaidConfig) => void` | Set site-wide configuration. Must be called before `run`. |
| `run` | `(options?: RunOptions) => Promise<void>` | Find and render all diagram elements in the DOM. |
| `render` | `(id: string, text: string, container?: Element) => Promise<RenderResult>` | Render a single diagram to SVG string. |
| `parse` | `(text: string, options?: ParseOptions) => Promise<ParseResult>` | Validate diagram syntax without rendering. |
| `registerExternalDiagrams` | `(diagrams: ExternalDiagramDefinition[], opts?) => Promise<void>` | Register third-party diagram types. |
| `registerLayoutLoaders` | `(loaders: LayoutLoaderDefinition[]) => void` | Register custom layout algorithms. |
| `registerIconPacks` | `(loaders: IconLoader[]) => void` | Register custom icon packs (sync or async). |
| `contentLoaded` | `() => void` | Trigger diagram rendering (called automatically on page load). |
| `setParseErrorHandler` | `(handler: (err, hash) => void) => void` | Set global parse error callback. |

**`RunOptions`:**

```typescript
interface RunOptions {
  querySelector?: string;  // Default: ".mermaid"
  nodes?: ArrayLike<HTMLElement>;  // Overrides querySelector
  postRenderCallback?: (id: string) => unknown;
  suppressErrors?: boolean;  // Default: false
}
```

**`ParseOptions` and `ParseResult`:**

```typescript
interface ParseOptions {
  suppressErrors?: boolean;
}

interface ParseResult {
  diagramType: string;
}
```

**`RenderResult`:**

```typescript
interface RenderResult {
  svg: string;
  bindFunctions?: (element: Element) => void;
}
```

### 9.2 Frontmatter and Directives

Mermaid diagrams support YAML frontmatter and inline directives for per-diagram configuration:

**Frontmatter:**
```
---
title: My Diagram
config:
  theme: dark
---
flowchart LR
  A --> B
```

**Inline directive:**
```
%%{init: {"theme": "forest", "flowchart": {"nodeSpacing": 100}}}%%
flowchart LR
  A --> B
```

The `utils.detectInit(text)` function extracts frontmatter and directive configurations, which are applied as directives to the current config.

### 9.3 Icon Packs

Custom icons can be registered for use in architecture diagrams and other icon-supporting diagram types:

```typescript
// Synchronous loader
mermaid.registerIconPacks([
  {
    name: 'my-icons',
    loader: () => ({
      prefix: 'mi',
      icons: { server: { body: '<path d="..."/>', width: 24, height: 24 } },
    }),
  },
]);

// Asynchronous loader
mermaid.registerIconPacks([
  {
    name: 'remote-icons',
    loader: () => fetch('/icons.json').then(r => r.json()),
  },
]);
```

### 9.4 Webpack Integration

The `tests/webpack/` directory provides a reference implementation for Webpack-based projects, demonstrating how to configure Webpack to bundle Mermaid correctly with its ESM dependencies.

### 9.5 VitePress Documentation Integration

The official documentation site (`packages/mermaid/src/docs/`) uses VitePress with:

- `unplugin-vue-components` for auto-importing Vue components
- `unocss` for utility-first CSS
- `vitepress-plugin-search` for full-text search
- A custom `IncludesPlugin` for file inclusion directives
- A virtual module (`virtual:mermaid-config`) providing default Mermaid config for live examples

The docs dev server configuration aliases `mermaid` to the built distribution file (`../../dist/mermaid.esm.min.mjs`), ensuring docs render with the current build.

### 9.6 Known Issues

| Issue | Description |
|-------|-------------|
| [#3526](https://github.com/mermaid-js/mermaid/issues/3526) | CSS classes not working with Flowchart v8.8.0+ |
| [#7609](https://github.com/mermaid-js/mermaid/issues/7609) | Internal error on subgraph with numeric identifier |
| [#6142](https://github.com/mermaid-js/mermaid/issues/6142) | `fontSize` themeVariable setting ignored |
| [#1361](https://github.com/mermaid-js/mermaid/issues/1361) | ER diagram attributes (feature request) |
| [#2199](https://github.com/mermaid-js/mermaid/issues/2199) | Multi-line notes in sequence diagrams (feature request) |

> [!WARNING]
> The `flowchart.htmlLabels` config is deprecated. Use the root-level `htmlLabels` setting instead. The root-level value always takes precedence. A deprecation warning is logged on first use of the flowchart-specific setting.

---

_Generated May 2026 from mermaid-js/mermaid at 8b52e53. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
