zombie-mermaid 2.2.1 → 2.2.2

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.
Files changed (251) hide show
  1. package/LICENSE +1 -0
  2. package/README.md +7 -2
  3. package/dist/ascii.cjs +9 -9
  4. package/dist/ascii.cjs.map +1 -1
  5. package/dist/ascii.js +4069 -3969
  6. package/dist/ascii.js.map +1 -1
  7. package/dist/cli.js +7605 -7381
  8. package/dist/index.cjs +52 -52
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.js +7613 -7459
  11. package/dist/index.js.map +1 -1
  12. package/dist/mcp.cjs +14142 -13717
  13. package/dist/mcp.cjs.map +1 -1
  14. package/dist/mcp.js +14142 -13717
  15. package/dist/mcp.js.map +1 -1
  16. package/package.json +27 -5
  17. package/packages/ascii-renderer/LICENSE +22 -0
  18. package/{src/ascii → packages/ascii-renderer/src}/class-diagram.ts +277 -57
  19. package/{src/ascii → packages/ascii-renderer/src}/er-diagram.ts +2 -2
  20. package/packages/ascii-renderer/src/flowchart.ts +94 -0
  21. package/{src/ascii → packages/ascii-renderer/src}/grid.ts +23 -0
  22. package/{src/ascii → packages/ascii-renderer/src}/index.ts +13 -84
  23. package/{src/ascii → packages/ascii-renderer/src}/registry.ts +23 -12
  24. package/{src/ascii → packages/ascii-renderer/src}/sequence.ts +55 -8
  25. package/{src/ascii → packages/ascii-renderer/src}/xychart.ts +6 -3
  26. package/packages/core/LICENSE +22 -0
  27. package/packages/core/src/click-directive.ts +106 -0
  28. package/packages/core/src/color-utils.ts +205 -0
  29. package/packages/core/src/diagram-type.ts +35 -0
  30. package/packages/core/src/direction-override.ts +46 -0
  31. package/packages/core/src/direction.ts +56 -0
  32. package/packages/core/src/index.ts +34 -0
  33. package/packages/core/src/init-directive.ts +248 -0
  34. package/packages/core/src/multiline-utils.ts +275 -0
  35. package/packages/core/src/statements.ts +197 -0
  36. package/packages/core/src/style-directives.ts +214 -0
  37. package/packages/core/src/text-metrics.ts +498 -0
  38. package/packages/core/src/theme.ts +696 -0
  39. package/packages/core/src/types.ts +670 -0
  40. package/packages/mcp/LICENSE +22 -0
  41. package/{src/mcp → packages/mcp/src}/server.ts +34 -2
  42. package/{src/mcp → packages/mcp/src}/tools/check-sequence-activations.ts +8 -5
  43. package/packages/mcp/src/tools/fix-sequence-activations.ts +77 -0
  44. package/{src/mcp → packages/mcp/src}/tools/render-ascii.ts +2 -2
  45. package/{src/mcp → packages/mcp/src}/tools/render-svg.ts +1 -1
  46. package/packages/mermaid-parser/LICENSE +22 -0
  47. package/{src → packages/mermaid-parser/src}/class/parser.ts +86 -8
  48. package/{src → packages/mermaid-parser/src}/er/parser.ts +59 -26
  49. package/packages/mermaid-parser/src/index.ts +48 -0
  50. package/{src → packages/mermaid-parser/src}/sequence/activation-check.ts +4 -3
  51. package/packages/mermaid-parser/src/sequence/activation-fix.ts +112 -0
  52. package/{src → packages/mermaid-parser/src}/sequence/parser.ts +74 -16
  53. package/{src → packages/mermaid-parser/src}/xychart/parser.ts +84 -6
  54. package/packages/svg-renderer/LICENSE +22 -0
  55. package/{src → packages/svg-renderer/src}/class/layout.ts +8 -4
  56. package/{src → packages/svg-renderer/src}/class/renderer.ts +7 -6
  57. package/packages/svg-renderer/src/edge-curves.ts +204 -0
  58. package/packages/svg-renderer/src/elk-instance.ts +292 -0
  59. package/{src → packages/svg-renderer/src}/er/layout.ts +6 -4
  60. package/{src → packages/svg-renderer/src}/er/renderer.ts +4 -4
  61. package/packages/svg-renderer/src/index.ts +58 -0
  62. package/packages/svg-renderer/src/layout-engine/constants.ts +19 -0
  63. package/packages/svg-renderer/src/layout-engine/edge-bundling.ts +379 -0
  64. package/packages/svg-renderer/src/layout-engine/elk-adapter-utils.ts +81 -0
  65. package/packages/svg-renderer/src/layout-engine/elk-graph-builder.ts +240 -0
  66. package/packages/svg-renderer/src/layout-engine/from-elk.ts +685 -0
  67. package/packages/svg-renderer/src/layout-engine/layer-alignment.ts +174 -0
  68. package/packages/svg-renderer/src/layout-engine/to-elk.ts +695 -0
  69. package/packages/svg-renderer/src/layout-engine.ts +74 -0
  70. package/packages/svg-renderer/src/layout.ts +8 -0
  71. package/packages/svg-renderer/src/renderer.ts +1485 -0
  72. package/packages/svg-renderer/src/resolve-colors.ts +339 -0
  73. package/{src → packages/svg-renderer/src}/sequence/layout.ts +2 -6
  74. package/{src → packages/svg-renderer/src}/sequence/renderer.ts +4 -4
  75. package/packages/svg-renderer/src/shape-clipping.ts +197 -0
  76. package/packages/svg-renderer/src/styles.ts +118 -0
  77. package/{src → packages/svg-renderer/src}/xychart/layout.ts +2 -2
  78. package/{src → packages/svg-renderer/src}/xychart/renderer.ts +6 -6
  79. package/src/__tests__/ascii-ansi.test.ts +6 -2
  80. package/src/__tests__/ascii-canvas-write.test.ts +2 -2
  81. package/src/__tests__/ascii-charset-border-junctions.test.ts +1 -1
  82. package/src/__tests__/ascii-cjk-width.test.ts +1 -1
  83. package/src/__tests__/ascii-class-box-occupancy.test.ts +147 -45
  84. package/src/__tests__/ascii-class-column-width-488-489.test.ts +1 -1
  85. package/src/__tests__/ascii-class-cross-level-jog-corruption.test.ts +187 -0
  86. package/src/__tests__/ascii-class-detour-label-routing-487.test.ts +1 -1
  87. package/src/__tests__/ascii-class-diagram-compartments.test.ts +1 -1
  88. package/src/__tests__/ascii-class-label-box-collision.test.ts +1 -1
  89. package/src/__tests__/ascii-class-label-row-collision-531.test.ts +1 -1
  90. package/src/__tests__/ascii-class-label-territory-row-awareness.test.ts +1 -1
  91. package/src/__tests__/ascii-class-padding.test.ts +1 -1
  92. package/src/__tests__/ascii-class-reciprocal-relationships-448.test.ts +86 -1
  93. package/src/__tests__/ascii-combining-mark-width.test.ts +2 -2
  94. package/src/__tests__/ascii-coords-overlay.test.ts +2 -2
  95. package/src/__tests__/ascii-decision-lr-box-start.test.ts +2 -2
  96. package/src/__tests__/ascii-display-width-unit.test.ts +1 -1
  97. package/src/__tests__/ascii-draw-arrows-coverage.test.ts +1 -1
  98. package/src/__tests__/ascii-draw-arrows-single-point-path.test.ts +12 -5
  99. package/src/__tests__/ascii-draw-bundles.test.ts +5 -5
  100. package/src/__tests__/ascii-edge-bundling-rank-violation-454.test.ts +1 -1
  101. package/src/__tests__/ascii-edge-bundling-routing.test.ts +9 -5
  102. package/src/__tests__/ascii-edge-cross-style-overlap.test.ts +10 -6
  103. package/src/__tests__/ascii-edge-ending-glyphs.test.ts +1 -1
  104. package/src/__tests__/ascii-edge-label-diagonal-fallback-418.test.ts +2 -2
  105. package/src/__tests__/ascii-edge-routing-fixes.test.ts +1 -1
  106. package/src/__tests__/ascii-edge-routing-single-point-path.test.ts +8 -4
  107. package/src/__tests__/ascii-edge-styles.test.ts +1 -1
  108. package/src/__tests__/ascii-emoji-cluster-width.test.ts +2 -2
  109. package/src/__tests__/ascii-er-box-occupancy.test.ts +1 -1
  110. package/src/__tests__/ascii-er-cardinality.test.ts +1 -1
  111. package/src/__tests__/ascii-er-corner-glyphs.test.ts +1 -1
  112. package/src/__tests__/ascii-er-jog-stray-line.test.ts +1 -1
  113. package/src/__tests__/ascii-er-label-padding.test.ts +1 -1
  114. package/src/__tests__/ascii-er-padding.test.ts +1 -1
  115. package/src/__tests__/ascii-er-relationship-label-corruption-350.test.ts +1 -1
  116. package/src/__tests__/ascii-er-relationship-overwrite.test.ts +1 -1
  117. package/src/__tests__/ascii-er-stray-connectors.test.ts +7 -4
  118. package/src/__tests__/ascii-er-unrelated-stem-separation-411.test.ts +1 -1
  119. package/src/__tests__/ascii-er-vertical-one-marker.test.ts +1 -1
  120. package/src/__tests__/ascii-grid-deep-chain.test.ts +4 -4
  121. package/src/__tests__/ascii-hyperlinks.test.ts +9 -6
  122. package/src/__tests__/ascii-label-line-terminal-fallback.test.ts +8 -4
  123. package/src/__tests__/ascii-lane-search.test.ts +1 -1
  124. package/src/__tests__/ascii-multibox-cjk-width.test.ts +1 -1
  125. package/src/__tests__/ascii-multiline.test.ts +6 -3
  126. package/src/__tests__/ascii-nested-subgraph-sibling-order-444.test.ts +8 -5
  127. package/src/__tests__/ascii-package-boundary.test.ts +47 -37
  128. package/src/__tests__/ascii-padding-edge-cases.test.ts +1 -1
  129. package/src/__tests__/ascii-parallel-edges-329.test.ts +8 -5
  130. package/src/__tests__/ascii-pathfinder-route-edge.test.ts +14 -4
  131. package/src/__tests__/ascii-reverse-direction-edges-629.test.ts +9 -5
  132. package/src/__tests__/ascii-sequence-alt-else-label.test.ts +1 -1
  133. package/src/__tests__/ascii-sequence-block-wall-clearance.test.ts +1 -1
  134. package/src/__tests__/ascii-sequence-box-group.test.ts +1 -1
  135. package/src/__tests__/ascii-sequence-cjk-width.test.ts +1 -1
  136. package/src/__tests__/ascii-sequence-create-destroy.test.ts +1 -1
  137. package/src/__tests__/ascii-sequence-form-invariants.test.ts +48 -50
  138. package/src/__tests__/ascii-sequence-mermaid-parity.test.ts +1 -1
  139. package/src/__tests__/ascii-sequence-notes.test.ts +1 -1
  140. package/src/__tests__/ascii-sequence-padding.test.ts +1 -1
  141. package/src/__tests__/ascii-sequence-self-arrow.test.ts +1 -1
  142. package/src/__tests__/ascii-shape-diamond.test.ts +3 -3
  143. package/src/__tests__/ascii-shape-rectangle.test.ts +5 -5
  144. package/src/__tests__/ascii-shape-rounded.test.ts +3 -3
  145. package/src/__tests__/ascii-shapes-circle.test.ts +3 -3
  146. package/src/__tests__/ascii-shapes-hexagon.test.ts +3 -3
  147. package/src/__tests__/ascii-shapes-special.test.ts +10 -5
  148. package/src/__tests__/ascii-shapes-stadium.test.ts +3 -3
  149. package/src/__tests__/ascii-shapes-state.test.ts +15 -5
  150. package/src/__tests__/ascii-state-bidirectional-label-swap-530.test.ts +1 -1
  151. package/src/__tests__/ascii-subgraph-bbox.test.ts +8 -4
  152. package/src/__tests__/ascii-subgraph-direction-honored-445.test.ts +1 -1
  153. package/src/__tests__/ascii-subgraph-label-border-clip.test.ts +88 -25
  154. package/src/__tests__/ascii-subgraph-later-edgeless-301.test.ts +8 -4
  155. package/src/__tests__/ascii-subgraph-title-padding.test.ts +1 -1
  156. package/src/__tests__/ascii-territory-unit.test.ts +2 -2
  157. package/src/__tests__/ascii-validate.test.ts +1 -1
  158. package/src/__tests__/ascii.test.ts +5 -2
  159. package/src/__tests__/box-color.test.ts +1 -1
  160. package/src/__tests__/class-arrow-directions.test.ts +1 -1
  161. package/src/__tests__/class-click-interactions.test.ts +3 -6
  162. package/src/__tests__/class-integration.test.ts +1 -1
  163. package/src/__tests__/class-notes.test.ts +3 -3
  164. package/src/__tests__/class-parser-error-messages.test.ts +162 -0
  165. package/src/__tests__/class-parser.test.ts +6 -6
  166. package/src/__tests__/class-styling.test.ts +2 -2
  167. package/src/__tests__/cli-render.test.ts +16 -1
  168. package/src/__tests__/direction-override.test.ts +1 -1
  169. package/src/__tests__/draw-lines.test.ts +2 -2
  170. package/src/__tests__/edge-cell-styles.test.ts +5 -2
  171. package/src/__tests__/elk-layout-cache.test.ts +6 -4
  172. package/src/__tests__/er-click-unsupported.test.ts +5 -8
  173. package/src/__tests__/er-parser-error-messages.test.ts +82 -0
  174. package/src/__tests__/er-parser.test.ts +3 -6
  175. package/src/__tests__/expanded-shapes.test.ts +1 -1
  176. package/src/__tests__/grid-occupancy.test.ts +1 -1
  177. package/src/__tests__/mcp-check-sequence-activations-tool.test.ts +1 -1
  178. package/src/__tests__/mcp-fix-sequence-activations-tool.test.ts +134 -0
  179. package/src/__tests__/mcp-render-ascii-tool.test.ts +5 -4
  180. package/src/__tests__/mcp-render-svg-theme-guard.test.ts +3 -3
  181. package/src/__tests__/mcp-render-svg-tool.test.ts +1 -1
  182. package/src/__tests__/mcp-server.test.ts +30 -1
  183. package/src/__tests__/multiline-labels.test.ts +29 -18
  184. package/src/__tests__/parser.test.ts +117 -5
  185. package/src/__tests__/pathfinder.test.ts +11 -4
  186. package/src/__tests__/render-options-overrides.test.ts +28 -21
  187. package/src/__tests__/render-options-per-type.test.ts +13 -9
  188. package/src/__tests__/resolve-colors.test.ts +1 -1
  189. package/src/__tests__/self-loop-edges.test.ts +112 -0
  190. package/src/__tests__/sequence-activation-check.test.ts +7 -8
  191. package/src/__tests__/sequence-activation-fix.test.ts +91 -0
  192. package/src/__tests__/sequence-layout.test.ts +4 -7
  193. package/src/__tests__/sequence-parser-syntax-errors.test.ts +179 -0
  194. package/src/__tests__/sequence-parser.test.ts +3 -6
  195. package/src/__tests__/statements.test.ts +53 -35
  196. package/src/__tests__/testdata/ascii/subgraph_direction_override.txt +21 -21
  197. package/src/__tests__/theme-palette-contrast.test.ts +84 -0
  198. package/src/__tests__/workspace-package-boundaries.test.ts +199 -25
  199. package/src/__tests__/xychart-ascii.test.ts +1 -1
  200. package/src/__tests__/xychart-colors.test.ts +3 -2
  201. package/src/__tests__/xychart-layout.test.ts +1 -1
  202. package/src/__tests__/xychart-parser-errors.test.ts +95 -0
  203. package/src/browser.ts +8 -2
  204. package/src/cli/mcp.ts +1 -1
  205. package/src/cli/render.ts +59 -25
  206. package/src/cli/web.ts +1 -1
  207. package/src/diagram-registry.ts +190 -25
  208. package/src/index.ts +34 -131
  209. package/src/parser.ts +102 -40
  210. /package/{src/ascii → packages/ascii-renderer/src}/ansi.ts +0 -0
  211. /package/{src/ascii → packages/ascii-renderer/src}/canvas.ts +0 -0
  212. /package/{src/ascii → packages/ascii-renderer/src}/converter.ts +0 -0
  213. /package/{src/ascii → packages/ascii-renderer/src}/coords.ts +0 -0
  214. /package/{src/ascii → packages/ascii-renderer/src}/display-width.ts +0 -0
  215. /package/{src/ascii → packages/ascii-renderer/src}/draw-arrows.ts +0 -0
  216. /package/{src/ascii → packages/ascii-renderer/src}/draw-boxes.ts +0 -0
  217. /package/{src/ascii → packages/ascii-renderer/src}/draw-bundles.ts +0 -0
  218. /package/{src/ascii → packages/ascii-renderer/src}/draw-lines.ts +0 -0
  219. /package/{src/ascii → packages/ascii-renderer/src}/draw-subgraphs.ts +0 -0
  220. /package/{src/ascii → packages/ascii-renderer/src}/draw.ts +0 -0
  221. /package/{src/ascii → packages/ascii-renderer/src}/edge-bundling.ts +0 -0
  222. /package/{src/ascii → packages/ascii-renderer/src}/edge-cell-styles.ts +0 -0
  223. /package/{src/ascii → packages/ascii-renderer/src}/edge-routing.ts +0 -0
  224. /package/{src/ascii → packages/ascii-renderer/src}/grid-occupancy.ts +0 -0
  225. /package/{src/ascii → packages/ascii-renderer/src}/hyperlinks.ts +0 -0
  226. /package/{src/ascii → packages/ascii-renderer/src}/lane-search.ts +0 -0
  227. /package/{src/ascii → packages/ascii-renderer/src}/multiline-utils.ts +0 -0
  228. /package/{src/ascii → packages/ascii-renderer/src}/pathfinder.ts +0 -0
  229. /package/{src/ascii → packages/ascii-renderer/src}/shapes/circle.ts +0 -0
  230. /package/{src/ascii → packages/ascii-renderer/src}/shapes/corners.ts +0 -0
  231. /package/{src/ascii → packages/ascii-renderer/src}/shapes/diamond.ts +0 -0
  232. /package/{src/ascii → packages/ascii-renderer/src}/shapes/hexagon.ts +0 -0
  233. /package/{src/ascii → packages/ascii-renderer/src}/shapes/index.ts +0 -0
  234. /package/{src/ascii → packages/ascii-renderer/src}/shapes/rectangle.ts +0 -0
  235. /package/{src/ascii → packages/ascii-renderer/src}/shapes/rounded.ts +0 -0
  236. /package/{src/ascii → packages/ascii-renderer/src}/shapes/special.ts +0 -0
  237. /package/{src/ascii → packages/ascii-renderer/src}/shapes/stadium.ts +0 -0
  238. /package/{src/ascii → packages/ascii-renderer/src}/shapes/state.ts +0 -0
  239. /package/{src/ascii → packages/ascii-renderer/src}/shapes/types.ts +0 -0
  240. /package/{src/ascii → packages/ascii-renderer/src}/territory.ts +0 -0
  241. /package/{src/ascii → packages/ascii-renderer/src}/types.ts +0 -0
  242. /package/{src/ascii → packages/ascii-renderer/src}/validate.ts +0 -0
  243. /package/{src/mcp → packages/mcp/src}/index.ts +0 -0
  244. /package/{src → packages/mermaid-parser/src}/class/format.ts +0 -0
  245. /package/{src → packages/mermaid-parser/src}/class/types.ts +0 -0
  246. /package/{src → packages/mermaid-parser/src}/er/types.ts +0 -0
  247. /package/{src → packages/mermaid-parser/src}/expanded-shapes.ts +0 -0
  248. /package/{src → packages/mermaid-parser/src}/sequence/box-color.ts +0 -0
  249. /package/{src → packages/mermaid-parser/src}/sequence/types.ts +0 -0
  250. /package/{src → packages/mermaid-parser/src}/xychart/colors.ts +0 -0
  251. /package/{src → packages/mermaid-parser/src}/xychart/types.ts +0 -0
