@zombie-mermaid/core 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1236 @@
1
+ import { ElkNode } from 'elkjs';
2
+
3
+ /**
4
+ * Test-only: reset the title-id counter so id assertions in tests don't
5
+ * depend on how many titled diagrams earlier tests in the same file rendered.
6
+ * Not part of the public API (not re-exported from src/index.ts).
7
+ */
8
+ export declare function __resetSvgTitleIdCounterForTests(): void;
9
+
10
+ /**
11
+ * Parse a `click <id> ...` statement and record the resulting
12
+ * {@link NodeInteraction} in `interactions`, keyed by whatever id scheme the
13
+ * caller's diagram type uses (flowchart/state node id, class diagram class
14
+ * id, ...).
15
+ *
16
+ * Supported forms:
17
+ * click id "url" ["tooltip"] [_blank|_self|_parent|_top]
18
+ * click id href "url" ["tooltip"] [_blank|_self|_parent|_top]
19
+ * click id call fn() ["tooltip"]
20
+ * click id callback fn() ["tooltip"]
21
+ *
22
+ * A line that doesn't match `click <id> ...` at all is a no-op — callers are
23
+ * expected to have already gated on a leading `click` keyword before calling
24
+ * this (see the `/^click\s+/i` checks at each call site) purely so this
25
+ * function's own regex can stay anchored to the id capture.
26
+ */
27
+ export declare function applyClickStatement(line: string, interactions: Map<string, NodeInteraction>): void;
28
+
29
+ /**
30
+ * Fold an init config into render options.
31
+ *
32
+ * Caller-supplied options always win: a directive supplies a default, never
33
+ * an override. See the module header for why.
34
+ */
35
+ export declare function applyInitConfig(options: RenderOptions, config: InitConfig): RenderOptions;
36
+
37
+ /**
38
+ * Build the CSS variable derivation rules for the SVG <style> block.
39
+ *
40
+ * When an optional variable (--line, --accent, etc.) is set on the SVG or
41
+ * a parent element, it's used directly. When unset, the fallback computes
42
+ * a blended value from --fg and --bg using color-mix().
43
+ *
44
+ * `nonce`, when given, lands on the `<style>` element as a `nonce`
45
+ * attribute — see `styleOpenTag()`.
46
+ *
47
+ * `font` is user-supplied input. When it's a CSS `var(...)` reference (e.g.
48
+ * `var(--font-family-body)`, letting the SVG inherit a host page's
49
+ * design-system font), the Google Fonts `@import` is skipped — it would
50
+ * otherwise URL-encode the literal `var(...)` string into a `family=` query
51
+ * param and produce a guaranteed no-op request — and the value is emitted
52
+ * unquoted, since a quoted string isn't parsed as a `var()` call by CSS.
53
+ *
54
+ * The `@import` is likewise skipped when `font` is a font *stack* (a
55
+ * comma-separated list, e.g. `"ui-sans-serif, system-ui, sans-serif"`) or a
56
+ * single CSS generic family keyword (e.g. `"system-ui"`) — see
57
+ * `isFontStackOrGenericFamily`. Neither names a single concrete font that
58
+ * Google Fonts could host, so importing one always produces a dead,
59
+ * always-404 request (#223). This is additive to the `var()` skip above,
60
+ * and only affects the `@import` decision — the `text { font-family: ... }`
61
+ * rule still renders the literal value exactly as it does today.
62
+ *
63
+ * Any other value is treated as a literal font name: sanitized and quoted
64
+ * exactly as before.
65
+ *
66
+ * `hasMonoFont`'s `.mono` rule (class-diagram method signatures, ER-diagram
67
+ * attribute types) never reaches out to Google Fonts at all — it used to
68
+ * `@import` 'JetBrains Mono' from Google's CDN, a third-party network
69
+ * dependency a published library's default SVG output had no business
70
+ * making (#1061, filed as a follow-up from #1059's ASCII-side self-hosting
71
+ * fix). It now embeds {@link SVG_MONO_FONT_FACE_CSS} — a small, subsetted
72
+ * (Basic Latin + Latin-1 Supplement), self-hosted `@font-face` as a base64
73
+ * `woff2` data URI, generated by scripts/build-mono-font-subset.ts into
74
+ * ./generated/mono-font-subset.ts — directly in the SVG's own `<style>`
75
+ * block. Unlike `font` above, this isn't caller-configurable: it's the same
76
+ * embed for every consumer, on by default, with no network request either
77
+ * way — a strict improvement over the dead-or-alive CDN fetch it replaces,
78
+ * and the only way a *standalone* SVG (no surrounding host page providing
79
+ * its own copy of the font) renders `.mono` text correctly out of the box.
80
+ */
81
+ export declare function buildStyleBlock(font: string, hasMonoFont: boolean, nonce?: string): string;
82
+
83
+ /**
84
+ * Options applicable to class diagrams (`classDiagram`). Class diagrams use
85
+ * fixed internal padding/spacing (not `padding`/`nodeSpacing`/
86
+ * `layerSpacing`) and have no `direction` or `curve` concept; `interactivity`
87
+ * gates `click`-based links only — there's no edge-animation concept to gate.
88
+ */
89
+ export declare type ClassRenderOptions = CommonRenderOptions & Pick<RenderOptions, 'fontSizes' | 'interactivity' | 'layoutCache'>;
90
+
91
+ /**
92
+ * Options every diagram type honors: theming (colors, font), the shared
93
+ * strict-CSP/accessibility/output controls, and the post-render
94
+ * `resolveColors` pass. Every other `RenderOptions` field applies to only a
95
+ * subset of diagram types — see the per-type types below.
96
+ */
97
+ export declare type CommonRenderOptions = Pick<RenderOptions, 'bg' | 'fg' | 'line' | 'accent' | 'muted' | 'surface' | 'border' | 'font' | 'transparent' | 'embedSource' | 'resolveColors' | 'nonce' | 'styleAttribute' | 'title' | 'decorative'>;
98
+
99
+ /** How an edge path is interpolated between its routed points. */
100
+ export declare type CurveStyle = 'linear' | 'basis' | 'natural' | 'step' | 'stepBefore' | 'stepAfter';
101
+
102
+ /** Default bg/fg when no colors are provided (zinc light) */
103
+ export declare const DEFAULTS: Readonly<{
104
+ bg: string;
105
+ fg: string;
106
+ }>;
107
+
108
+ /** Human-readable note about directive keys that were parsed but not applied. */
109
+ export declare function describeIgnored(config: InitConfig): string[];
110
+
111
+ /**
112
+ * Detect the diagram type from the mermaid source text.
113
+ * Returns the type keyword used for routing to the correct pipeline.
114
+ *
115
+ * The header keyword is the first *statement*, not the first line: Mermaid
116
+ * allows `;` as a statement separator, so `flowchart TD;A-->B` has its header
117
+ * and first edge on one line. Uses the same splitter every parser uses, so
118
+ * routing and parsing can never disagree about where the header ends.
119
+ */
120
+ export declare function detectDiagramType(text: string): DiagramType;
121
+
122
+ /**
123
+ * Diagram color configuration.
124
+ *
125
+ * Required: bg + fg give you a clean mono diagram.
126
+ * Optional: line, accent, muted, surface, border bring in richer color
127
+ * from Shiki themes or custom palettes. Each falls back to a color-mix()
128
+ * derivation from bg + fg if not set.
129
+ */
130
+ export declare interface DiagramColors {
131
+ /** Background color → CSS variable --bg */
132
+ bg: string;
133
+ /** Foreground / primary text color → CSS variable --fg */
134
+ fg: string;
135
+ /** Edge/connector color → CSS variable --line */
136
+ line?: string;
137
+ /** Arrow heads, highlights, special nodes → CSS variable --accent */
138
+ accent?: string;
139
+ /** Secondary text, edge labels → CSS variable --muted */
140
+ muted?: string;
141
+ /** Node/box fill tint → CSS variable --surface */
142
+ surface?: string;
143
+ /** Node/group stroke color → CSS variable --border */
144
+ border?: string;
145
+ }
146
+
147
+ /** The diagram types this library can detect and route to a renderer. */
148
+ export declare type DiagramType = 'flowchart' | 'sequence' | 'class' | 'er' | 'xychart';
149
+
150
+ export declare type Direction = 'TD' | 'TB' | 'LR' | 'BT' | 'RL';
151
+
152
+ export declare type EdgeStyle = 'solid' | 'dotted' | 'thick'
153
+ /** `A ~~~ B` — participates in layout but draws no line or arrowhead. */
154
+ | 'invisible';
155
+
156
+ /**
157
+ * Options applicable to ER diagrams (`erDiagram`). ER diagrams use fixed
158
+ * internal padding/spacing and ignore `curve` and `interactivity` (no
159
+ * animated edges or `click` links in this renderer's ER support), but do
160
+ * honor `direction` (applied before layout via `withDirectionOverride`).
161
+ */
162
+ export declare type ErRenderOptions = CommonRenderOptions & Pick<RenderOptions, 'direction' | 'fontSizes' | 'layoutCache'>;
163
+
164
+ /**
165
+ * Escape a string for use as an XML/HTML attribute value.
166
+ * Escapes quotes and ampersands to prevent attribute injection.
167
+ *
168
+ * Deliberately distinct from `escapeXml()` above: attribute values in this
169
+ * codebase are always double-quoted, so single quotes don't need escaping —
170
+ * `escapeXml()` escapes them too (for safe embedding in either quote style),
171
+ * which would change output if reused here.
172
+ */
173
+ export declare function escapeAttr(value: string): string;
174
+
175
+ /**
176
+ * Escape special XML characters in text content.
177
+ */
178
+ export declare function escapeXml(text: string): string;
179
+
180
+ /**
181
+ * Scan a whole diagram for init directives and merge them.
182
+ *
183
+ * Later directives win over earlier ones, matching Mermaid, where a second
184
+ * directive overrides the first.
185
+ */
186
+ export declare function extractInitConfig(lines: string[]): InitConfig;
187
+
188
+ /**
189
+ * Options applicable to flowchart (`graph` / `flowchart`) and state
190
+ * (`stateDiagram-v2`) diagrams — both share `DiagramType: 'flowchart'` and
191
+ * the same layout/render pipeline (src/layout-engine.ts, src/renderer.ts),
192
+ * so they share one option shape. `componentSpacing` is currently a no-op
193
+ * everywhere (accepted for forward compatibility only) but grouped here
194
+ * since it's spacing-shaped like `padding`/`nodeSpacing`/`layerSpacing`.
195
+ */
196
+ export declare type FlowchartRenderOptions = CommonRenderOptions & Pick<RenderOptions, 'padding' | 'nodeSpacing' | 'layerSpacing' | 'componentSpacing' | 'mergeEdges' | 'direction' | 'curve' | 'fontSizes' | 'interactivity' | 'layoutCache'>;
197
+
198
+ /**
199
+ * Serialize a color as `#rrggbb` when fully opaque, otherwise as
200
+ * `rgba(r, g, b, a)` — the two forms every SVG consumer (browsers, resvg,
201
+ * librsvg, Inkscape) agrees on.
202
+ */
203
+ export declare function formatCssColor(c: RgbaColor): string;
204
+
205
+ /**
206
+ * Extract diagram colors from a Shiki theme object.
207
+ * Works with any VS Code / TextMate theme loaded by Shiki.
208
+ *
209
+ * Maps editor UI colors to diagram roles:
210
+ * editor.background → bg
211
+ * editor.foreground → fg
212
+ * editorLineNumber.fg → line (optional)
213
+ * focusBorder / keyword → accent (optional)
214
+ * comment token → muted (optional)
215
+ * editor.selectionBackground→ surface (optional)
216
+ * editorWidget.border → border (optional)
217
+ *
218
+ * @example
219
+ * ```ts
220
+ * import { getSingletonHighlighter } from 'shiki'
221
+ * import { fromShikiTheme } from 'zombie-mermaid'
222
+ *
223
+ * const hl = await getSingletonHighlighter({ themes: ['tokyo-night'] })
224
+ * const colors = fromShikiTheme(hl.getTheme('tokyo-night'))
225
+ * const svg = renderMermaidSVG(code, colors)
226
+ * ```
227
+ */
228
+ export declare function fromShikiTheme(theme: ShikiThemeLike): DiagramColors;
229
+
230
+ /**
231
+ * Get the relative width of a single character.
232
+ *
233
+ * Returns a normalized width ratio where:
234
+ * - 0.0 = zero-width (combining marks)
235
+ * - 0.3 = space
236
+ * - 0.4 = narrow (i, l, t, f, j, I, 1)
237
+ * - 0.8 = semi-narrow (r)
238
+ * - 1.0 = average lowercase
239
+ * - 1.2 = wide lowercase / uppercase
240
+ * - 1.5 = very wide (W, M)
241
+ * - 2.0 = fullwidth (CJK, emoji)
242
+ */
243
+ export declare function getCharWidth(char: string): number;
244
+
245
+ /**
246
+ * Pick a readable text color for a given fill color.
247
+ *
248
+ * If `fill` is a concrete, resolvable hex color, returns pure black or
249
+ * white depending on the fill's perceptual luminance (threshold 0.5: light
250
+ * fills get dark text, dark fills get light text). If `fill` is undefined
251
+ * or isn't a resolvable color (a `var(...)` reference, a named CSS color,
252
+ * or malformed input), returns `fallback` unchanged so callers don't guess
253
+ * at colors they can't actually evaluate.
254
+ */
255
+ export declare function getReadableTextColor(fill: string | undefined, fallback: string): string;
256
+
257
+ /**
258
+ * Whether `char` has an exact measured Inter advance in `INTER_ADVANCES`,
259
+ * as opposed to falling through to a coarse character-class bucket or the
260
+ * default width in `getCharWidth`. Exported only so tests can assert the
261
+ * table covers every printable ASCII character (U+0020–U+007E) — a gap
262
+ * here means a real character silently degrades to an approximate width.
263
+ */
264
+ export declare function hasMeasuredAdvance(char: string): boolean;
265
+
266
+ /** Configuration a diagram can set for itself via `%%{init: ...}%%`. */
267
+ export declare interface InitConfig {
268
+ theme?: string;
269
+ /** Flowchart edge interpolation. */
270
+ curve?: CurveStyle;
271
+ /** Recognized but not acted on — see `IGNORED_KEYS`. */
272
+ ignored: string[];
273
+ }
274
+
275
+ /** True when `value` is one of the five directions Mermaid recognizes. */
276
+ export declare function isDirection(value: string): value is Direction;
277
+
278
+ /** True if `line` is an init directive. */
279
+ export declare function isInitDirective(line: string): boolean;
280
+
281
+ /** Fonts whose glyphs all share one advance width. */
282
+ export declare function isMonospaceFont(font: string): boolean;
283
+
284
+ /**
285
+ * Check if a single character (code point) is "wide" — i.e. renders as two
286
+ * columns in a monospace terminal / two grid cells wide instead of one.
287
+ * Covers CJK/kana/hangul/fullwidth-form characters (via `isFullwidth`) as
288
+ * well as emoji. Shared by the SVG text-measurement path (`getCharWidth`
289
+ * above) and the ASCII grid's display-width helpers
290
+ * (`src/ascii/display-width.ts`), so both agree on what counts as wide.
291
+ */
292
+ export declare function isWideChar(char: string): boolean;
293
+
294
+ /**
295
+ * Opt-in bounded LRU cache for `elkLayoutSync()` results.
296
+ *
297
+ * Off by default — `elkLayoutSync()` only consults a cache when one is
298
+ * explicitly passed in, so existing callers see no behavior change.
299
+ * Create one with `createLayoutCache()` and reuse it across renders (e.g.
300
+ * module scope, or a `useRef` in React) — a fresh cache per render defeats
301
+ * the point.
302
+ *
303
+ * The `map`/`maxSize` fields are implementation detail exposed only so
304
+ * `elkLayoutSync()` (and tests) can read/mutate them directly without a
305
+ * class; treat a `LayoutCache` as opaque from outside this module.
306
+ */
307
+ export declare interface LayoutCache {
308
+ /* Excluded from this release type: map */
309
+ /* Excluded from this release type: maxSize */
310
+ }
311
+
312
+ /** Standard line height ratio for multi-line text (1.3 = 130% of font size) */
313
+ export declare const LINE_HEIGHT_RATIO = 1.3;
314
+
315
+ /**
316
+ * Measure multi-line text dimensions.
317
+ *
318
+ * Splits text on newlines and returns the maximum width across all lines,
319
+ * total height based on line count, and the split lines for rendering.
320
+ *
321
+ * @param text - The text to measure (may contain \n)
322
+ * @param fontSize - Font size in pixels
323
+ * @param fontWeight - Font weight (affects width slightly)
324
+ * @returns Metrics including width, height, lines array, and lineHeight
325
+ */
326
+ export declare function measureMultilineText(text: string, fontSize: number, fontWeight: number): MultilineMetrics;
327
+
328
+ export declare function measureTextWidth(text: string, fontSize: number, fontWeight: number): number;
329
+
330
+ export declare interface MermaidEdge {
331
+ source: string;
332
+ target: string;
333
+ label?: string;
334
+ style: EdgeStyle;
335
+ /** Whether to render an arrowhead at the start (source end) of the edge */
336
+ hasArrowStart: boolean;
337
+ /** Whether to render an arrowhead at the end (target end) of the edge */
338
+ hasArrowEnd: boolean;
339
+ /**
340
+ * Terminator shape at the source end when it's a circle/cross marker
341
+ * (`o--`/`x--`) rather than a plain arrowhead. Undefined for a regular
342
+ * `<`-style arrowhead or no marker at all — `hasArrowStart` alone still
343
+ * governs whether anything is drawn there. Currently consumed by the
344
+ * ASCII renderer only (see issue #330); the SVG renderer still draws a
345
+ * plain arrowhead for these.
346
+ */
347
+ startMarker?: 'circle' | 'cross';
348
+ /** Terminator shape at the target end (`--o`/`--x`). See `startMarker`. */
349
+ endMarker?: 'circle' | 'cross';
350
+ /** Edge id from `A e1@--> B` (Mermaid v11.10.0+), for `e1@{ ... }` and CSS targeting */
351
+ id?: string;
352
+ /** Set by `e1@{ animate: true }` — renders as a marching-ants dash */
353
+ animate?: boolean;
354
+ }
355
+
356
+ export declare interface MermaidGraph {
357
+ direction: Direction;
358
+ nodes: Map<string, MermaidNode>;
359
+ edges: MermaidEdge[];
360
+ subgraphs: MermaidSubgraph[];
361
+ classDefs: Map<string, Record<string, string>>;
362
+ /** Maps node IDs to their class names (from `class X className` or `:::className` shorthand) */
363
+ classAssignments: Map<string, string>;
364
+ /** Maps node IDs to inline styles (from `style X fill:#f00,stroke:#333`) */
365
+ nodeStyles: Map<string, Record<string, string>>;
366
+ /** Maps edge indices (or 'default') to inline styles from `linkStyle` directives */
367
+ linkStyles: Map<number | 'default', Record<string, string>>;
368
+ /** Maps node IDs to interactions declared by `click` statements */
369
+ interactions: Map<string, NodeInteraction>;
370
+ /** Configuration the diagram set for itself via `%%{init: ...}%%` */
371
+ initConfig?: InitConfig;
372
+ }
373
+
374
+ export declare interface MermaidNode {
375
+ id: string;
376
+ label: string;
377
+ shape: NodeShape;
378
+ }
379
+
380
+ export declare interface MermaidSubgraph {
381
+ id: string;
382
+ label: string;
383
+ nodeIds: string[];
384
+ children: MermaidSubgraph[];
385
+ /** Optional direction override for this subgraph's internal layout */
386
+ direction?: Direction;
387
+ }
388
+
389
+ export declare const MIX: {
390
+ /** Primary text: near-full fg */
391
+ readonly text: 100;
392
+ /** Secondary text (group headers): fg mixed at 60% */
393
+ readonly textSec: 60;
394
+ /** Muted text (edge labels, notes): fg mixed at 40% */
395
+ readonly textMuted: 40;
396
+ /** Faint text (de-emphasized): fg mixed at 25% */
397
+ readonly textFaint: 25;
398
+ /** Edge/connector lines: fg mixed at 50% for clear visibility */
399
+ readonly line: 50;
400
+ /** Arrow head fill: fg mixed at 85% for clear visibility */
401
+ readonly arrow: 85;
402
+ /** Node fill tint: fg mixed at 3% */
403
+ readonly nodeFill: 3;
404
+ /** Node/group stroke: fg mixed at 20% */
405
+ readonly nodeStroke: 20;
406
+ /** Group header band tint: fg mixed at 5% */
407
+ readonly groupHeader: 5;
408
+ /** Inner divider strokes: fg mixed at 12% */
409
+ readonly innerStroke: 12;
410
+ /** Key badge background opacity (ER diagrams) */
411
+ readonly keyBadge: 10;
412
+ };
413
+
414
+ /**
415
+ * Mix `fg` into `bg` at `pct` percent — the shape every MIX entry in
416
+ * packages/core/src/theme.ts uses (`color-mix(in srgb, var(--fg) N%, var(--bg))`).
417
+ * Returns `fg` unchanged when either input isn't a concrete color this
418
+ * module can parse (a `var(...)` reference, a named color).
419
+ */
420
+ export declare function mixHexColors(fg: string, bg: string, pct: number): string;
421
+
422
+ /**
423
+ * Evaluate `color-mix(in srgb, c1 p1%, c2 p2%)` per CSS Color Module
424
+ * Level 5 (https://www.w3.org/TR/css-color-5/#color-mix): percentages are
425
+ * normalized so they sum to 100 (a sum under 100 additionally scales the
426
+ * result's alpha by `sum / 100`), and the two colors are interpolated in
427
+ * premultiplied-alpha space, so mixing an opaque color toward
428
+ * `transparent` fades its alpha without darkening it.
429
+ *
430
+ * `p1`/`p2` follow the spec's omission rules: pass `undefined` for an
431
+ * omitted percentage (both omitted → 50/50; one omitted → 100 minus the
432
+ * other). Returns null when both percentages are zero, which the spec
433
+ * defines as invalid.
434
+ */
435
+ export declare function mixSrgb(c1: RgbaColor, c2: RgbaColor, p1?: number, p2?: number): RgbaColor | null;
436
+
437
+ /** Metrics for multi-line text measurement */
438
+ export declare interface MultilineMetrics {
439
+ /** Maximum line width in pixels */
440
+ width: number;
441
+ /** Total height in pixels (lines × lineHeight) */
442
+ height: number;
443
+ /** Individual lines after splitting */
444
+ lines: string[];
445
+ /** Computed line height in pixels */
446
+ lineHeight: number;
447
+ }
448
+
449
+ /**
450
+ * An interaction attached to a node by a `click` statement.
451
+ *
452
+ * This renderer emits static SVG and never executes diagram-supplied script,
453
+ * so a `call`/callback binding is parsed but not invoked — see
454
+ * docs/diagrams.md and docs/decisions/no-script-interactivity.md. An `href`
455
+ * becomes a real SVG link and a tooltip becomes a `<title>`.
456
+ */
457
+ export declare interface NodeInteraction {
458
+ /** `click A "https://..."` — rendered as an <a> wrapper */
459
+ href?: string;
460
+ /** Link target, e.g. `_blank` */
461
+ target?: string;
462
+ /** Tooltip text — rendered as a <title> child */
463
+ tooltip?: string;
464
+ /**
465
+ * `click A call fn()` — the raw expression text (`fn()`), exposed as data
466
+ * only. Nothing in the rendered SVG carries it and the library never
467
+ * evaluates it; a host that trusts its diagram source reads it from
468
+ * `parseMermaid(source).interactions` and binds behaviour to the node's
469
+ * `data-id` attribute itself:
470
+ *
471
+ * ```ts
472
+ * for (const [id, { callback }] of parseMermaid(source).interactions) {
473
+ * if (callback === 'showDetail()') {
474
+ * svgRoot.querySelector(`[data-id="${id}"]`)
475
+ * ?.addEventListener('click', () => showDetail(id))
476
+ * }
477
+ * }
478
+ * ```
479
+ */
480
+ callback?: string;
481
+ }
482
+
483
+ export declare type NodeShape = 'rectangle' | 'rounded' | 'diamond' | 'stadium' | 'circle' | 'subroutine' | 'doublecircle' | 'hexagon' | 'cylinder' | 'asymmetric' | 'trapezoid' | 'trapezoid-alt' | 'parallelogram' | 'parallelogram-alt' | 'state-start' | 'state-end' | 'document' | 'stacked-document' | 'stacked-process' | 'card' | 'lined-process' | 'divided-process' | 'window-pane' | 'triangle' | 'flipped-triangle' | 'filled-circle' | 'crossed-circle' | 'fork-join' | 'notched-pentagon' | 'sloped-rectangle' | 'flag' | 'bow-tie-rectangle' | 'half-rounded-rectangle' | 'brace' | 'brace-right' | 'braces' | 'bolt' | 'text' | 'anchor';
484
+
485
+ /**
486
+ * Normalize label text: strip surrounding quotes, convert <br> tags and
487
+ * literal \n sequences to newline characters. Strips unsupported HTML tags
488
+ * but preserves formatting tags (<b>, <i>, <u>, <s>) for SVG rendering.
489
+ */
490
+ export declare function normalizeBrTags(label: string): string;
491
+
492
+ /**
493
+ * Parse a concrete CSS color value into sRGB components.
494
+ *
495
+ * Accepts the forms this library's own theme system produces or documents:
496
+ * hex literals (`#rgb`, `#rgba`, `#rrggbb`, `#rrggbbaa`), `rgb()`/`rgba()`,
497
+ * and the `transparent` keyword. Anything else — CSS named colors, `hsl()`,
498
+ * `var(...)`, an unresolved `color-mix(...)` — returns null so the caller
499
+ * can leave it untouched rather than guess.
500
+ */
501
+ export declare function parseCssColor(value: string): RgbaColor | null;
502
+
503
+ /**
504
+ * Parse a hex color string into 0-255 RGB components, ignoring any alpha
505
+ * digits. Returns null for anything that isn't a well-formed hex literal
506
+ * (e.g. `var(--foo)`, named CSS colors, or attribute-injection payloads) —
507
+ * the caller should treat those as unresolvable and fall back.
508
+ */
509
+ export declare function parseHexColor(value: string): [number, number, number] | null;
510
+
511
+ /** Parse a hex color literal (3/4/6/8 digits) into an RgbaColor, or null. */
512
+ export declare function parseHexRgba(value: string): RgbaColor | null;
513
+
514
+ /**
515
+ * Parse an init directive's payload.
516
+ *
517
+ * Returns `undefined` when the line is not a directive or its payload cannot
518
+ * be parsed. A malformed directive is ignored rather than fatal: Mermaid
519
+ * treats config as advisory, and failing an entire diagram over a stray brace
520
+ * in a comment-like construct would be a poor trade.
521
+ */
522
+ export declare function parseInitDirective(line: string): InitConfig | undefined;
523
+
524
+ /** Parse "fill:#f00,stroke:#333" style property strings into a Record */
525
+ export declare function parseStyleProps(propsStr: string): Record<string, string>;
526
+
527
+ export declare interface Point {
528
+ x: number;
529
+ y: number;
530
+ }
531
+
532
+ export declare interface PositionedEdge {
533
+ source: string;
534
+ target: string;
535
+ label?: string;
536
+ style: EdgeStyle;
537
+ hasArrowStart: boolean;
538
+ hasArrowEnd: boolean;
539
+ /** Full path including bends — array of {x, y} points */
540
+ points: Point[];
541
+ /** Layout-computed label center position (avoids label-label collisions) */
542
+ labelPosition?: Point;
543
+ /** Inline styles resolved from `linkStyle` directives — override theme defaults */
544
+ inlineStyle?: Record<string, string>;
545
+ /** Edge id from `A e1@--> B`, emitted as data-id for CSS targeting */
546
+ id?: string;
547
+ /** Set by `e1@{ animate: true }` — renders as a marching-ants dash */
548
+ animate?: boolean;
549
+ }
550
+
551
+ export declare interface PositionedGraph {
552
+ width: number;
553
+ height: number;
554
+ nodes: PositionedNode[];
555
+ edges: PositionedEdge[];
556
+ groups: PositionedGroup[];
557
+ }
558
+
559
+ export declare interface PositionedGroup {
560
+ id: string;
561
+ label: string;
562
+ x: number;
563
+ y: number;
564
+ width: number;
565
+ height: number;
566
+ children: PositionedGroup[];
567
+ }
568
+
569
+ export declare interface PositionedNode {
570
+ id: string;
571
+ label: string;
572
+ shape: NodeShape;
573
+ x: number;
574
+ y: number;
575
+ width: number;
576
+ height: number;
577
+ /** Inline styles resolved from classDef + explicit `style` statements — override theme defaults */
578
+ inlineStyle?: Record<string, string>;
579
+ /** Custom class name assigned via `class A className` or `:::className` shorthand — emitted onto the rendered element's `class` attribute so external CSS can target it */
580
+ className?: string;
581
+ /** Interaction from a `click` statement — an href wraps the node in an <a> */
582
+ interaction?: NodeInteraction;
583
+ }
584
+
585
+ /**
586
+ * Render a multi-line text element with proper vertical centering.
587
+ *
588
+ * For single-line text, returns a simple <text> element.
589
+ * For multi-line text (containing \n), returns <text> with <tspan> children.
590
+ * Inline formatting tags (<b>, <i>, <u>, <s>) are rendered as SVG attributes.
591
+ *
592
+ * @param text - The text to render (may contain \n and formatting tags)
593
+ * @param cx - Center x coordinate
594
+ * @param cy - Center y coordinate
595
+ * @param fontSize - Font size in pixels
596
+ * @param attrs - Additional SVG attributes (e.g., 'text-anchor="middle" fill="var(--_text)"')
597
+ * @param baselineShift - Baseline shift for vertical alignment (default 0.35)
598
+ * @returns SVG text element string
599
+ */
600
+ export declare function renderMultilineText(text: string, cx: number, cy: number, fontSize: number, attrs: string, baselineShift?: number): string;
601
+
602
+ /**
603
+ * Render a multi-line text element with a background rectangle (pill).
604
+ *
605
+ * Used for edge labels that need a background for readability.
606
+ *
607
+ * @param text - The text to render (may contain \n)
608
+ * @param cx - Center x coordinate
609
+ * @param cy - Center y coordinate
610
+ * @param textWidth - Pre-calculated text width (max line width)
611
+ * @param textHeight - Pre-calculated text height (lines × lineHeight)
612
+ * @param fontSize - Font size in pixels
613
+ * @param padding - Padding around text
614
+ * @param textAttrs - SVG attributes for the text element
615
+ * @param bgAttrs - SVG attributes for the background rect
616
+ * @returns SVG elements string (rect + text)
617
+ */
618
+ export declare function renderMultilineTextWithBackground(text: string, cx: number, cy: number, textWidth: number, textHeight: number, fontSize: number, padding: number, textAttrs: string, bgAttrs: string): string;
619
+
620
+ export declare interface RenderOptions {
621
+ /** Background color → CSS variable --bg. Default: '#FFFFFF' */
622
+ bg?: string;
623
+ /** Foreground / primary text color → CSS variable --fg. Default: '#27272A' */
624
+ fg?: string;
625
+ /** Edge/connector color → CSS variable --line */
626
+ line?: string;
627
+ /** Arrow heads, highlights → CSS variable --accent */
628
+ accent?: string;
629
+ /** Secondary text, edge labels → CSS variable --muted */
630
+ muted?: string;
631
+ /** Node/box fill tint → CSS variable --surface */
632
+ surface?: string;
633
+ /** Node/group stroke color → CSS variable --border */
634
+ border?: string;
635
+ /** Font family for all text. Default: 'Inter' */
636
+ font?: string;
637
+ /** Canvas padding in px. Default: 40. Flowchart/state diagrams only — class/ER diagrams use fixed internal padding. */
638
+ padding?: number;
639
+ /** Horizontal spacing between sibling nodes. Default: 28. Flowchart/state diagrams only — class/ER diagrams use fixed internal spacing. */
640
+ nodeSpacing?: number;
641
+ /** Vertical spacing between layers. Default: 48. Flowchart/state diagrams only — class/ER diagrams use fixed internal spacing. */
642
+ layerSpacing?: number;
643
+ /** Currently unused — accepted for forward compatibility but not read anywhere. */
644
+ componentSpacing?: number;
645
+ /** Whether to bundle overlapping fan-out/fan-in edge paths into shared trunks to reduce visual clutter. Default: true */
646
+ mergeEdges?: boolean;
647
+ /**
648
+ * Force the diagram's layout direction, overriding the one its source
649
+ * declares — a flowchart's `graph LR` / `flowchart TD` header, or a state
650
+ * diagram's / ER diagram's top-level `direction LR` line. Applied after
651
+ * parsing and before layout, so the source text is never rewritten and
652
+ * `parseMermaid()` output is unaffected.
653
+ *
654
+ * Replaces only the *top-level* direction. A nested subgraph's or
655
+ * composite state's own `direction` line still applies on top of this
656
+ * override, exactly as it does on top of the diagram's own header — the
657
+ * override behaves as if the caller had written that direction in the
658
+ * source header, nothing more.
659
+ *
660
+ * Flowchart, state, and ER diagrams only — the three diagram types that
661
+ * have a direction concept to override. Sequence, class, and XY-chart
662
+ * diagrams ignore it (no error; output is identical with or without it).
663
+ *
664
+ * Unset (the default) keeps the source's direction, so existing output is
665
+ * unchanged. See issue #276.
666
+ */
667
+ direction?: Direction;
668
+ /** Render with transparent background (no background style on SVG). Default: false */
669
+ transparent?: boolean;
670
+ /**
671
+ * Render-target-scoped interactivity level. Declarative only — this
672
+ * library never emits `<script>`; see
673
+ * docs/decisions/no-script-interactivity.md for the tier model this maps
674
+ * to (tier 1: `<title>`/text; tier 2: `<a href>`, CSS `:hover`, CSS
675
+ * animation; tier 3: `click ... call fn()`, recorded as data, never
676
+ * executed). Default: `'static'`.
677
+ *
678
+ * - `'none'` — strips flowchart/state-diagram edge animation
679
+ * (`e1@{ animate: true }`), and strips `click`-based links
680
+ * (`<a href>`) and `<title>` tooltips. Intended for print/rasterized
681
+ * output: a CSS `@keyframes` animation would otherwise silently
682
+ * render as a single static frame with no indication that motion
683
+ * was intended, and a link is meaningless once rasterized.
684
+ * - `'static'` — default. Tier 1 + tier 2 minus motion: `click`-based
685
+ * links and `<title>` tooltips still render, but flowchart/state-diagram
686
+ * edge animation does not — a diagram that opts into
687
+ * `e1@{ animate: true }` renders as a still line unless `'full'` is
688
+ * requested. xychart hover tooltips stay off unless requested via
689
+ * `'full'` or the deprecated `interactive: true` below. This is a
690
+ * breaking change from earlier releases, where `'static'` (and the
691
+ * default) still animated — animation is tier-2 *motion*, which the
692
+ * stricter `'static'` reading excludes; see the ADR.
693
+ * - `'full'` — also enables flowchart/state-diagram edge animation and
694
+ * xychart hover tooltips.
695
+ */
696
+ interactivity?: 'none' | 'static' | 'full';
697
+ /**
698
+ * @deprecated Use `interactivity` instead. Enable hover tooltips on chart
699
+ * data points (xychart only). Default: false.
700
+ *
701
+ * When `interactivity` is not set, this boolean still controls xychart
702
+ * tooltips as before (`true` behaves like `interactivity: 'full'` for
703
+ * that one effect). When `interactivity` *is* set, it takes precedence
704
+ * and this field is ignored.
705
+ */
706
+ interactive?: boolean;
707
+ /** Stamp the original diagram source onto the root `<svg>` as a `data-src` attribute (HTML-escaped). Default: false */
708
+ embedSource?: boolean;
709
+ /**
710
+ * Replace every CSS `var(--…)` and `color-mix(…)` in the output with its
711
+ * computed sRGB value (`#rrggbb`, or `rgba()` when translucent), using
712
+ * the same mix percentages the `<style>` block declares (see
713
+ * `MIX` in src/theme.ts — there is one table, not a copy). Default: false.
714
+ *
715
+ * Browsers evaluate both natively, so the default output stays a live
716
+ * function of its CSS custom properties (docs/theming.md). Rasterizers
717
+ * and non-browser SVG consumers — resvg, librsvg, Inkscape, ImageMagick —
718
+ * implement neither and render the whole theme as black; turn this on
719
+ * for any output headed to one of them (GitHub issue #456).
720
+ *
721
+ * Trade-off: the result is a fixed palette. Overriding `--bg`/`--fg` on
722
+ * the embedded SVG no longer restyles it, and passing a `var(...)`
723
+ * reference as a color (the React live-theming pattern) has nothing to
724
+ * resolve against — such references, and any `var()` this library did
725
+ * not declare itself (e.g. a host-page font variable), are left as-is.
726
+ */
727
+ resolveColors?: boolean;
728
+ /**
729
+ * CSP nonce to stamp on every `<style>` element in the output (see GitHub
730
+ * issue #216).
731
+ *
732
+ * The renderer styles its SVG with an inline `<style>` element (the theme
733
+ * block; flowcharts with `e1@{ animate: true }` edges and xycharts add a
734
+ * second one). A host page whose `Content-Security-Policy` has a
735
+ * `style-src` without `'unsafe-inline'` blocks those, and the diagram
736
+ * silently renders unstyled. The standard fix is a per-response nonce:
737
+ * the host generates one, lists it as `style-src 'nonce-<value>'`, and
738
+ * puts `nonce="<value>"` on each element it wants to allow. Pass that
739
+ * value here and every emitted `<style>` gets it — one `<style>` left
740
+ * un-nonced is enough to lose the whole diagram's styling, so this is
741
+ * applied at the single shared emission point rather than per diagram
742
+ * type.
743
+ *
744
+ * The value is attribute-escaped on output. An empty string is treated as
745
+ * unset. Default: undefined (no `nonce` attribute).
746
+ *
747
+ * A nonce only authorises `<style>` *elements* — it cannot authorise a
748
+ * `style="…"` *attribute* (browsers apply nonces to elements only), so the
749
+ * root `<svg style="--bg: …">` attribute stays blocked under the same
750
+ * policy. Pair this with `styleAttribute: false` and put the theme
751
+ * variables in your own stylesheet; see that option.
752
+ */
753
+ nonce?: string;
754
+ /**
755
+ * Emit the root `<svg style="--bg: …; --fg: …; background: var(--bg)">`
756
+ * attribute. Default: true.
757
+ *
758
+ * That attribute is how the theme colours reach the SVG: every rule in
759
+ * the embedded `<style>` block resolves against the `--bg`/`--fg`/…
760
+ * custom properties it sets. Under a strict `Content-Security-Policy`
761
+ * (`style-src` without `'unsafe-inline'`) the browser drops it, and no
762
+ * `nonce` can rescue it — nonces apply to elements, never attributes —
763
+ * so the diagram loses its colours even when the `<style>` element itself
764
+ * is allowed (see GitHub issue #216).
765
+ *
766
+ * Set this to `false` to leave the attribute out entirely. The host must
767
+ * then define the same custom properties on the SVG or an ancestor from
768
+ * its own (nonced or external) stylesheet; `themeCssVariables(options)`
769
+ * returns the exact declaration list the attribute would have carried,
770
+ * so the two can't drift:
771
+ *
772
+ * ```ts
773
+ * const opts = { bg: '#fff', fg: '#000', nonce, styleAttribute: false }
774
+ * const svg = renderMermaidSVG(code, opts)
775
+ * const css = `.diagram svg { ${themeCssVariables(opts)} }`
776
+ * // `<style nonce="…">${css}</style>` + `<div class="diagram">${svg}</div>`
777
+ * ```
778
+ *
779
+ * With the attribute gone, the SVG has no inline `background` either; the
780
+ * declarations from `themeCssVariables()` include it (unless
781
+ * `transparent`) so the host's rule restores it. Only the *root* `style`
782
+ * attribute is affected: a per-node `style A font-family:…` override
783
+ * still renders as that node's own `style` attribute, since it's diagram
784
+ * content rather than theming, and under such a CSP it is simply ignored
785
+ * by the browser. `nonce` and this option are independent — a host using
786
+ * hashes rather than nonces may want only this one.
787
+ */
788
+ styleAttribute?: boolean;
789
+ /**
790
+ * Accessible name for the rendered SVG (see GitHub issue #215). Rendered
791
+ * as `role="img"` + `aria-labelledby` pointing at a `<title>` child
792
+ * holding this text — the standard SVG/WAI-ARIA technique for naming an
793
+ * inline image. Without a name, assistive tech either treats the SVG as a
794
+ * plain group (every node/edge label announced individually, out of
795
+ * reading order) or skips it — a WCAG 1.1.1 failure for diagrams embedded
796
+ * in a page.
797
+ *
798
+ * Supply your own description of what the diagram shows (e.g. "Flowchart:
799
+ * Build → Test → Ship") — this library does not auto-generate one, since a
800
+ * fabricated summary like "flowchart with 3 nodes" would be a confidently
801
+ * useless accessible name. When omitted, the SVG still gets `role="img"`
802
+ * (so it's read as one image, not a leaky group) but claims no name — the
803
+ * same as an `<img>` with no `alt`.
804
+ *
805
+ * Ignored when `decorative` is true. Default: undefined (no name).
806
+ *
807
+ * If the diagram has a `click A "url"` link, `role="img"` is never
808
+ * applied regardless of this option — see `decorative` below.
809
+ */
810
+ title?: string;
811
+ /**
812
+ * Mark the diagram as decorative — already described in surrounding
813
+ * prose, so it shouldn't be announced as its own image. Emits
814
+ * `aria-hidden="true"` on the root `<svg>` instead of
815
+ * `role`/`aria-labelledby`/`<title>`; `title`, if also given, is ignored.
816
+ * Default: false
817
+ *
818
+ * Silently overridden (no `aria-hidden`) if the diagram has any
819
+ * `click A "url"` link: that renders as a real, focusable `<a href>`
820
+ * inside the SVG, and `aria-hidden="true"` on an ancestor of a focusable
821
+ * element is an explicit WAI-ARIA violation — assistive tech would drop
822
+ * the link from the accessibility tree while it stays reachable by Tab.
823
+ * `title`, if also given, still applies in that case (see #239).
824
+ */
825
+ decorative?: boolean;
826
+ /**
827
+ * Edge path interpolation for flowcharts and state diagrams.
828
+ * Default: 'linear'. A diagram's own
829
+ * `%%{init: {"flowchart": {"curve": ...}}}%%` supplies this when the caller
830
+ * does not; an explicit value here always wins.
831
+ */
832
+ curve?: CurveStyle;
833
+ /**
834
+ * Font size overrides (px). Fields left unspecified fall back to their
835
+ * default. Applies to all diagram types (flowchart, sequence, class, ER).
836
+ */
837
+ fontSizes?: {
838
+ /** Node label text. Default: 13 */
839
+ nodeLabel?: number;
840
+ /** Edge label text. Default: 11 */
841
+ edgeLabel?: number;
842
+ /** Subgraph header text. Default: 12 */
843
+ groupHeader?: number;
844
+ };
845
+ /**
846
+ * Sequence-diagram layout overrides (px). Fields left unspecified fall
847
+ * back to their default. Sequence diagrams only.
848
+ */
849
+ sequence?: {
850
+ /** Vertical space per message row. Default: 40 */
851
+ messageRowHeight?: number;
852
+ /** Vertical space between actor boxes and the first message. Default: 20 */
853
+ headerGap?: number;
854
+ /** Actor box height. Default: 40 */
855
+ actorHeight?: number;
856
+ /** Gap between a message arrow and a note positioned directly after it. Default: 8 */
857
+ noteOffsetAfterMessage?: number;
858
+ /** Gap between consecutively stacked notes. Default: 4 */
859
+ noteStackGap?: number;
860
+ };
861
+ /**
862
+ * Opt-in ELK layout cache (see `createLayoutCache()`). When set,
863
+ * `layoutGraphSync()` / `layoutClassDiagramSync()` / `layoutErDiagramSync()`
864
+ * (flowchart/state, class, and ER diagrams — the ELK-based layout
865
+ * engines) skip re-running ELK layout on a cache hit, keyed on a
866
+ * deterministic serialization of the fully-resolved ELK input graph
867
+ * (diagram structure + every layout-affecting option already baked in).
868
+ *
869
+ * Unset (the default) preserves the original always-recompute behavior
870
+ * exactly — this cache is entirely opt-in. Create one instance and
871
+ * reuse it across renders (e.g. module scope, or a `useRef` in React);
872
+ * passing a freshly-created cache on every call defeats the point,
873
+ * since it starts empty each time.
874
+ */
875
+ layoutCache?: LayoutCache;
876
+ }
877
+
878
+ /**
879
+ * Resolve the final inline style for a node from classDefs and nodeStyles.
880
+ *
881
+ * Cascade, weakest to strongest:
882
+ * 1. `classDef default` — Mermaid's implicit base for every node
883
+ * 2. the node's own assigned class (`class A foo` / `A:::foo`)
884
+ * 3. an explicit `style A ...` directive
885
+ *
886
+ * Returns undefined when nothing in the cascade applies, so callers can fall
887
+ * back to theme defaults without an empty-object check.
888
+ */
889
+ export declare function resolveNodeStyle(nodeId: string, directives: StyleDirectives): Record<string, string> | undefined;
890
+
891
+ /** An sRGB color: 0-255 channels plus a 0-1 alpha. */
892
+ export declare interface RgbaColor {
893
+ r: number;
894
+ g: number;
895
+ b: number;
896
+ a: number;
897
+ }
898
+
899
+ /**
900
+ * Accept only link schemes that cannot execute script.
901
+ *
902
+ * A `click` target comes from diagram text, which may be untrusted. An
903
+ * `href` of `javascript:...` (or a `data:` URL containing markup) would turn
904
+ * a rendered diagram into an XSS vector for any page that inlines the SVG, so
905
+ * anything but http/https/mailto and same-document or relative references is
906
+ * dropped rather than emitted.
907
+ *
908
+ * C0 controls are rejected outright, before any other check. The URL parser
909
+ * strips tab and newline from *anywhere* in a URL, so `java\tscript:` reaches
910
+ * a browser as `javascript:` — while the scheme match below sees `java\t…`,
911
+ * finds no scheme, and waves it through as a relative reference. Splitting a
912
+ * blocked scheme with a control character is the whole bypass; there is no
913
+ * legitimate URL with a raw control in it, so the entire range goes.
914
+ */
915
+ export declare function safeHref(href: string | undefined): string | undefined;
916
+
917
+ /**
918
+ * Validate a user-authored class name (from `:::className` or
919
+ * `class A className`) before it's emitted into the SVG `class` attribute.
920
+ *
921
+ * The parsers already constrain class names to word characters and hyphens
922
+ * (see `splitClassShorthand` above and the flowchart parser's
923
+ * CLASS_SHORTHAND_REGEX), so this is a defense-in-depth allowlist rather
924
+ * than an escaping step — a class name can't be made "safe" by escaping
925
+ * since any character other than a valid CSS identifier character would
926
+ * break the class token itself, not just the surrounding attribute quotes.
927
+ * Anything that doesn't match a valid CSS identifier (letters, digits,
928
+ * underscore, hyphen; not starting with a digit or a hyphen+digit) is
929
+ * dropped rather than emitted.
930
+ */
931
+ export declare function sanitizeClassName(className: string | undefined): string | undefined;
932
+
933
+ /**
934
+ * Options applicable to sequence diagrams (`sequenceDiagram`). Sequence
935
+ * diagrams ignore `direction`, `curve`, spacing/`layoutCache` (a
936
+ * non-ELK layout), and `interactivity` (no animated edges or `click` links
937
+ * in this renderer's sequence support).
938
+ */
939
+ export declare type SequenceRenderOptions = CommonRenderOptions & Pick<RenderOptions, 'fontSizes' | 'sequence'>;
940
+
941
+ /** Select the metrics model for subsequent measurements. Called once per render. */
942
+ export declare function setMonospaceMetrics(monospace: boolean): void;
943
+
944
+ /**
945
+ * Minimal subset of Shiki's ThemeRegistrationResolved that we need.
946
+ * We don't import from shiki to avoid a hard dependency.
947
+ */
948
+ declare interface ShikiThemeLike {
949
+ type?: string;
950
+ colors?: Record<string, string>;
951
+ tokenColors?: Array<{
952
+ scope?: string | string[];
953
+ settings?: {
954
+ foreground?: string;
955
+ };
956
+ }>;
957
+ }
958
+
959
+ /**
960
+ * Split the `:::className` shorthand off a node/class identifier.
961
+ *
962
+ * `Animal:::someclass` → `{ id: 'Animal', className: 'someclass' }`;
963
+ * an identifier without the shorthand comes back unchanged with no class.
964
+ * Class names follow CSS identifier conventions (word characters and
965
+ * hyphens), the same constraint the flowchart parser's CLASS_SHORTHAND_REGEX
966
+ * applies.
967
+ */
968
+ export declare function splitClassShorthand(identifier: string): {
969
+ id: string;
970
+ className?: string;
971
+ };
972
+
973
+ /**
974
+ * Split Mermaid source into trimmed statements, dropping blank lines and
975
+ * `%%` comment lines. See `splitStatementsByLine` for the line-grouped form
976
+ * this flattens.
977
+ */
978
+ export declare function splitStatements(text: string): Statement[];
979
+
980
+ /**
981
+ * Split Mermaid source into trimmed statements, grouped by the physical
982
+ * source line each one came from — dropping blank lines and `%%` comment
983
+ * lines.
984
+ *
985
+ * Newlines and semicolons both separate statements, matching Mermaid's own
986
+ * `graph TD; A-->B;` form. Comments are removed *before* semicolon splitting
987
+ * so that a `;` inside a comment can't resurrect the rest of that line as
988
+ * code.
989
+ *
990
+ * The grouping is what lets a caller tell a genuine multi-line continuation
991
+ * (crossing from one line's group into the next) apart from an explicit
992
+ * `;`-separated statement on the *same* line (a later entry within one
993
+ * group) — see `src/parser.ts`'s `mergeContinuationLines`, which only
994
+ * treats the former as mergeable.
995
+ */
996
+ export declare function splitStatementsByLine(text: string): Statement[][];
997
+
998
+ /**
999
+ * One statement produced by the splitter, paired with the 1-based physical
1000
+ * source line it came from.
1001
+ *
1002
+ * `line` is captured while walking `text.split('\n')`, before blank lines
1003
+ * and `%%` comment lines are dropped — so it survives being the original
1004
+ * source line number even though a statement's array index no longer does.
1005
+ * This is what lets every parser built on top of `splitStatements`/
1006
+ * `splitStatementsByLine` report *where* an error is, not just quote back
1007
+ * the offending statement's text (see issue #760).
1008
+ */
1009
+ export declare interface Statement {
1010
+ text: string;
1011
+ line: number;
1012
+ }
1013
+
1014
+ /**
1015
+ * Strip all inline formatting tags from text, keeping only plain text.
1016
+ * Used for text measurement where tag characters shouldn't affect width.
1017
+ */
1018
+ export declare function stripFormattingTags(text: string): string;
1019
+
1020
+ /** The three maps a styling-aware diagram carries. `MermaidGraph` and
1021
+ * `ClassDiagram` both satisfy this structurally. */
1022
+ export declare interface StyleDirectives {
1023
+ /** Maps class names to their style properties (from `classDef name prop:val`) */
1024
+ classDefs: Map<string, Record<string, string>>;
1025
+ /** Maps node IDs to their assigned class name (from `class A,B name`, `cssClass "A,B" name`, or `A:::name`) */
1026
+ classAssignments: Map<string, string>;
1027
+ /** Maps node IDs to inline styles (from `style X fill:#f00,stroke:#333`) */
1028
+ nodeStyles: Map<string, Record<string, string>>;
1029
+ }
1030
+
1031
+ /**
1032
+ * The opening `<style>` tag every renderer uses — with a `nonce` attribute
1033
+ * when the caller supplied one (see `RenderOptions.nonce`, #216).
1034
+ *
1035
+ * All `<style>` emission points go through this one function so a nonce
1036
+ * can't be missed on one of them: under a nonce-based CSP a single
1037
+ * un-nonced `<style>` is silently dropped by the browser, which for the
1038
+ * theme block means an unstyled diagram with no console hint as to why.
1039
+ *
1040
+ * An empty/whitespace-only nonce is treated as unset — `nonce=""` would
1041
+ * authorise nothing and only mislead a reader into thinking it did.
1042
+ * The value is attribute-escaped; a real nonce is base64 and never needs
1043
+ * escaping, but the option is a plain string and this keeps a stray `"`
1044
+ * from breaking out of the attribute.
1045
+ */
1046
+ export declare function styleOpenTag(nonce?: string): string;
1047
+
1048
+ /**
1049
+ * How the renderers emit their two inline-style surfaces — the `<style>`
1050
+ * element(s) and the root `<svg style="--bg: …">` attribute. Both exist so a
1051
+ * host page with a strict `Content-Security-Policy` (`style-src` without
1052
+ * `'unsafe-inline'`) can still render diagrams with their colours intact;
1053
+ * see `RenderOptions.nonce` / `RenderOptions.styleAttribute` in packages/core/src/types.ts
1054
+ * and GitHub issue #216. Threaded as one object through every diagram
1055
+ * renderer so the two options can't drift apart per diagram type.
1056
+ */
1057
+ export declare interface SvgEmitOptions {
1058
+ /** Value for a `nonce` attribute on every emitted `<style>` element. */
1059
+ nonce?: string;
1060
+ /** Emit the root `style="--bg: …"` attribute. Default: true. */
1061
+ styleAttribute?: boolean;
1062
+ }
1063
+
1064
+ /**
1065
+ * Build the SVG opening tag with CSS variables set as inline styles.
1066
+ * Only includes optional variables that are actually provided — unset ones
1067
+ * will fall back to the color-mix() derivations in the <style> block.
1068
+ *
1069
+ * `styleAttribute: false` drops the `style="…"` attribute entirely (the
1070
+ * host supplies those declarations from its own stylesheet — see
1071
+ * `themeStyleDeclarations()` and `RenderOptions.styleAttribute`, #216).
1072
+ * Every other attribute — `xmlns`, `viewBox`, `width`/`height`, the
1073
+ * `role`/`aria-*` accessibility attributes, and anything a caller splices
1074
+ * on afterwards (`data-src`, `data-xychart-colors`) — is unaffected.
1075
+ *
1076
+ * Also handles the SVG's accessible name (see `RenderOptions.title` /
1077
+ * `RenderOptions.decorative` in packages/core/src/types.ts, and GitHub issue #215):
1078
+ *
1079
+ * - `decorative: true` → `aria-hidden="true"` on the root, no `role` or
1080
+ * name. Use for a diagram already described in surrounding prose; `title`
1081
+ * is ignored when this is set.
1082
+ * - `title` given (and not decorative) → `role="img"` +
1083
+ * `aria-labelledby="zm-title-N"` on the root, plus a `<title id="zm-title-N">`
1084
+ * as the SVG's first child holding the escaped text. This is the standard
1085
+ * SVG/WAI-ARIA "accessible name via a referenced title element" technique
1086
+ * (see MDN "SVG accessibility" and the WAI-ARIA `img` role: an element
1087
+ * with `role="img"` needs a computed accessible name to be meaningful to
1088
+ * assistive tech; `aria-labelledby` pointing at a `<title>` is the
1089
+ * documented way to supply one for inline SVG).
1090
+ * - Neither given → `role="img"` only, no name. This still stops assistive
1091
+ * tech from treating the SVG as a plain group (which announces every
1092
+ * node/edge label individually, out of reading order — the core bug in
1093
+ * #215), without fabricating a name the library can't honestly claim. It
1094
+ * reads the same as an `<img>` with no `alt`: present as a single image,
1095
+ * unlabeled.
1096
+ *
1097
+ * `hasInteractiveLinks` overrides all of the above (see #239): a `click A
1098
+ * "url"` statement renders a real, focusable `<a href>` inside the SVG, and
1099
+ * both `role="img"` and `aria-hidden="true"` are unsafe on an ancestor of a
1100
+ * focusable element — `role="img"` tells assistive tech to stop descending
1101
+ * into children (the link becomes unreachable by screen reader while still
1102
+ * Tab-focusable), and `aria-hidden="true"` on a focusable descendant is an
1103
+ * explicit WAI-ARIA violation (the link vanishes from the accessibility tree
1104
+ * but not from the tab order). When any node has a link, the root gets no
1105
+ * `role` at all — `decorative` is silently overridden rather than honored,
1106
+ * since aria-hiding a diagram that contains an actionable link is not a safe
1107
+ * request to fulfill — but `title`/`aria-labelledby` still apply if given:
1108
+ * an accessible name is still valid on an element with no explicit role.
1109
+ *
1110
+ * The per-node/per-point `<title>` tooltips added by earlier work (nested
1111
+ * inside `<g>` elements, with no `id` attribute) are unaffected: they never
1112
+ * collide with the root title's generated id, and a root `<title>` alongside
1113
+ * unrelated descendant `<title>` elements is valid SVG.
1114
+ *
1115
+ * @param transparent - If true, omits the background style for transparent SVGs
1116
+ * @param title - Accessible name text. Ignored when `decorative` is true
1117
+ * and there are no interactive links (see `hasInteractiveLinks`).
1118
+ * @param decorative - Marks the SVG as decorative (`aria-hidden="true"`).
1119
+ * Overridden when `hasInteractiveLinks` is true.
1120
+ * @param hasInteractiveLinks - True if any node has a `click`-based `href`.
1121
+ * See #239 — forces no root `role` so the link
1122
+ * stays reachable, regardless of `decorative`.
1123
+ * @param styleAttribute - Emit the root `style="…"` attribute. Default true.
1124
+ */
1125
+ export declare function svgOpenTag(width: number, height: number, colors: DiagramColors, transparent?: boolean, title?: string, decorative?: boolean, hasInteractiveLinks?: boolean, styleAttribute?: boolean): string;
1126
+
1127
+ export declare type ThemeName = keyof typeof THEMES;
1128
+
1129
+ export declare const THEMES: Record<string, DiagramColors>;
1130
+
1131
+ /**
1132
+ * The exact CSS declaration list the root `<svg style="…">` attribute
1133
+ * carries: the theme custom properties (`--bg`, `--fg`, plus whichever
1134
+ * enrichment variables were actually provided — unset ones fall back to the
1135
+ * color-mix() derivations in the `<style>` block) and, unless `transparent`,
1136
+ * a `background: var(--bg)`.
1137
+ *
1138
+ * Exposed (via `themeCssVariables()` in src/index.ts) so a host that turns
1139
+ * the attribute off with `styleAttribute: false` — because its
1140
+ * Content-Security-Policy forbids `style=` attributes, which a nonce can
1141
+ * never authorise (#216) — can put the very same declarations in its own
1142
+ * stylesheet on a wrapper instead. Single source of truth for the variable
1143
+ * list: `svgOpenTag()` and the helper both call this, so the two can't
1144
+ * drift.
1145
+ *
1146
+ * Emitted compactly (`--bg:#fff;--fg:#000;background:var(--bg)`) rather
1147
+ * than pretty-printed: it's the same string the attribute has always
1148
+ * carried, so default output stays byte-identical. Colour values are the
1149
+ * caller's own `RenderOptions` and are not escaped here — same as before.
1150
+ */
1151
+ export declare function themeStyleDeclarations(colors: DiagramColors, transparent?: boolean): string;
1152
+
1153
+ /**
1154
+ * Normalize a regex-captured direction token to a `Direction`.
1155
+ *
1156
+ * Accepts `string | undefined` because every call site passes a regex
1157
+ * capture group value (`match[1]`, typed as possibly-`undefined` under
1158
+ * `noUncheckedIndexedAccess`) straight through. Each call site's regex
1159
+ * guards the capture with the same `(TD|TB|LR|BT|RL)` alternation
1160
+ * (case-insensitively), so the group always participates in the match in
1161
+ * practice — but that's a regex-structure guarantee the type checker can't
1162
+ * see across the call site. Validating `undefined` here, instead of
1163
+ * asserting non-null at each call site, turns a hypothetical violation into
1164
+ * a clear, descriptive error rather than a raw `undefined` crash.
1165
+ */
1166
+ export declare function toDirection(raw: string | undefined): Direction;
1167
+
1168
+ /**
1169
+ * `class A,B className` — attach a style class to one or more nodes.
1170
+ *
1171
+ * Allows an optional trailing semicolon (`class A,B foo;`) — Mermaid treats
1172
+ * it as valid/optional, and `classDef`/`style` already tolerate it via their
1173
+ * `(.+)$` capture. Without this, the semicolon form fails to match here and
1174
+ * falls through to node parsing, rendering a stray node labelled "class".
1175
+ *
1176
+ * Returns true when `line` was a class-assignment statement.
1177
+ */
1178
+ export declare function tryApplyClassAssignment(line: string, target: StyleDirectives): boolean;
1179
+
1180
+ /**
1181
+ * `classDef name prop:val,prop:val` — define a named style class.
1182
+ *
1183
+ * Mermaid's `classList` rule accepts a comma-separated list of names
1184
+ * (`classDef a,b font-size:12pt`) in both the flowchart and class grammars;
1185
+ * every name in the list gets the same properties.
1186
+ *
1187
+ * Returns true when `line` was a classDef statement (and has been applied).
1188
+ */
1189
+ export declare function tryApplyClassDef(line: string, target: StyleDirectives): boolean;
1190
+
1191
+ /**
1192
+ * `cssClass "A,B" className` — the class-diagram grammar's own attachment
1193
+ * form (`cssClassStatement: CSSCLASS STR ALPHA` in classDiagram.jison).
1194
+ * Same effect as `class A,B className`.
1195
+ *
1196
+ * Returns true when `line` was a cssClass statement.
1197
+ */
1198
+ export declare function tryApplyCssClass(line: string, target: StyleDirectives): boolean;
1199
+
1200
+ /**
1201
+ * `style A,B fill:#f00,stroke:#333` — inline style on specific nodes.
1202
+ * Repeated `style` statements for the same node merge property by property.
1203
+ *
1204
+ * Returns true when `line` was a style statement.
1205
+ */
1206
+ export declare function tryApplyStyleStatement(line: string, target: StyleDirectives): boolean;
1207
+
1208
+ /**
1209
+ * Return `diagram` with its top-level `direction` replaced by `override`,
1210
+ * or `diagram` itself (same reference) when there is nothing to apply.
1211
+ *
1212
+ * The parsed diagram is never mutated — a shallow clone carries the new
1213
+ * direction, so `parseMermaid()` output a caller holds on to stays exactly
1214
+ * what the parser produced, and a second render of the same parsed object
1215
+ * without the option sees the source direction again.
1216
+ *
1217
+ * `isDirection` re-checks the value at runtime because `Direction` is only
1218
+ * a compile-time guarantee: a plain-JavaScript caller can pass any string.
1219
+ * An unrecognized value is ignored (the diagram's own direction stands)
1220
+ * rather than thrown on — the same lenient treatment every other
1221
+ * `RenderOptions` value gets, e.g. an unknown `interactivity` or `curve`
1222
+ * string falls back to its default instead of failing the render.
1223
+ */
1224
+ export declare function withDirectionOverride<T extends {
1225
+ direction?: Direction;
1226
+ }>(diagram: T, override: Direction | undefined): T;
1227
+
1228
+ /**
1229
+ * Options applicable to XY charts (`xychart-beta`). XY charts have no
1230
+ * spacing/`direction`/`curve`/`fontSizes`/`layoutCache` concept (layout is
1231
+ * a fixed pixel computation, not ELK-based); `interactivity` (preferred) and
1232
+ * the deprecated `interactive` boolean both gate hover tooltips only.
1233
+ */
1234
+ export declare type XyChartRenderOptions = CommonRenderOptions & Pick<RenderOptions, 'interactivity' | 'interactive'>;
1235
+
1236
+ export { }