zombie-mermaid 1.4.0 → 1.5.0

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.
package/README.md CHANGED
@@ -6,11 +6,14 @@
6
6
 
7
7
  Ultra-fast, fully themeable, zero DOM dependencies. A maintained fork of [`beautiful-mermaid`](https://github.com/lukilabs/beautiful-mermaid).
8
8
 
9
- ![zombie-mermaid sequence diagram example](hero.png)
9
+ ![Raw Mermaid source rendering into a themed, animated diagram, drawn by zombie-mermaid itself](hero.svg)
10
10
 
11
- [**Live demo →**](https://dfadler.github.io/zombie-mermaid/)
11
+ [![Live Demo](https://img.shields.io/badge/Live_Demo-view_the_sample_gallery-1f6feb?style=for-the-badge)](https://dfadler.github.io/zombie-mermaid/)
12
12
 
13
13
  [![npm version](https://img.shields.io/npm/v/zombie-mermaid.svg)](https://www.npmjs.com/package/zombie-mermaid)
14
+ [![CI](https://github.com/dfadler/zombie-mermaid/actions/workflows/ci.yml/badge.svg)](https://github.com/dfadler/zombie-mermaid/actions/workflows/ci.yml)
15
+ [![codecov](https://codecov.io/gh/dfadler/zombie-mermaid/branch/main/graph/badge.svg)](https://codecov.io/gh/dfadler/zombie-mermaid)
16
+ [![Socket Security](https://socket.dev/api/badge/npm/package/zombie-mermaid)](https://socket.dev/npm/package/zombie-mermaid)
14
17
  [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
15
18
 
16
19
  </div>
@@ -145,11 +148,3 @@ Thank you Alexander for the excellent foundation!
145
148
  ## License
146
149
 
147
150
  MIT — see [LICENSE](LICENSE) for details.
148
-
149
- ---
150
-
151
- <div align="center">
152
-
153
- Built with care by the team at [Craft](https://craft.do)
154
-
155
- </div>
package/dist/cli.js CHANGED
@@ -800,13 +800,8 @@ function parseFlowchart(lines) {
800
800
  applyClickStatement(line, graph);
801
801
  continue;
802
802
  }
803
- const edgeMetaMatch = line.match(/^([\w-]+)(?=@\{)/);
804
- if (edgeMetaMatch && graph.edges.some((e) => e.id === edgeMetaMatch[1])) {
805
- const block = matchExpandedBlock(line.slice(edgeMetaMatch[1].length));
806
- if (block) {
807
- applyEdgeMeta(graph, edgeMetaMatch[1], parseExpandedMeta(block.body));
808
- continue;
809
- }
803
+ if (tryApplyEdgeMetaLine(line, graph)) {
804
+ continue;
810
805
  }
811
806
  const linkStyleMatch = line.match(/^linkStyle\s+(default|[\d,\s]+)\s+(.+)$/);
812
807
  if (linkStyleMatch) {
@@ -920,6 +915,9 @@ function parseStateDiagram(lines) {
920
915
  }
921
916
  continue;
922
917
  }
918
+ if (tryApplyEdgeMetaLine(line, graph)) {
919
+ continue;
920
+ }
923
921
  const compositeMatch = line.match(
924
922
  /^state\s+(?:"([^"]+)"\s+as\s+)?([\w\p{L}]+)\s*\{$/u
925
923
  );
@@ -953,10 +951,11 @@ function parseStateDiagram(lines) {
953
951
  continue;
954
952
  }
955
953
  const transitionMatch = line.match(
956
- /^(\[\*\]|[\w\p{L}-]+)\s*(-->)\s*(\[\*\]|[\w\p{L}-]+)(?:\s*:\s*(.+))?$/u
954
+ /^(\[\*\]|[\w\p{L}-]+)\s*(?:([\w-]+)@)?-->\s*(\[\*\]|[\w\p{L}-]+)(?:\s*:\s*(.+))?$/u
957
955
  );
958
956
  if (transitionMatch) {
959
957
  let sourceId = transitionMatch[1];
958
+ const edgeId = transitionMatch[2];
960
959
  let targetId = transitionMatch[3];
961
960
  const rawTransitionLabel = transitionMatch[4]?.trim();
962
961
  const edgeLabel = rawTransitionLabel ? normalizeBrTags(rawTransitionLabel) : void 0;
@@ -988,7 +987,8 @@ function parseStateDiagram(lines) {
988
987
  label: edgeLabel,
989
988
  style: "solid",
990
989
  hasArrowStart: false,
991
- hasArrowEnd: true
990
+ hasArrowEnd: true,
991
+ ...edgeId !== void 0 ? { id: edgeId } : {}
992
992
  });
993
993
  continue;
994
994
  }
@@ -1162,6 +1162,17 @@ function applyClickStatement(line, graph) {
1162
1162
  graph.interactions.set(nodeId, interaction);
1163
1163
  }
1164
1164
  }
1165
+ var EDGE_META_ID_REGEX = /^([\w-]+)(?=@\{)/;
1166
+ function tryApplyEdgeMetaLine(line, graph) {
1167
+ const edgeMetaMatch = line.match(EDGE_META_ID_REGEX);
1168
+ if (!edgeMetaMatch || !graph.edges.some((e) => e.id === edgeMetaMatch[1])) {
1169
+ return false;
1170
+ }
1171
+ const block = matchExpandedBlock(line.slice(edgeMetaMatch[1].length));
1172
+ if (!block) return false;
1173
+ applyEdgeMeta(graph, edgeMetaMatch[1], parseExpandedMeta(block.body));
1174
+ return true;
1175
+ }
1165
1176
  function applyEdgeMeta(graph, edgeId, meta) {
1166
1177
  for (const edge of graph.edges) {
1167
1178
  if (edge.id !== edgeId) continue;
@@ -1623,7 +1634,12 @@ function getReadableTextColor(fill, fallback) {
1623
1634
  const luminance = perceptualLuminance(...rgb);
1624
1635
  return luminance > 0.5 ? "#000000" : "#FFFFFF";
1625
1636
  }
1626
- function svgOpenTag(width, height, colors, transparent) {
1637
+ var titleIdCounter = 0;
1638
+ function nextTitleId() {
1639
+ titleIdCounter += 1;
1640
+ return `zm-title-${titleIdCounter}`;
1641
+ }
1642
+ function svgOpenTag(width, height, colors, transparent, title, decorative, hasInteractiveLinks) {
1627
1643
  const vars = [
1628
1644
  `--bg:${colors.bg}`,
1629
1645
  `--fg:${colors.fg}`,
@@ -1634,7 +1650,27 @@ function svgOpenTag(width, height, colors, transparent) {
1634
1650
  colors.border ? `--border:${colors.border}` : ""
1635
1651
  ].filter(Boolean).join(";");
1636
1652
  const bgStyle = transparent ? "" : ";background:var(--bg)";
1637
- return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}" width="${width}" height="${height}" style="${vars}${bgStyle}">`;
1653
+ let a11yAttrs = "";
1654
+ let titleEl = "";
1655
+ if (hasInteractiveLinks) {
1656
+ if (title) {
1657
+ const id = nextTitleId();
1658
+ a11yAttrs = ` aria-labelledby="${id}"`;
1659
+ titleEl = `
1660
+ <title id="${id}">${escapeXml(title)}</title>`;
1661
+ }
1662
+ } else if (decorative) {
1663
+ a11yAttrs = ' aria-hidden="true"';
1664
+ } else {
1665
+ a11yAttrs = ' role="img"';
1666
+ if (title) {
1667
+ const id = nextTitleId();
1668
+ a11yAttrs += ` aria-labelledby="${id}"`;
1669
+ titleEl = `
1670
+ <title id="${id}">${escapeXml(title)}</title>`;
1671
+ }
1672
+ }
1673
+ return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}" width="${width}" height="${height}"${a11yAttrs} style="${vars}${bgStyle}">` + titleEl;
1638
1674
  }
1639
1675
 
1640
1676
  // src/ascii/ansi.ts
@@ -1908,19 +1944,44 @@ function colorizeText(text, hex, mode) {
1908
1944
 
1909
1945
  // src/ascii/display-width.ts
1910
1946
  var WIDE_CHAR_PLACEHOLDER = "";
1911
- function charDisplayWidth(char) {
1912
- return isWideChar(char) ? 2 : 1;
1947
+ var COMBINING_MARK_REGEX = /\p{Mn}|\p{Me}/u;
1948
+ function isCombiningMark2(char) {
1949
+ return COMBINING_MARK_REGEX.test(char);
1950
+ }
1951
+ var graphemeSegmenter = new Intl.Segmenter(void 0, {
1952
+ granularity: "grapheme"
1953
+ });
1954
+ function graphemeClusters(text) {
1955
+ const clusters = [];
1956
+ for (const { segment } of graphemeSegmenter.segment(text)) {
1957
+ clusters.push(segment);
1958
+ }
1959
+ return clusters;
1960
+ }
1961
+ function charDisplayWidth(cluster) {
1962
+ let sawWide = false;
1963
+ let sawNonMark = false;
1964
+ for (const ch of cluster) {
1965
+ if (isWideChar(ch)) sawWide = true;
1966
+ if (!isCombiningMark2(ch)) sawNonMark = true;
1967
+ }
1968
+ if (sawWide) return 2;
1969
+ return sawNonMark ? 1 : 0;
1913
1970
  }
1914
1971
  function displayWidth(text) {
1915
1972
  let width = 0;
1916
- for (const ch of text) width += charDisplayWidth(ch);
1973
+ for (const cluster of graphemeClusters(text)) {
1974
+ width += charDisplayWidth(cluster);
1975
+ }
1917
1976
  return width;
1918
1977
  }
1919
1978
  function toDisplayCells(text) {
1920
1979
  const cells = [];
1921
- for (const ch of text) {
1922
- cells.push(ch);
1923
- if (isWideChar(ch)) cells.push(WIDE_CHAR_PLACEHOLDER);
1980
+ for (const cluster of graphemeClusters(text)) {
1981
+ const width = charDisplayWidth(cluster);
1982
+ if (width === 0) continue;
1983
+ cells.push(cluster);
1984
+ if (width === 2) cells.push(WIDE_CHAR_PLACEHOLDER);
1924
1985
  }
1925
1986
  return cells;
1926
1987
  }
@@ -2278,10 +2339,28 @@ var Grid = class {
2278
2339
  add(key) {
2279
2340
  this.#cells.add(key);
2280
2341
  }
2342
+ /**
2343
+ * Release a single cell. For temporary reservations only (see
2344
+ * `rerouteAroundStyleConflicts` in grid.ts) — every other reservation in
2345
+ * this module (node blocks, in particular) is permanent for the life of
2346
+ * a render, so a real caller should rarely need this.
2347
+ */
2348
+ delete(key) {
2349
+ this.#cells.delete(key);
2350
+ }
2351
+ /** Iterate the reserved cell keys. Read-only — see `cloneGrid`. */
2352
+ keys() {
2353
+ return this.#cells.keys();
2354
+ }
2281
2355
  };
2282
2356
  function createGrid() {
2283
2357
  return new Grid();
2284
2358
  }
2359
+ function cloneGrid(grid) {
2360
+ const clone = createGrid();
2361
+ for (const key of grid.keys()) clone.add(key);
2362
+ return clone;
2363
+ }
2285
2364
  var NODE_BLOCK_SIZE = 3;
2286
2365
  function isOccupied(grid, coord) {
2287
2366
  return grid.has(gridKey(coord));
@@ -2313,6 +2392,42 @@ function placeBlock(grid, origin, size = NODE_BLOCK_SIZE) {
2313
2392
  }
2314
2393
  }
2315
2394
  }
2395
+ var MAX_WALK_STEPS = 1e5;
2396
+ function pathCells(path) {
2397
+ if (path.length === 0) return [];
2398
+ const cells = [path[0]];
2399
+ for (let i = 1; i < path.length; i++) {
2400
+ const from = path[i - 1];
2401
+ const to = path[i];
2402
+ let x = from.x;
2403
+ let y = from.y;
2404
+ const absDx = Math.abs(to.x - from.x);
2405
+ const absDy = Math.abs(to.y - from.y);
2406
+ const sx = from.x < to.x ? 1 : -1;
2407
+ const sy = from.y < to.y ? 1 : -1;
2408
+ let err = absDx - absDy;
2409
+ let steps = 0;
2410
+ while (x !== to.x || y !== to.y) {
2411
+ if (steps >= MAX_WALK_STEPS) {
2412
+ throw new Error(
2413
+ `pathCells: segment from (${from.x},${from.y}) to (${to.x},${to.y}) did not reach its endpoint within ${MAX_WALK_STEPS} steps`
2414
+ );
2415
+ }
2416
+ const e2 = 2 * err;
2417
+ if (e2 > -absDy) {
2418
+ err -= absDy;
2419
+ x += sx;
2420
+ }
2421
+ if (e2 < absDx) {
2422
+ err += absDx;
2423
+ y += sy;
2424
+ }
2425
+ cells.push({ x, y });
2426
+ steps++;
2427
+ }
2428
+ }
2429
+ return cells;
2430
+ }
2316
2431
 
2317
2432
  // src/ascii/converter.ts
2318
2433
  function convertToAsciiGraph(parsed, config) {
@@ -3128,6 +3243,26 @@ function processBundles(graph) {
3128
3243
  }
3129
3244
  }
3130
3245
 
3246
+ // src/ascii/edge-cell-styles.ts
3247
+ function createEdgeCellStyles() {
3248
+ return /* @__PURE__ */ new Map();
3249
+ }
3250
+ function findStyleConflict(grid, cellStyles, path, style) {
3251
+ for (const cell of pathCells(path)) {
3252
+ if (isOccupied(grid, cell)) continue;
3253
+ const existing = cellStyles.get(gridKey(cell));
3254
+ if (existing !== void 0 && existing !== style) return cell;
3255
+ }
3256
+ return null;
3257
+ }
3258
+ function claimPathCells(grid, cellStyles, path, style) {
3259
+ for (const cell of pathCells(path)) {
3260
+ if (isOccupied(grid, cell)) continue;
3261
+ const key = gridKey(cell);
3262
+ if (!cellStyles.has(key)) cellStyles.set(key, style);
3263
+ }
3264
+ }
3265
+
3131
3266
  // src/ascii/multiline-utils.ts
3132
3267
  function splitLines(label) {
3133
3268
  return label.split("\n");
@@ -4903,6 +5038,26 @@ function increaseGridSizeForPath(graph, path) {
4903
5038
  }
4904
5039
  }
4905
5040
  }
5041
+ var MAX_STYLE_CONFLICT_REROUTES = 8;
5042
+ function rerouteAroundStyleConflicts(graph, edge, cellStyles, nodeOnlyGrid) {
5043
+ const temporarilyBlocked = [];
5044
+ try {
5045
+ for (let i = 0; i < MAX_STYLE_CONFLICT_REROUTES; i++) {
5046
+ const conflict = findStyleConflict(
5047
+ nodeOnlyGrid,
5048
+ cellStyles,
5049
+ edge.path,
5050
+ edge.style
5051
+ );
5052
+ if (!conflict) return;
5053
+ graph.grid.add(gridKey(conflict));
5054
+ temporarilyBlocked.push(conflict);
5055
+ determinePath(graph, edge);
5056
+ }
5057
+ } finally {
5058
+ for (const cell of temporarilyBlocked) graph.grid.delete(gridKey(cell));
5059
+ }
5060
+ }
4906
5061
  function isNodeInAnySubgraph(graph, node) {
4907
5062
  return graph.subgraphs.some((sg) => sg.nodes.includes(node));
4908
5063
  }
@@ -5257,14 +5412,19 @@ function createMapping(graph) {
5257
5412
  graph.pathBudget = createPathBudget();
5258
5413
  graph.bundles = analyzeEdgeBundles(graph);
5259
5414
  processBundles(graph);
5415
+ const cellStyles = createEdgeCellStyles();
5416
+ const nodeOnlyGrid = cloneGrid(graph.grid);
5260
5417
  for (const edge of graph.edges) {
5261
5418
  if (edge.bundle && edge.path.length > 0) {
5262
5419
  increaseGridSizeForPath(graph, edge.path);
5420
+ claimPathCells(nodeOnlyGrid, cellStyles, edge.path, edge.style);
5263
5421
  determineLabelLine(graph, edge);
5264
5422
  continue;
5265
5423
  }
5266
5424
  determinePath(graph, edge);
5425
+ rerouteAroundStyleConflicts(graph, edge, cellStyles, nodeOnlyGrid);
5267
5426
  increaseGridSizeForPath(graph, edge.path);
5427
+ claimPathCells(nodeOnlyGrid, cellStyles, edge.path, edge.style);
5268
5428
  determineLabelLine(graph, edge);
5269
5429
  }
5270
5430
  for (const node of graph.nodes) {
@@ -9232,16 +9392,27 @@ function pointsToPath(points, curve = "linear") {
9232
9392
  }
9233
9393
 
9234
9394
  // src/renderer.ts
9235
- function renderSvg(graph, colors, font = "Inter", transparent = false, fontSizes = FONT_SIZES, curve = "linear", embedSource) {
9395
+ function renderSvg(graph, colors, font = "Inter", transparent = false, fontSizes = FONT_SIZES, curve = "linear", embedSource, animationEnabled = true, title, decorative) {
9236
9396
  const parts = [];
9397
+ const hasInteractiveLinks = graph.nodes.some(
9398
+ (n) => Boolean(safeHref(n.interaction?.href))
9399
+ );
9237
9400
  parts.push(
9238
9401
  withDataSrc(
9239
- svgOpenTag(graph.width, graph.height, colors, transparent),
9402
+ svgOpenTag(
9403
+ graph.width,
9404
+ graph.height,
9405
+ colors,
9406
+ transparent,
9407
+ title,
9408
+ decorative,
9409
+ hasInteractiveLinks
9410
+ ),
9240
9411
  embedSource
9241
9412
  )
9242
9413
  );
9243
9414
  parts.push(buildStyleBlock(font, false));
9244
- if (graph.edges.some((e) => e.animate)) {
9415
+ if (animationEnabled && graph.edges.some((e) => e.animate)) {
9245
9416
  parts.push(edgeAnimationStyle());
9246
9417
  }
9247
9418
  parts.push("<defs>");
@@ -9260,7 +9431,7 @@ function renderSvg(graph, colors, font = "Inter", transparent = false, fontSizes
9260
9431
  parts.push(renderGroup(group, font, fontSizes));
9261
9432
  }
9262
9433
  for (const edge of graph.edges) {
9263
- parts.push(renderEdge(edge, curve));
9434
+ parts.push(renderEdge(edge, curve, animationEnabled));
9264
9435
  }
9265
9436
  for (const edge of graph.edges) {
9266
9437
  if (edge.label) {
@@ -9331,8 +9502,9 @@ function renderGroup(group, font, fontSizes) {
9331
9502
  parts.push("</g>");
9332
9503
  return parts.join("\n");
9333
9504
  }
9334
- function renderEdge(edge, curve) {
9505
+ function renderEdge(edge, curve, animationEnabled = true) {
9335
9506
  if (edge.points.length < 2) return "";
9507
+ const animate = animationEnabled && (edge.animate ?? false);
9336
9508
  const curved = curve !== "linear";
9337
9509
  const invisible = edge.style === "invisible";
9338
9510
  const dashArray = edge.style === "dotted" ? ' stroke-dasharray="4 4"' : "";
@@ -9349,9 +9521,9 @@ function renderEdge(edge, curve) {
9349
9521
  markers += ` marker-start="url(#arrowhead-start${suffix})"`;
9350
9522
  }
9351
9523
  const dataAttrs = [
9352
- // An animated edge (`e1@{ animate: true }`) carries an extra class; its
9353
- // keyframes live in the shared style block.
9354
- `class="edge${edge.animate ? " edge-animated" : ""}"`,
9524
+ // An animated edge (`e1@{ animate: true }`, with animation enabled)
9525
+ // carries an extra class; its keyframes live in the shared style block.
9526
+ `class="edge${animate ? " edge-animated" : ""}"`,
9355
9527
  `data-from="${escapeAttr(edge.source)}"`,
9356
9528
  `data-to="${escapeAttr(edge.target)}"`,
9357
9529
  `data-style="${edge.style}"`,
@@ -9364,7 +9536,7 @@ function renderEdge(edge, curve) {
9364
9536
  if (edge.id) {
9365
9537
  dataAttrs.push(`data-id="${escapeAttr(edge.id)}"`);
9366
9538
  }
9367
- const animatedDash = edge.animate && !dashArray ? ' stroke-dasharray="8 6"' : "";
9539
+ const animatedDash = animate && !dashArray ? ' stroke-dasharray="8 6"' : "";
9368
9540
  const geometry = curved ? `d="${pointsToPath(edge.points, curve)}"` : `points="${pointsToPolylinePath(edge.points)}"`;
9369
9541
  return `<${curved ? "path" : "polyline"} ${dataAttrs.join(" ")} ${geometry} fill="none" stroke="${strokeColor}" stroke-width="${strokeWidth}"${dashArray}${animatedDash}${markers} />`;
9370
9542
  }
@@ -10279,11 +10451,18 @@ function layoutSequenceDiagram(diagram, options = {}) {
10279
10451
  }
10280
10452
 
10281
10453
  // src/sequence/renderer.ts
10282
- function renderSequenceSvg(diagram, colors, font = "Inter", transparent = false, fontSizes = FONT_SIZES, embedSource) {
10454
+ function renderSequenceSvg(diagram, colors, font = "Inter", transparent = false, fontSizes = FONT_SIZES, embedSource, title, decorative) {
10283
10455
  const parts = [];
10284
10456
  parts.push(
10285
10457
  withDataSrc(
10286
- svgOpenTag(diagram.width, diagram.height, colors, transparent),
10458
+ svgOpenTag(
10459
+ diagram.width,
10460
+ diagram.height,
10461
+ colors,
10462
+ transparent,
10463
+ title,
10464
+ decorative
10465
+ ),
10287
10466
  embedSource
10288
10467
  )
10289
10468
  );
@@ -10680,11 +10859,18 @@ var CLS_FONT = {
10680
10859
  annotationSize: 10,
10681
10860
  annotationWeight: 500
10682
10861
  };
10683
- function renderClassSvg(diagram, colors, font = "Inter", transparent = false, fontSizes = FONT_SIZES, embedSource) {
10862
+ function renderClassSvg(diagram, colors, font = "Inter", transparent = false, fontSizes = FONT_SIZES, embedSource, title, decorative) {
10684
10863
  const parts = [];
10685
10864
  parts.push(
10686
10865
  withDataSrc(
10687
- svgOpenTag(diagram.width, diagram.height, colors, transparent),
10866
+ svgOpenTag(
10867
+ diagram.width,
10868
+ diagram.height,
10869
+ colors,
10870
+ transparent,
10871
+ title,
10872
+ decorative
10873
+ ),
10688
10874
  embedSource
10689
10875
  )
10690
10876
  );
@@ -11068,11 +11254,18 @@ var ER_FONT = {
11068
11254
  keySize: 9,
11069
11255
  keyWeight: 600
11070
11256
  };
11071
- function renderErSvg(diagram, colors, font = "Inter", transparent = false, fontSizes = FONT_SIZES, embedSource) {
11257
+ function renderErSvg(diagram, colors, font = "Inter", transparent = false, fontSizes = FONT_SIZES, embedSource, title, decorative) {
11072
11258
  const parts = [];
11073
11259
  parts.push(
11074
11260
  withDataSrc(
11075
- svgOpenTag(diagram.width, diagram.height, colors, transparent),
11261
+ svgOpenTag(
11262
+ diagram.width,
11263
+ diagram.height,
11264
+ colors,
11265
+ transparent,
11266
+ title,
11267
+ decorative
11268
+ ),
11076
11269
  embedSource
11077
11270
  )
11078
11271
  );
@@ -11807,7 +12000,7 @@ var TIP = {
11807
12000
  minY: 4,
11808
12001
  pointerSize: 6
11809
12002
  };
11810
- function renderXYChartSvg(chart, colors, font = "Inter", transparent = false, interactive = false, embedSource) {
12003
+ function renderXYChartSvg(chart, colors, font = "Inter", transparent = false, interactive = false, embedSource, title, decorative) {
11811
12004
  const parts = [];
11812
12005
  const maxColorIdx = Math.max(
11813
12006
  0,
@@ -11815,10 +12008,14 @@ function renderXYChartSvg(chart, colors, font = "Inter", transparent = false, in
11815
12008
  ...chart.lines.map((l) => l.colorIndex)
11816
12009
  );
11817
12010
  const svgTag = withDataSrc(
11818
- svgOpenTag(chart.width, chart.height, colors, transparent).replace(
11819
- "<svg ",
11820
- `<svg data-xychart-colors="${maxColorIdx}" `
11821
- ),
12011
+ svgOpenTag(
12012
+ chart.width,
12013
+ chart.height,
12014
+ colors,
12015
+ transparent,
12016
+ title,
12017
+ decorative
12018
+ ).replace("<svg ", `<svg data-xychart-colors="${maxColorIdx}" `),
11822
12019
  embedSource
11823
12020
  );
11824
12021
  parts.push(svgTag);
@@ -12234,6 +12431,18 @@ function buildColors(options) {
12234
12431
  border: options.border
12235
12432
  };
12236
12433
  }
12434
+ function resolveInteractivity(options) {
12435
+ return options.interactivity ?? "static";
12436
+ }
12437
+ function resolveAnimationEnabled(options) {
12438
+ return resolveInteractivity(options) !== "none";
12439
+ }
12440
+ function resolveXYChartInteractive(options) {
12441
+ if (options.interactivity !== void 0) {
12442
+ return options.interactivity === "full";
12443
+ }
12444
+ return options.interactive ?? false;
12445
+ }
12237
12446
  function renderMermaidSVG(text, options = {}) {
12238
12447
  const originalText = text;
12239
12448
  text = decodeXML(text);
@@ -12243,6 +12452,8 @@ function renderMermaidSVG(text, options = {}) {
12243
12452
  const fontSizes = resolveFontSizes(options.fontSizes);
12244
12453
  const diagramType = detectDiagramType(text);
12245
12454
  const embedSource = options.embedSource ? originalText : void 0;
12455
+ const title = options.title;
12456
+ const decorative = options.decorative;
12246
12457
  const lines = splitStatements(text);
12247
12458
  switch (diagramType) {
12248
12459
  case "sequence": {
@@ -12254,7 +12465,9 @@ function renderMermaidSVG(text, options = {}) {
12254
12465
  font,
12255
12466
  transparent,
12256
12467
  fontSizes,
12257
- embedSource
12468
+ embedSource,
12469
+ title,
12470
+ decorative
12258
12471
  );
12259
12472
  }
12260
12473
  case "class": {
@@ -12266,7 +12479,9 @@ function renderMermaidSVG(text, options = {}) {
12266
12479
  font,
12267
12480
  transparent,
12268
12481
  fontSizes,
12269
- embedSource
12482
+ embedSource,
12483
+ title,
12484
+ decorative
12270
12485
  );
12271
12486
  }
12272
12487
  case "er": {
@@ -12278,7 +12493,9 @@ function renderMermaidSVG(text, options = {}) {
12278
12493
  font,
12279
12494
  transparent,
12280
12495
  fontSizes,
12281
- embedSource
12496
+ embedSource,
12497
+ title,
12498
+ decorative
12282
12499
  );
12283
12500
  }
12284
12501
  case "xychart": {
@@ -12289,8 +12506,10 @@ function renderMermaidSVG(text, options = {}) {
12289
12506
  colors,
12290
12507
  font,
12291
12508
  transparent,
12292
- options.interactive ?? false,
12293
- embedSource
12509
+ resolveXYChartInteractive(options),
12510
+ embedSource,
12511
+ title,
12512
+ decorative
12294
12513
  );
12295
12514
  }
12296
12515
  case "flowchart":
@@ -12305,7 +12524,10 @@ function renderMermaidSVG(text, options = {}) {
12305
12524
  transparent,
12306
12525
  fontSizes,
12307
12526
  effective.curve ?? "linear",
12308
- embedSource
12527
+ embedSource,
12528
+ resolveAnimationEnabled(options),
12529
+ title,
12530
+ decorative
12309
12531
  );
12310
12532
  }
12311
12533
  }