@@ -0,0 +1,112 @@
1
+ // ============================================================================
2
+ // Sequence diagram — activation/deactivation auto-fix
3
+ //
4
+ // Extends activation-check.ts (issue #539) with the "optionally proposes a
5
+ // fix" half of that issue's scope. Deliberately narrow: only
6
+ // `DANGLING_ACTIVATION` (an `activate X` never closed) is auto-fixable —
7
+ // the mechanical, unambiguous repair is to append a matching `deactivate X`
8
+ // after the diagram's last statement, which is always syntactically valid
9
+ // regardless of block nesting (Mermaid's `deactivate` isn't block-scoped).
10
+ //
11
+ // `UNMATCHED_DEACTIVATION` (a `deactivate X` with nothing open) is
12
+ // deliberately NOT auto-fixed: fixing it means either deleting that
13
+ // specific statement or inserting a preceding `activate X`, and this
14
+ // package doesn't track source line/position per activation statement (see
15
+ // SequenceDiagram.activations — only a message-index `afterIndex`, no raw
16
+ // line offset), so a text-level edit could not target the right occurrence
17
+ // with confidence when the same statement text repeats. Rather than guess
18
+ // and risk mangling unrelated source, this case is reported back as a
19
+ // remaining (unfixable) issue for a human — or a fuzzier LLM-based layer,
20
+ // per the issue's own caveat about unvalidated frontier-model behavior — to
21
+ // resolve.
22
+ // ============================================================================
23
+
24
+ import { detectDiagramType, splitStatements } from '@zombie-mermaid/core'
25
+ import { parseSequenceDiagram } from './parser.ts'
26
+ import {
27
+ checkActivationBalance,
28
+ type ActivationIssue,
29
+ } from './activation-check.ts'
30
+
31
+ export interface ActivationFixResult {
32
+ /** true when the returned diagram has no remaining activation issues. */
33
+ ok: boolean
34
+ /** Original diagram, unchanged if there was nothing fixable. */
35
+ originalDiagram: string
36
+ /**
37
+ * Diagram with a "deactivate X" statement appended for every
38
+ * DANGLING_ACTIVATION issue found. Identical to `originalDiagram` when
39
+ * there was nothing to fix.
40
+ */
41
+ fixedDiagram: string
42
+ /** Human-readable description of each fix actually applied. */
43
+ fixesApplied: string[]
44
+ /**
45
+ * Issues that could not be auto-fixed (currently always
46
+ * UNMATCHED_DEACTIVATION — see module header). Empty when `ok` is true.
47
+ */
48
+ remainingIssues: ActivationIssue[]
49
+ }
50
+
51
+ /**
52
+ * Check a Mermaid sequence diagram for activation/deactivation imbalance
53
+ * and, where mechanically safe, return a corrected version.
54
+ *
55
+ * Throws the same way `parseSequenceDiagram`/`detectDiagramType` do on
56
+ * invalid or non-sequence input — callers (e.g. the MCP tool handler) are
57
+ * expected to catch and translate, matching `check-sequence-activations.ts`'s
58
+ * own error handling.
59
+ */
60
+ export function fixActivationBalance(
61
+ sourceDiagram: string,
62
+ ): ActivationFixResult {
63
+ const diagramType = detectDiagramType(sourceDiagram)
64
+ if (diagramType !== 'sequence') {
65
+ throw new Error(
66
+ 'fixActivationBalance only supports sequence diagrams (source must ' +
67
+ `start with "sequenceDiagram"); detected diagram type: "${diagramType}".`,
68
+ )
69
+ }
70
+
71
+ const lines = splitStatements(sourceDiagram)
72
+ const diagram = parseSequenceDiagram(lines)
73
+ const result = checkActivationBalance(diagram)
74
+
75
+ if (result.ok) {
76
+ return {
77
+ ok: true,
78
+ originalDiagram: sourceDiagram,
79
+ fixedDiagram: sourceDiagram,
80
+ fixesApplied: [],
81
+ remainingIssues: [],
82
+ }
83
+ }
84
+
85
+ const dangling = result.issues.filter(
86
+ (issue) => issue.code === 'DANGLING_ACTIVATION',
87
+ )
88
+ const remainingIssues = result.issues.filter(
89
+ (issue) => issue.code !== 'DANGLING_ACTIVATION',
90
+ )
91
+
92
+ const appended = dangling
93
+ .map((issue) => ` deactivate ${issue.actorId}`)
94
+ .join('\n')
95
+ const fixedDiagram =
96
+ dangling.length === 0
97
+ ? sourceDiagram
98
+ : `${sourceDiagram.replace(/\s+$/, '')}\n${appended}`
99
+
100
+ const fixesApplied = dangling.map(
101
+ (issue) =>
102
+ `Appended "deactivate ${issue.actorId}" to close: ${issue.message}`,
103
+ )
104
+
105
+ return {
106
+ ok: remainingIssues.length === 0,
107
+ originalDiagram: sourceDiagram,
108
+ fixedDiagram,
109
+ fixesApplied,
110
+ remainingIssues,
111
+ }
112
+ }
@@ -1,5 +1,5 @@
1
1
  import type { SequenceDiagram, Message, Block, Actor } from './types.ts'
2
- import { normalizeBrTags } from '@zombie-mermaid/core'
2
+ import { normalizeBrTags, type Statement } from '@zombie-mermaid/core'
3
3
  import { parseBoxHeader } from './box-color.ts'
4
4
 
5
5
  /**
@@ -120,7 +120,7 @@ const MESSAGE_ANY_ARROW_RE =
120
120
  // any of these guarantees, but removing the `!` would only replace a
121
121
  // proven-safe assertion with an unreachable guard. Left as-is; no
122
122
  // behavior change.
123
- export function parseSequenceDiagram(lines: string[]): SequenceDiagram {
123
+ export function parseSequenceDiagram(lines: Statement[]): SequenceDiagram {
124
124
  const diagram: SequenceDiagram = {
125
125
  actors: [],
126
126
  messages: [],
@@ -136,6 +136,9 @@ export function parseSequenceDiagram(lines: string[]): SequenceDiagram {
136
136
  // only mean the box — but this parser is lenient about other statements,
137
137
  // and a `loop` opened inside a box must still own the next `end`.
138
138
  let boxOpenedAtDepth = 0
139
+ // Line the currently-open box started on, for the unclosed-box error at
140
+ // EOF below (issue #762) — `boxCtx.open` alone doesn't carry position.
141
+ let boxOpenLine: number | undefined
139
142
 
140
143
  // Track actor IDs to auto-create actors referenced in messages
141
144
  const actorIds = new Set<string>()
@@ -145,6 +148,7 @@ export function parseSequenceDiagram(lines: string[]): SequenceDiagram {
145
148
  label: string
146
149
  startIndex: number
147
150
  dividers: Block['dividers']
151
+ line: number
148
152
  }> = []
149
153
 
150
154
  // `autonumber` state — a bare `autonumber` turns numbering on starting at 1
@@ -163,7 +167,8 @@ export function parseSequenceDiagram(lines: string[]): SequenceDiagram {
163
167
  let pendingDestroy: string | undefined
164
168
 
165
169
  for (let i = 1; i < lines.length; i++) {
166
- const line = lines[i]!
170
+ const stmt = lines[i]!
171
+ const line = stmt.text
167
172
 
168
173
  // --- box <color?> <label?> ---
169
174
  // Opens a participant group; closed by `end`. Boxes cannot nest
@@ -173,7 +178,7 @@ export function parseSequenceDiagram(lines: string[]): SequenceDiagram {
173
178
  if (boxMatch) {
174
179
  if (boxCtx.open !== undefined) {
175
180
  throw new Error(
176
- 'Sequence diagram: a box cannot be nested inside another box — close the open box with "end" first',
181
+ `Line ${stmt.line}: Sequence diagram: a box cannot be nested inside another box — close the open box with "end" first`,
177
182
  )
178
183
  }
179
184
  const { color, label } = parseBoxHeader(boxMatch[1] ?? '')
@@ -185,6 +190,7 @@ export function parseSequenceDiagram(lines: string[]): SequenceDiagram {
185
190
  diagram.boxes.push(box)
186
191
  boxCtx.open = diagram.boxes.length - 1
187
192
  boxOpenedAtDepth = blockStack.length
193
+ boxOpenLine = stmt.line
188
194
  continue
189
195
  }
190
196
 
@@ -202,7 +208,7 @@ export function parseSequenceDiagram(lines: string[]): SequenceDiagram {
202
208
  if (actorIds.has(id)) {
203
209
  // Mermaid's own wording (sequenceDb `createParticipant`).
204
210
  throw new Error(
205
- "It is not possible to have actors with the same id, even if one is destroyed before the next is created. Use 'AS' aliases to simulate the behavior",
211
+ `Line ${stmt.line}: It is not possible to have actors with the same id, even if one is destroyed before the next is created. Use 'AS' aliases to simulate the behavior`,
206
212
  )
207
213
  }
208
214
  actorIds.add(id)
@@ -211,7 +217,7 @@ export function parseSequenceDiagram(lines: string[]): SequenceDiagram {
211
217
  label: normalizeBrTags(createMatch[3]?.trim() ?? id),
212
218
  type,
213
219
  })
214
- joinOpenBox(diagram, boxCtx, id)
220
+ joinOpenBox(diagram, boxCtx, id, stmt.line)
215
221
  pendingCreate = id
216
222
  continue
217
223
  }
@@ -221,7 +227,7 @@ export function parseSequenceDiagram(lines: string[]): SequenceDiagram {
221
227
  const destroyMatch = line.match(/^destroy\s+(.+)$/)
222
228
  if (destroyMatch) {
223
229
  const id = destroyMatch[1]!.trim()
224
- ensureActor(diagram, actorIds, boxCtx, id)
230
+ ensureActor(diagram, actorIds, boxCtx, id, stmt.line)
225
231
  pendingDestroy = id
226
232
  continue
227
233
  }
@@ -262,7 +268,7 @@ export function parseSequenceDiagram(lines: string[]): SequenceDiagram {
262
268
  }
263
269
  // A re-declaration inside a box joins it (or errors if it already
264
270
  // belongs to a different one) — Mermaid's `addActor` rule.
265
- joinOpenBox(diagram, boxCtx, id)
271
+ joinOpenBox(diagram, boxCtx, id, stmt.line)
266
272
  continue
267
273
  }
268
274
 
@@ -279,7 +285,7 @@ export function parseSequenceDiagram(lines: string[]): SequenceDiagram {
279
285
 
280
286
  // Ensure actors exist
281
287
  for (const aid of noteActorIds) {
282
- ensureActor(diagram, actorIds, boxCtx, aid)
288
+ ensureActor(diagram, actorIds, boxCtx, aid, stmt.line)
283
289
  }
284
290
 
285
291
  let position: 'left' | 'right' | 'over' = 'over'
@@ -308,6 +314,7 @@ export function parseSequenceDiagram(lines: string[]): SequenceDiagram {
308
314
  label,
309
315
  startIndex: diagram.messages.length,
310
316
  dividers: [],
317
+ line: stmt.line,
311
318
  })
312
319
  continue
313
320
  }
@@ -333,6 +340,7 @@ export function parseSequenceDiagram(lines: string[]): SequenceDiagram {
333
340
  blockStack.length === boxOpenedAtDepth
334
341
  ) {
335
342
  boxCtx.open = undefined
343
+ boxOpenLine = undefined
336
344
  continue
337
345
  }
338
346
 
@@ -349,6 +357,17 @@ export function parseSequenceDiagram(lines: string[]): SequenceDiagram {
349
357
  continue
350
358
  }
351
359
 
360
+ // --- Unmatched end ---
361
+ // Neither branch above claimed this "end" — no box and no block is
362
+ // currently open, so there's nothing for it to close. Previously
363
+ // silently ignored (#762); mirrors the "box cannot be nested" throw
364
+ // above in surfacing a structural mistake instead of dropping it.
365
+ if (line === 'end') {
366
+ throw new Error(
367
+ `Line ${stmt.line}: Sequence diagram: "end" does not match any open block ("loop"/"alt"/"opt"/"par"/"critical"/"break"/"rect") or "box" — nothing is currently open to close.`,
368
+ )
369
+ }
370
+
352
371
  // --- Standalone activate / deactivate ---
353
372
  // "activate A" / "deactivate A". Mermaid's own grammar expands the `+`/`-`
354
373
  // arrow shorthand into exactly this (message, then an activeStart for the
@@ -361,7 +380,7 @@ export function parseSequenceDiagram(lines: string[]): SequenceDiagram {
361
380
  const activationMatch = line.match(/^(activate|deactivate)\s+(.+)$/)
362
381
  if (activationMatch) {
363
382
  const actorId = activationMatch[2]!.trim()
364
- ensureActor(diagram, actorIds, boxCtx, actorId)
383
+ ensureActor(diagram, actorIds, boxCtx, actorId, stmt.line)
365
384
  diagram.activations.push({
366
385
  actorId,
367
386
  kind: activationMatch[1] === 'activate' ? 'start' : 'end',
@@ -403,6 +422,22 @@ export function parseSequenceDiagram(lines: string[]): SequenceDiagram {
403
422
  const msgMatch =
404
423
  line.match(MESSAGE_LONG_ARROW_RE) ?? line.match(MESSAGE_ANY_ARROW_RE)
405
424
  if (msgMatch) {
425
+ // Mermaid's own unquoted actor-name grammar excludes `>` and `)` from
426
+ // ever starting an identifier (see the FROM/TO comment above) — so a
427
+ // TO capture starting with either one means the real arrow in the
428
+ // source is longer than what the alternation above actually matched
429
+ // (e.g. "->>>" only matches as "->>", leaving a stray ">" to be
430
+ // absorbed into TO as part of a garbled actor name) rather than a
431
+ // genuinely valid, if unusual, message. Reject it with an actionable
432
+ // error instead of silently minting that garbled actor — see the
433
+ // `Alice->>>Bob: Hello` example in issue #762.
434
+ const arrowToken = msgMatch[2]!
435
+ const toFirstChar = msgMatch[4]![0]
436
+ if (toFirstChar === '>' || toFirstChar === ')') {
437
+ throw new Error(
438
+ `Line ${stmt.line}: Malformed sequence-diagram arrow in "${line}" — "${arrowToken}${toFirstChar}" is not a recognized arrow. Expected one of: ->, -->, ->>, -->>, -x, --x, -), --), <<->>, <<-->>.`,
439
+ )
440
+ }
406
441
  pushMessage(
407
442
  diagram,
408
443
  actorIds,
@@ -413,13 +448,14 @@ export function parseSequenceDiagram(lines: string[]): SequenceDiagram {
413
448
  msgMatch[3],
414
449
  msgMatch[4]!,
415
450
  msgMatch[5]!,
451
+ stmt.line,
416
452
  )
417
453
  const msgIndex = diagram.messages.length - 1
418
454
  const msg = diagram.messages[msgIndex]!
419
455
  if (pendingCreate !== undefined) {
420
456
  if (msg.to !== pendingCreate) {
421
457
  throw new Error(
422
- `The created participant ${pendingCreate} does not have an associated creating message after its declaration. Please check the sequence diagram.`,
458
+ `Line ${stmt.line}: The created participant ${pendingCreate} does not have an associated creating message after its declaration. Please check the sequence diagram.`,
423
459
  )
424
460
  }
425
461
  findActor(diagram, pendingCreate).createdAt = msgIndex
@@ -428,7 +464,7 @@ export function parseSequenceDiagram(lines: string[]): SequenceDiagram {
428
464
  if (pendingDestroy !== undefined) {
429
465
  if (msg.from !== pendingDestroy && msg.to !== pendingDestroy) {
430
466
  throw new Error(
431
- `The destroyed participant ${pendingDestroy} does not have an associated destroying message after its declaration. Please check the sequence diagram.`,
467
+ `Line ${stmt.line}: The destroyed participant ${pendingDestroy} does not have an associated destroying message after its declaration. Please check the sequence diagram.`,
432
468
  )
433
469
  }
434
470
  findActor(diagram, pendingDestroy).destroyedAt = msgIndex
@@ -438,6 +474,25 @@ export function parseSequenceDiagram(lines: string[]): SequenceDiagram {
438
474
  }
439
475
  }
440
476
 
477
+ // A block/box left open at EOF is a structural mistake, not something to
478
+ // silently accept as "closed by end of input" — mirrors the class-diagram
479
+ // parser's unclosed-body check (#761) for the same reason: previously
480
+ // this was silently ignored (#762). Checked innermost-first (the block
481
+ // stack) since an unclosed block is the more specific, more actionable
482
+ // thing to report when both are open.
483
+ if (blockStack.length > 0) {
484
+ const unclosed = blockStack[blockStack.length - 1]!
485
+ throw new Error(
486
+ `Line ${unclosed.line}: Sequence diagram: unclosed "${unclosed.type}" block — expected a matching "end" before the diagram ends.`,
487
+ )
488
+ }
489
+ if (boxCtx.open !== undefined) {
490
+ const openBox = diagram.boxes[boxCtx.open]!
491
+ throw new Error(
492
+ `Line ${boxOpenLine}: Sequence diagram: unclosed "box${openBox.label ? ` ${openBox.label}` : ''}" — expected a matching "end" before the diagram ends.`,
493
+ )
494
+ }
495
+
441
496
  return diagram
442
497
  }
443
498
 
@@ -461,12 +516,13 @@ function ensureActor(
461
516
  actorIds: Set<string>,
462
517
  boxCtx: BoxContext,
463
518
  id: string,
519
+ lineNumber: number,
464
520
  ): void {
465
521
  if (!actorIds.has(id)) {
466
522
  actorIds.add(id)
467
523
  diagram.actors.push({ id, label: id, type: 'participant' })
468
524
  }
469
- joinOpenBox(diagram, boxCtx, id)
525
+ joinOpenBox(diagram, boxCtx, id, lineNumber)
470
526
  }
471
527
 
472
528
  /**
@@ -478,6 +534,7 @@ function joinOpenBox(
478
534
  diagram: SequenceDiagram,
479
535
  boxCtx: BoxContext,
480
536
  id: string,
537
+ lineNumber: number,
481
538
  ): void {
482
539
  const open = boxCtx.open
483
540
  if (open === undefined) return
@@ -487,7 +544,7 @@ function joinOpenBox(
487
544
  const from = diagram.boxes[existing]!.label
488
545
  const to = diagram.boxes[open]!.label
489
546
  throw new Error(
490
- `A same participant should only be defined in one Box: ${id} can't be in '${from}' and in '${to}' at the same time.`,
547
+ `Line ${lineNumber}: A same participant should only be defined in one Box: ${id} can't be in '${from}' and in '${to}' at the same time.`,
491
548
  )
492
549
  }
493
550
  boxCtx.membership.set(id, open)
@@ -510,9 +567,10 @@ function pushMessage(
510
567
  activationMark: string | undefined,
511
568
  to: string,
512
569
  rawLabel: string,
570
+ lineNumber: number,
513
571
  ): void {
514
- ensureActor(diagram, actorIds, boxCtx, from)
515
- ensureActor(diagram, actorIds, boxCtx, to)
572
+ ensureActor(diagram, actorIds, boxCtx, from, lineNumber)
573
+ ensureActor(diagram, actorIds, boxCtx, to, lineNumber)
516
574
 
517
575
  const bidirectional = arrow === '<<->>' || arrow === '<<-->>'
518
576
  const lineStyle = bidirectional
@@ -1,4 +1,5 @@
1
1
  import type { XYChart, XYAxis, XYChartSeries } from './types.ts'
2
+ import type { Statement } from '@zombie-mermaid/core'
2
3
 
3
4
  // ============================================================================
4
5
  // XY Chart parser
@@ -21,14 +22,15 @@ import type { XYChart, XYAxis, XYChartSeries } from './types.ts'
21
22
  * Parse a Mermaid xychart-beta diagram from preprocessed lines.
22
23
  * Lines should already be trimmed and comment-stripped.
23
24
  */
24
- export function parseXYChart(lines: string[]): XYChart {
25
+ export function parseXYChart(lines: Statement[]): XYChart {
25
26
  const xAxis: XYAxis = {}
26
27
  const yAxis: XYAxis = {}
27
28
  const series: XYChartSeries[] = []
28
29
  let title: string | undefined
29
30
  let horizontal = false
30
31
 
31
- for (const line of lines) {
32
+ for (const stmt of lines) {
33
+ const line = stmt.text
32
34
  // Header line — detect horizontal
33
35
  if (/^xychart(-beta)?\b/i.test(line)) {
34
36
  if (/\bhorizontal\b/i.test(line)) horizontal = true
@@ -86,16 +88,42 @@ export function parseXYChart(lines: string[]): XYChart {
86
88
  // bar [...]
87
89
  const barMatch = line.match(/^bar\s+\[([^\]]+)\]/)
88
90
  if (barMatch) {
89
- series.push({ type: 'bar', data: parseNumericArray(barMatch[1]!) })
91
+ series.push({
92
+ type: 'bar',
93
+ data: parseNumericArray(barMatch[1]!, 'bar', line, stmt.line),
94
+ })
90
95
  continue
91
96
  }
92
97
 
93
98
  // line [...]
94
99
  const lineMatch = line.match(/^line\s+\[([^\]]+)\]/)
95
100
  if (lineMatch) {
96
- series.push({ type: 'line', data: parseNumericArray(lineMatch[1]!) })
101
+ series.push({
102
+ type: 'line',
103
+ data: parseNumericArray(lineMatch[1]!, 'line', line, stmt.line),
104
+ })
97
105
  continue
98
106
  }
107
+
108
+ // None of the recognized directive shapes matched. A line that doesn't
109
+ // start with any known xychart-beta keyword at all falls through
110
+ // silently below, same as before — but a line that *does* start with
111
+ // one of the five keyworded directives (x-axis/y-axis/bar/line/title)
112
+ // and still failed every pattern above is almost certainly an attempt
113
+ // at that directive with broken syntax (an unclosed bracket, a missing
114
+ // quote, a malformed range). Previously this was silently dropped —
115
+ // the diagram would render with that axis/series just missing and no
116
+ // indication why. Surface an actionable error instead. See issue #541
117
+ // (parser error-message quality audit — this parser had zero throw
118
+ // sites before this pass).
119
+ const keywordMatch = line.match(/^(x-axis|y-axis|bar|line|title)\b/i)
120
+ if (keywordMatch) {
121
+ throw malformedDirectiveError(
122
+ keywordMatch[1]!.toLowerCase(),
123
+ line,
124
+ stmt.line,
125
+ )
126
+ }
99
127
  }
100
128
 
101
129
  // Auto-derive y-axis range from data if not specified
@@ -120,6 +148,56 @@ export function parseXYChart(lines: string[]): XYChart {
120
148
  return { title, horizontal, xAxis, yAxis, series }
121
149
  }
122
150
 
123
- function parseNumericArray(str: string): number[] {
124
- return str.split(',').map((s) => parseFloat(s.trim()))
151
+ /**
152
+ * Parse a `bar`/`line` series' comma-separated bracket contents into
153
+ * numbers, throwing on any element that isn't a valid number instead of
154
+ * silently coercing it to `NaN` (which serializes as `null` and can
155
+ * propagate into layout math with no indication anything was wrong — see
156
+ * issue #541's audit finding on this exact parser).
157
+ */
158
+ function parseNumericArray(
159
+ str: string,
160
+ seriesType: 'bar' | 'line',
161
+ line: string,
162
+ lineNumber: number,
163
+ ): number[] {
164
+ return str.split(',').map((raw, index) => {
165
+ const trimmed = raw.trim()
166
+ const value = parseFloat(trimmed)
167
+ if (trimmed.length === 0 || Number.isNaN(value)) {
168
+ throw new Error(
169
+ `Line ${lineNumber}: Invalid numeric value ${JSON.stringify(trimmed)} at position ${
170
+ index + 1
171
+ } in "${line}". Every value in a ${seriesType} [...] list must be a number.`,
172
+ )
173
+ }
174
+ return value
175
+ })
176
+ }
177
+
178
+ /** Expected-syntax hint per xychart-beta keyword, for `malformedDirectiveError`. */
179
+ const XYCHART_DIRECTIVE_HELP: Record<string, string> = {
180
+ 'x-axis':
181
+ 'x-axis [A, B, C] (categories) or x-axis 0 --> 100 (numeric range), either optionally preceded by a quoted title',
182
+ 'y-axis':
183
+ 'y-axis 0 --> 100 (numeric range) or y-axis "Title" (title only), optionally preceded by a quoted title before a range',
184
+ bar: 'bar [10, 20, 30] — a comma-separated numeric array in square brackets',
185
+ line: 'line [10, 20, 30] — a comma-separated numeric array in square brackets',
186
+ title: 'title "Chart Title" — a double-quoted string',
187
+ }
188
+
189
+ /**
190
+ * Build the error for a line that starts with a recognized xychart-beta
191
+ * keyword (x-axis/y-axis/bar/line/title) but doesn't match that keyword's
192
+ * expected syntax in any of the forms this parser supports.
193
+ */
194
+ function malformedDirectiveError(
195
+ keyword: string,
196
+ line: string,
197
+ lineNumber: number,
198
+ ): Error {
199
+ const help = XYCHART_DIRECTIVE_HELP[keyword] ?? keyword
200
+ return new Error(
201
+ `Line ${lineNumber}: Malformed xychart-beta "${keyword}" directive: "${line}". Expected: ${help}.`,
202
+ )
125
203
  }
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Craft Docs
4
+ Copyright (c) 2026 Dustin Fadler
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
@@ -16,23 +16,27 @@ import type {
16
16
  PositionedClassNode,
17
17
  PositionedClassNote,
18
18
  PositionedClassRelationship,
19
- } from './types.ts'
20
- import { formatClassMember } from './format.ts'
19
+ } from '@zombie-mermaid/mermaid-parser'
20
+ import { formatClassMember } from '@zombie-mermaid/mermaid-parser'
21
21
  import type { ClassRenderOptions } from '@zombie-mermaid/core'
22
22
  import {
23
23
  estimateTextWidth,
24
24
  estimateMonoTextWidth,
25
25
  FONT_WEIGHTS,
26
26
  resolveFontSizes,
27
- elkLayoutSync,
27
+ } from '../styles.ts'
28
+ import { elkLayoutSync } from '../elk-instance.ts'
29
+ import {
28
30
  extractEdgePoints,
29
31
  extractEdgeLabelPosition,
32
+ } from '../layout-engine/elk-adapter-utils.ts'
33
+ import {
30
34
  ELK_DIRECTION_FALLBACK,
31
35
  baseElkLayoutOptions,
32
36
  buildElkEdge,
33
37
  buildElkLeafNode,
34
38
  directionToElk,
35
- } from '@zombie-mermaid/svg-renderer'
39
+ } from '../layout-engine/elk-graph-builder.ts'
36
40
  import { measureMultilineText, resolveNodeStyle } from '@zombie-mermaid/core'
37
41
 
38
42
  /** Layout constants for class diagrams */
@@ -5,7 +5,7 @@ import type {
5
5
  PositionedClassRelationship,
6
6
  ClassMember,
7
7
  RelationshipType,
8
- } from './types.ts'
8
+ } from '@zombie-mermaid/mermaid-parser'
9
9
  import type { DiagramColors, SvgEmitOptions } from '@zombie-mermaid/core'
10
10
  import {
11
11
  svgOpenTag,
@@ -17,14 +17,14 @@ import {
17
17
  escapeAttr,
18
18
  safeHref,
19
19
  } from '@zombie-mermaid/core'
20
+ import { withDataSrc } from '../renderer.ts'
20
21
  import {
21
- withDataSrc,
22
22
  FONT_SIZES,
23
23
  FONT_WEIGHTS,
24
24
  STROKE_WIDTHS,
25
25
  TEXT_BASELINE_SHIFT,
26
- } from '@zombie-mermaid/svg-renderer'
27
- import type { FontSizes } from '@zombie-mermaid/svg-renderer'
26
+ } from '../styles.ts'
27
+ import type { FontSizes } from '../styles.ts'
28
28
  import { CLS } from './layout.ts'
29
29
 
30
30
  // ============================================================================
@@ -61,7 +61,8 @@ const CLS_FONT = {
61
61
  * @param decorative - Marks the SVG decorative (from `options.decorative`).
62
62
  * @param linksEnabled - Whether `click`-based `<a href>` links and `<title>`
63
63
  * tooltips render (from `options.interactivity !==
64
- * 'none'`, see `resolveLinksEnabled` in src/index.ts).
64
+ * 'none'`, see `resolveLinksEnabled` in
65
+ * src/diagram-registry.ts).
65
66
  * Default true — matches the flowchart/state renderer.
66
67
  * @param emit - Strict-CSP controls (from `options.nonce` /
67
68
  * `options.styleAttribute`, see #216). Default: no nonce,
@@ -399,7 +400,7 @@ const NOTE_FOLD = 6
399
400
  /**
400
401
  * Render a note as a dog-eared box: a polygon with its top-right corner
401
402
  * clipped plus a small fold triangle — the same shape the sequence renderer
402
- * draws for its notes (src/sequence/renderer.ts renderNote), so notes look
403
+ * draws for its notes (../sequence/renderer.ts renderNote), so notes look
403
404
  * alike across diagram types. Wrapped in <g class="class-note"> with
404
405
  * `data-for` naming the class it's attached to, if any.
405
406
  */