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.
- package/LICENSE +1 -0
- package/README.md +7 -2
- package/dist/ascii.cjs +9 -9
- package/dist/ascii.cjs.map +1 -1
- package/dist/ascii.js +4069 -3969
- package/dist/ascii.js.map +1 -1
- package/dist/cli.js +7605 -7381
- package/dist/index.cjs +52 -52
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +7613 -7459
- package/dist/index.js.map +1 -1
- package/dist/mcp.cjs +14142 -13717
- package/dist/mcp.cjs.map +1 -1
- package/dist/mcp.js +14142 -13717
- package/dist/mcp.js.map +1 -1
- package/package.json +27 -5
- package/packages/ascii-renderer/LICENSE +22 -0
- package/{src/ascii → packages/ascii-renderer/src}/class-diagram.ts +277 -57
- package/{src/ascii → packages/ascii-renderer/src}/er-diagram.ts +2 -2
- package/packages/ascii-renderer/src/flowchart.ts +94 -0
- package/{src/ascii → packages/ascii-renderer/src}/grid.ts +23 -0
- package/{src/ascii → packages/ascii-renderer/src}/index.ts +13 -84
- package/{src/ascii → packages/ascii-renderer/src}/registry.ts +23 -12
- package/{src/ascii → packages/ascii-renderer/src}/sequence.ts +55 -8
- package/{src/ascii → packages/ascii-renderer/src}/xychart.ts +6 -3
- package/packages/core/LICENSE +22 -0
- package/packages/core/src/click-directive.ts +106 -0
- package/packages/core/src/color-utils.ts +205 -0
- package/packages/core/src/diagram-type.ts +35 -0
- package/packages/core/src/direction-override.ts +46 -0
- package/packages/core/src/direction.ts +56 -0
- package/packages/core/src/index.ts +34 -0
- package/packages/core/src/init-directive.ts +248 -0
- package/packages/core/src/multiline-utils.ts +275 -0
- package/packages/core/src/statements.ts +197 -0
- package/packages/core/src/style-directives.ts +214 -0
- package/packages/core/src/text-metrics.ts +498 -0
- package/packages/core/src/theme.ts +696 -0
- package/packages/core/src/types.ts +670 -0
- package/packages/mcp/LICENSE +22 -0
- package/{src/mcp → packages/mcp/src}/server.ts +34 -2
- package/{src/mcp → packages/mcp/src}/tools/check-sequence-activations.ts +8 -5
- package/packages/mcp/src/tools/fix-sequence-activations.ts +77 -0
- package/{src/mcp → packages/mcp/src}/tools/render-ascii.ts +2 -2
- package/{src/mcp → packages/mcp/src}/tools/render-svg.ts +1 -1
- package/packages/mermaid-parser/LICENSE +22 -0
- package/{src → packages/mermaid-parser/src}/class/parser.ts +86 -8
- package/{src → packages/mermaid-parser/src}/er/parser.ts +59 -26
- package/packages/mermaid-parser/src/index.ts +48 -0
- package/{src → packages/mermaid-parser/src}/sequence/activation-check.ts +4 -3
- package/packages/mermaid-parser/src/sequence/activation-fix.ts +112 -0
- package/{src → packages/mermaid-parser/src}/sequence/parser.ts +74 -16
- package/{src → packages/mermaid-parser/src}/xychart/parser.ts +84 -6
- package/packages/svg-renderer/LICENSE +22 -0
- package/{src → packages/svg-renderer/src}/class/layout.ts +8 -4
- package/{src → packages/svg-renderer/src}/class/renderer.ts +7 -6
- package/packages/svg-renderer/src/edge-curves.ts +204 -0
- package/packages/svg-renderer/src/elk-instance.ts +292 -0
- package/{src → packages/svg-renderer/src}/er/layout.ts +6 -4
- package/{src → packages/svg-renderer/src}/er/renderer.ts +4 -4
- package/packages/svg-renderer/src/index.ts +58 -0
- package/packages/svg-renderer/src/layout-engine/constants.ts +19 -0
- package/packages/svg-renderer/src/layout-engine/edge-bundling.ts +379 -0
- package/packages/svg-renderer/src/layout-engine/elk-adapter-utils.ts +81 -0
- package/packages/svg-renderer/src/layout-engine/elk-graph-builder.ts +240 -0
- package/packages/svg-renderer/src/layout-engine/from-elk.ts +685 -0
- package/packages/svg-renderer/src/layout-engine/layer-alignment.ts +174 -0
- package/packages/svg-renderer/src/layout-engine/to-elk.ts +695 -0
- package/packages/svg-renderer/src/layout-engine.ts +74 -0
- package/packages/svg-renderer/src/layout.ts +8 -0
- package/packages/svg-renderer/src/renderer.ts +1485 -0
- package/packages/svg-renderer/src/resolve-colors.ts +339 -0
- package/{src → packages/svg-renderer/src}/sequence/layout.ts +2 -6
- package/{src → packages/svg-renderer/src}/sequence/renderer.ts +4 -4
- package/packages/svg-renderer/src/shape-clipping.ts +197 -0
- package/packages/svg-renderer/src/styles.ts +118 -0
- package/{src → packages/svg-renderer/src}/xychart/layout.ts +2 -2
- package/{src → packages/svg-renderer/src}/xychart/renderer.ts +6 -6
- package/src/__tests__/ascii-ansi.test.ts +6 -2
- package/src/__tests__/ascii-canvas-write.test.ts +2 -2
- package/src/__tests__/ascii-charset-border-junctions.test.ts +1 -1
- package/src/__tests__/ascii-cjk-width.test.ts +1 -1
- package/src/__tests__/ascii-class-box-occupancy.test.ts +147 -45
- package/src/__tests__/ascii-class-column-width-488-489.test.ts +1 -1
- package/src/__tests__/ascii-class-cross-level-jog-corruption.test.ts +187 -0
- package/src/__tests__/ascii-class-detour-label-routing-487.test.ts +1 -1
- package/src/__tests__/ascii-class-diagram-compartments.test.ts +1 -1
- package/src/__tests__/ascii-class-label-box-collision.test.ts +1 -1
- package/src/__tests__/ascii-class-label-row-collision-531.test.ts +1 -1
- package/src/__tests__/ascii-class-label-territory-row-awareness.test.ts +1 -1
- package/src/__tests__/ascii-class-padding.test.ts +1 -1
- package/src/__tests__/ascii-class-reciprocal-relationships-448.test.ts +86 -1
- package/src/__tests__/ascii-combining-mark-width.test.ts +2 -2
- package/src/__tests__/ascii-coords-overlay.test.ts +2 -2
- package/src/__tests__/ascii-decision-lr-box-start.test.ts +2 -2
- package/src/__tests__/ascii-display-width-unit.test.ts +1 -1
- package/src/__tests__/ascii-draw-arrows-coverage.test.ts +1 -1
- package/src/__tests__/ascii-draw-arrows-single-point-path.test.ts +12 -5
- package/src/__tests__/ascii-draw-bundles.test.ts +5 -5
- package/src/__tests__/ascii-edge-bundling-rank-violation-454.test.ts +1 -1
- package/src/__tests__/ascii-edge-bundling-routing.test.ts +9 -5
- package/src/__tests__/ascii-edge-cross-style-overlap.test.ts +10 -6
- package/src/__tests__/ascii-edge-ending-glyphs.test.ts +1 -1
- package/src/__tests__/ascii-edge-label-diagonal-fallback-418.test.ts +2 -2
- package/src/__tests__/ascii-edge-routing-fixes.test.ts +1 -1
- package/src/__tests__/ascii-edge-routing-single-point-path.test.ts +8 -4
- package/src/__tests__/ascii-edge-styles.test.ts +1 -1
- package/src/__tests__/ascii-emoji-cluster-width.test.ts +2 -2
- package/src/__tests__/ascii-er-box-occupancy.test.ts +1 -1
- package/src/__tests__/ascii-er-cardinality.test.ts +1 -1
- package/src/__tests__/ascii-er-corner-glyphs.test.ts +1 -1
- package/src/__tests__/ascii-er-jog-stray-line.test.ts +1 -1
- package/src/__tests__/ascii-er-label-padding.test.ts +1 -1
- package/src/__tests__/ascii-er-padding.test.ts +1 -1
- package/src/__tests__/ascii-er-relationship-label-corruption-350.test.ts +1 -1
- package/src/__tests__/ascii-er-relationship-overwrite.test.ts +1 -1
- package/src/__tests__/ascii-er-stray-connectors.test.ts +7 -4
- package/src/__tests__/ascii-er-unrelated-stem-separation-411.test.ts +1 -1
- package/src/__tests__/ascii-er-vertical-one-marker.test.ts +1 -1
- package/src/__tests__/ascii-grid-deep-chain.test.ts +4 -4
- package/src/__tests__/ascii-hyperlinks.test.ts +9 -6
- package/src/__tests__/ascii-label-line-terminal-fallback.test.ts +8 -4
- package/src/__tests__/ascii-lane-search.test.ts +1 -1
- package/src/__tests__/ascii-multibox-cjk-width.test.ts +1 -1
- package/src/__tests__/ascii-multiline.test.ts +6 -3
- package/src/__tests__/ascii-nested-subgraph-sibling-order-444.test.ts +8 -5
- package/src/__tests__/ascii-package-boundary.test.ts +47 -37
- package/src/__tests__/ascii-padding-edge-cases.test.ts +1 -1
- package/src/__tests__/ascii-parallel-edges-329.test.ts +8 -5
- package/src/__tests__/ascii-pathfinder-route-edge.test.ts +14 -4
- package/src/__tests__/ascii-reverse-direction-edges-629.test.ts +9 -5
- package/src/__tests__/ascii-sequence-alt-else-label.test.ts +1 -1
- package/src/__tests__/ascii-sequence-block-wall-clearance.test.ts +1 -1
- package/src/__tests__/ascii-sequence-box-group.test.ts +1 -1
- package/src/__tests__/ascii-sequence-cjk-width.test.ts +1 -1
- package/src/__tests__/ascii-sequence-create-destroy.test.ts +1 -1
- package/src/__tests__/ascii-sequence-form-invariants.test.ts +48 -50
- package/src/__tests__/ascii-sequence-mermaid-parity.test.ts +1 -1
- package/src/__tests__/ascii-sequence-notes.test.ts +1 -1
- package/src/__tests__/ascii-sequence-padding.test.ts +1 -1
- package/src/__tests__/ascii-sequence-self-arrow.test.ts +1 -1
- package/src/__tests__/ascii-shape-diamond.test.ts +3 -3
- package/src/__tests__/ascii-shape-rectangle.test.ts +5 -5
- package/src/__tests__/ascii-shape-rounded.test.ts +3 -3
- package/src/__tests__/ascii-shapes-circle.test.ts +3 -3
- package/src/__tests__/ascii-shapes-hexagon.test.ts +3 -3
- package/src/__tests__/ascii-shapes-special.test.ts +10 -5
- package/src/__tests__/ascii-shapes-stadium.test.ts +3 -3
- package/src/__tests__/ascii-shapes-state.test.ts +15 -5
- package/src/__tests__/ascii-state-bidirectional-label-swap-530.test.ts +1 -1
- package/src/__tests__/ascii-subgraph-bbox.test.ts +8 -4
- package/src/__tests__/ascii-subgraph-direction-honored-445.test.ts +1 -1
- package/src/__tests__/ascii-subgraph-label-border-clip.test.ts +88 -25
- package/src/__tests__/ascii-subgraph-later-edgeless-301.test.ts +8 -4
- package/src/__tests__/ascii-subgraph-title-padding.test.ts +1 -1
- package/src/__tests__/ascii-territory-unit.test.ts +2 -2
- package/src/__tests__/ascii-validate.test.ts +1 -1
- package/src/__tests__/ascii.test.ts +5 -2
- package/src/__tests__/box-color.test.ts +1 -1
- package/src/__tests__/class-arrow-directions.test.ts +1 -1
- package/src/__tests__/class-click-interactions.test.ts +3 -6
- package/src/__tests__/class-integration.test.ts +1 -1
- package/src/__tests__/class-notes.test.ts +3 -3
- package/src/__tests__/class-parser-error-messages.test.ts +162 -0
- package/src/__tests__/class-parser.test.ts +6 -6
- package/src/__tests__/class-styling.test.ts +2 -2
- package/src/__tests__/cli-render.test.ts +16 -1
- package/src/__tests__/direction-override.test.ts +1 -1
- package/src/__tests__/draw-lines.test.ts +2 -2
- package/src/__tests__/edge-cell-styles.test.ts +5 -2
- package/src/__tests__/elk-layout-cache.test.ts +6 -4
- package/src/__tests__/er-click-unsupported.test.ts +5 -8
- package/src/__tests__/er-parser-error-messages.test.ts +82 -0
- package/src/__tests__/er-parser.test.ts +3 -6
- package/src/__tests__/expanded-shapes.test.ts +1 -1
- package/src/__tests__/grid-occupancy.test.ts +1 -1
- package/src/__tests__/mcp-check-sequence-activations-tool.test.ts +1 -1
- package/src/__tests__/mcp-fix-sequence-activations-tool.test.ts +134 -0
- package/src/__tests__/mcp-render-ascii-tool.test.ts +5 -4
- package/src/__tests__/mcp-render-svg-theme-guard.test.ts +3 -3
- package/src/__tests__/mcp-render-svg-tool.test.ts +1 -1
- package/src/__tests__/mcp-server.test.ts +30 -1
- package/src/__tests__/multiline-labels.test.ts +29 -18
- package/src/__tests__/parser.test.ts +117 -5
- package/src/__tests__/pathfinder.test.ts +11 -4
- package/src/__tests__/render-options-overrides.test.ts +28 -21
- package/src/__tests__/render-options-per-type.test.ts +13 -9
- package/src/__tests__/resolve-colors.test.ts +1 -1
- package/src/__tests__/self-loop-edges.test.ts +112 -0
- package/src/__tests__/sequence-activation-check.test.ts +7 -8
- package/src/__tests__/sequence-activation-fix.test.ts +91 -0
- package/src/__tests__/sequence-layout.test.ts +4 -7
- package/src/__tests__/sequence-parser-syntax-errors.test.ts +179 -0
- package/src/__tests__/sequence-parser.test.ts +3 -6
- package/src/__tests__/statements.test.ts +53 -35
- package/src/__tests__/testdata/ascii/subgraph_direction_override.txt +21 -21
- package/src/__tests__/theme-palette-contrast.test.ts +84 -0
- package/src/__tests__/workspace-package-boundaries.test.ts +199 -25
- package/src/__tests__/xychart-ascii.test.ts +1 -1
- package/src/__tests__/xychart-colors.test.ts +3 -2
- package/src/__tests__/xychart-layout.test.ts +1 -1
- package/src/__tests__/xychart-parser-errors.test.ts +95 -0
- package/src/browser.ts +8 -2
- package/src/cli/mcp.ts +1 -1
- package/src/cli/render.ts +59 -25
- package/src/cli/web.ts +1 -1
- package/src/diagram-registry.ts +190 -25
- package/src/index.ts +34 -131
- package/src/parser.ts +102 -40
- /package/{src/ascii → packages/ascii-renderer/src}/ansi.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/canvas.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/converter.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/coords.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/display-width.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/draw-arrows.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/draw-boxes.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/draw-bundles.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/draw-lines.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/draw-subgraphs.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/draw.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/edge-bundling.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/edge-cell-styles.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/edge-routing.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/grid-occupancy.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/hyperlinks.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/lane-search.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/multiline-utils.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/pathfinder.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/shapes/circle.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/shapes/corners.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/shapes/diamond.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/shapes/hexagon.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/shapes/index.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/shapes/rectangle.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/shapes/rounded.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/shapes/special.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/shapes/stadium.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/shapes/state.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/shapes/types.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/territory.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/types.ts +0 -0
- /package/{src/ascii → packages/ascii-renderer/src}/validate.ts +0 -0
- /package/{src/mcp → packages/mcp/src}/index.ts +0 -0
- /package/{src → packages/mermaid-parser/src}/class/format.ts +0 -0
- /package/{src → packages/mermaid-parser/src}/class/types.ts +0 -0
- /package/{src → packages/mermaid-parser/src}/er/types.ts +0 -0
- /package/{src → packages/mermaid-parser/src}/expanded-shapes.ts +0 -0
- /package/{src → packages/mermaid-parser/src}/sequence/box-color.ts +0 -0
- /package/{src → packages/mermaid-parser/src}/sequence/types.ts +0 -0
- /package/{src → packages/mermaid-parser/src}/xychart/colors.ts +0 -0
- /package/{src → packages/mermaid-parser/src}/xychart/types.ts +0 -0
package/src/index.ts
CHANGED
|
@@ -37,17 +37,17 @@ export { fromShikiTheme, THEMES, DEFAULTS } from '@zombie-mermaid/core'
|
|
|
37
37
|
export { parseMermaid } from './parser.ts'
|
|
38
38
|
import {
|
|
39
39
|
resolveCssColors,
|
|
40
|
-
layoutGraphSync,
|
|
41
|
-
renderSvg,
|
|
42
40
|
resolveFontSizes,
|
|
43
41
|
} from '@zombie-mermaid/svg-renderer'
|
|
44
|
-
export {
|
|
45
|
-
|
|
42
|
+
export {
|
|
43
|
+
renderMermaidASCII,
|
|
44
|
+
renderMermaidAscii,
|
|
45
|
+
} from '@zombie-mermaid/ascii-renderer'
|
|
46
|
+
export type { AsciiRenderOptions } from '@zombie-mermaid/ascii-renderer'
|
|
46
47
|
export { createLayoutCache } from '@zombie-mermaid/svg-renderer'
|
|
47
48
|
export type { LayoutCache } from '@zombie-mermaid/svg-renderer'
|
|
48
49
|
|
|
49
50
|
import { decodeXML } from 'entities'
|
|
50
|
-
import { parseMermaid } from './parser.ts'
|
|
51
51
|
import type {
|
|
52
52
|
RenderOptions,
|
|
53
53
|
DiagramColors,
|
|
@@ -60,17 +60,9 @@ import {
|
|
|
60
60
|
isMonospaceFont,
|
|
61
61
|
setMonospaceMetrics,
|
|
62
62
|
detectDiagramType,
|
|
63
|
-
applyInitConfig,
|
|
64
|
-
withDirectionOverride,
|
|
65
63
|
splitStatements,
|
|
66
64
|
} from '@zombie-mermaid/core'
|
|
67
65
|
|
|
68
|
-
import { parseSequenceDiagram } from './sequence/parser.ts'
|
|
69
|
-
import { layoutSequenceDiagram } from './sequence/layout.ts'
|
|
70
|
-
import { renderSequenceSvg } from './sequence/renderer.ts'
|
|
71
|
-
import { parseClassDiagram } from './class/parser.ts'
|
|
72
|
-
import { layoutClassDiagramSync } from './class/layout.ts'
|
|
73
|
-
import { renderClassSvg } from './class/renderer.ts'
|
|
74
66
|
import { diagramRegistry } from './diagram-registry.ts'
|
|
75
67
|
import type { SvgRenderContext } from './diagram-registry.ts'
|
|
76
68
|
|
|
@@ -133,42 +125,15 @@ function resolveSvgEmit(options: RenderOptions): SvgEmitOptions {
|
|
|
133
125
|
}
|
|
134
126
|
}
|
|
135
127
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Whether flowchart/state-diagram edge animation (`e1@{ animate: true }`)
|
|
148
|
-
* should render. Gated to `'full'` only — CSS animation is tier-2 *motion*
|
|
149
|
-
* (see docs/decisions/no-script-interactivity.md), so the default
|
|
150
|
-
* (`'static'`, tier 1 + tier 2 minus motion) and `'none'` both render the
|
|
151
|
-
* edge as a still line.
|
|
152
|
-
*/
|
|
153
|
-
function resolveAnimationEnabled(options: RenderOptions): boolean {
|
|
154
|
-
return resolveInteractivity(options) === 'full'
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Whether flowchart `click`-based links (`<a href>`) and `<title>` tooltips
|
|
159
|
-
* should render. Gated behind `interactivity !== 'none'` — `'none'` is meant
|
|
160
|
-
* for print/rasterized output, where a link is meaningless, so it strips
|
|
161
|
-
* both; `'static'` and `'full'` both keep them.
|
|
162
|
-
*/
|
|
163
|
-
function resolveLinksEnabled(options: RenderOptions): boolean {
|
|
164
|
-
return resolveInteractivity(options) !== 'none'
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// Whether xychart hover tooltips should render (`interactivity` wins over
|
|
168
|
-
// the deprecated `interactive` boolean when both are set) now lives next to
|
|
169
|
-
// the xychart registry entry in src/diagram-registry.ts, since xychart's
|
|
170
|
-
// SVG dispatch is fully handled by the registry lookup below — there is no
|
|
171
|
-
// remaining switch case here for it to serve.
|
|
128
|
+
// Interactivity-derived render gates — whether xychart hover tooltips
|
|
129
|
+
// render, whether flowchart/state edge animation (`e1@{ animate: true }`)
|
|
130
|
+
// plays, and whether `click`-based links/`<title>` tooltips render — all
|
|
131
|
+
// now live next to their diagram type's registry entry in
|
|
132
|
+
// src/diagram-registry.ts (`resolveAnimationEnabled`/`resolveLinksEnabled`
|
|
133
|
+
// there, duplicated rather than imported since that module is imported BY
|
|
134
|
+
// this file — see those functions' own comments for why), since every
|
|
135
|
+
// diagram type's SVG dispatch is fully handled by the registry lookup
|
|
136
|
+
// below and there is no remaining switch case here for them to serve.
|
|
172
137
|
|
|
173
138
|
/**
|
|
174
139
|
* Render Mermaid diagram text to an SVG string — synchronously.
|
|
@@ -247,90 +212,28 @@ function renderMermaidSVGRaw(text: string, options: RenderOptions): string {
|
|
|
247
212
|
|
|
248
213
|
const lines = splitStatements(decoded)
|
|
249
214
|
|
|
250
|
-
// Registry
|
|
251
|
-
//
|
|
252
|
-
//
|
|
253
|
-
//
|
|
254
|
-
//
|
|
215
|
+
// Registry dispatch (see src/diagram-registry.ts — issue #533 / #745):
|
|
216
|
+
// every diagram type, including 'flowchart' (and the 'state' pipeline it
|
|
217
|
+
// shares), is registered there and handled identically to how each
|
|
218
|
+
// type's original switch case (or, for 'flowchart', its inline fallback)
|
|
219
|
+
// used to read, just via the shared adapter shape instead. `parse` takes
|
|
220
|
+
// both `lines` (what every already-registered type's parser wants) and
|
|
221
|
+
// `decoded` (the raw text flowchart/state's parser needs instead — see
|
|
222
|
+
// the `parse` doc comment on `DiagramModule`).
|
|
255
223
|
const registered = diagramRegistry[diagramType]
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
emit,
|
|
268
|
-
}
|
|
269
|
-
return registered.renderSvg(positioned, ctx, options)
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
switch (diagramType) {
|
|
273
|
-
case 'sequence': {
|
|
274
|
-
const diagram = parseSequenceDiagram(lines)
|
|
275
|
-
const positioned = layoutSequenceDiagram(diagram, options)
|
|
276
|
-
return renderSequenceSvg(
|
|
277
|
-
positioned,
|
|
278
|
-
colors,
|
|
279
|
-
font,
|
|
280
|
-
transparent,
|
|
281
|
-
fontSizes,
|
|
282
|
-
embedSource,
|
|
283
|
-
title,
|
|
284
|
-
decorative,
|
|
285
|
-
emit,
|
|
286
|
-
)
|
|
287
|
-
}
|
|
288
|
-
case 'class': {
|
|
289
|
-
const diagram = parseClassDiagram(lines)
|
|
290
|
-
const positioned = layoutClassDiagramSync(diagram, options)
|
|
291
|
-
return renderClassSvg(
|
|
292
|
-
positioned,
|
|
293
|
-
colors,
|
|
294
|
-
font,
|
|
295
|
-
transparent,
|
|
296
|
-
fontSizes,
|
|
297
|
-
embedSource,
|
|
298
|
-
title,
|
|
299
|
-
decorative,
|
|
300
|
-
resolveLinksEnabled(options),
|
|
301
|
-
emit,
|
|
302
|
-
)
|
|
303
|
-
}
|
|
304
|
-
case 'flowchart':
|
|
305
|
-
default: {
|
|
306
|
-
const parsed = parseMermaid(decoded)
|
|
307
|
-
// A diagram's own `%%{init: ...}%%` supplies defaults; an explicit
|
|
308
|
-
// render option always wins. See packages/core/src/init-directive.ts.
|
|
309
|
-
const effective = parsed.initConfig
|
|
310
|
-
? applyInitConfig(options, parsed.initConfig)
|
|
311
|
-
: options
|
|
312
|
-
// `direction` replaces the header's (or a state diagram's top-level
|
|
313
|
-
// `direction` line's) direction before layout; nested subgraph /
|
|
314
|
-
// composite-state directions live on the subgraph objects and still
|
|
315
|
-
// apply on top of it. See packages/core/src/direction-override.ts.
|
|
316
|
-
const graph = withDirectionOverride(parsed, effective.direction)
|
|
317
|
-
const positioned = layoutGraphSync(graph, effective)
|
|
318
|
-
return renderSvg(
|
|
319
|
-
positioned,
|
|
320
|
-
colors,
|
|
321
|
-
font,
|
|
322
|
-
transparent,
|
|
323
|
-
fontSizes,
|
|
324
|
-
effective.curve ?? 'linear',
|
|
325
|
-
embedSource,
|
|
326
|
-
resolveAnimationEnabled(options),
|
|
327
|
-
resolveLinksEnabled(options),
|
|
328
|
-
title,
|
|
329
|
-
decorative,
|
|
330
|
-
emit,
|
|
331
|
-
)
|
|
332
|
-
}
|
|
224
|
+
const diagram = registered.parse(lines, decoded)
|
|
225
|
+
const positioned = registered.layoutForSvg(diagram, options)
|
|
226
|
+
const ctx: SvgRenderContext = {
|
|
227
|
+
colors,
|
|
228
|
+
font,
|
|
229
|
+
transparent,
|
|
230
|
+
fontSizes,
|
|
231
|
+
embedSource,
|
|
232
|
+
title,
|
|
233
|
+
decorative,
|
|
234
|
+
emit,
|
|
333
235
|
}
|
|
236
|
+
return registered.renderSvg(positioned, ctx, options)
|
|
334
237
|
}
|
|
335
238
|
|
|
336
239
|
/**
|
package/src/parser.ts
CHANGED
|
@@ -2,14 +2,14 @@ import type {
|
|
|
2
2
|
MermaidGraph,
|
|
3
3
|
MermaidNode,
|
|
4
4
|
MermaidSubgraph,
|
|
5
|
-
Direction,
|
|
6
5
|
NodeShape,
|
|
7
6
|
EdgeStyle,
|
|
7
|
+
Statement,
|
|
8
8
|
} from '@zombie-mermaid/core'
|
|
9
9
|
import {
|
|
10
|
-
|
|
10
|
+
toDirection,
|
|
11
11
|
normalizeBrTags,
|
|
12
|
-
|
|
12
|
+
splitStatementsByLine,
|
|
13
13
|
extractInitConfig,
|
|
14
14
|
applyClickStatement as applyClickStatementShared,
|
|
15
15
|
parseStyleProps,
|
|
@@ -22,8 +22,8 @@ import {
|
|
|
22
22
|
matchExpandedBlock,
|
|
23
23
|
parseExpandedMeta,
|
|
24
24
|
resolveShapeName,
|
|
25
|
-
} from '
|
|
26
|
-
import type { ExpandedNodeMeta } from '
|
|
25
|
+
} from '@zombie-mermaid/mermaid-parser'
|
|
26
|
+
import type { ExpandedNodeMeta } from '@zombie-mermaid/mermaid-parser'
|
|
27
27
|
/** Remove a single layer of matching wrapping quotes (`"…"` or `'…'`). */
|
|
28
28
|
function stripWrappingQuotes(s: string): string {
|
|
29
29
|
const t = s.trim()
|
|
@@ -48,26 +48,15 @@ function stripWrappingQuotes(s: string): string {
|
|
|
48
48
|
// that we don't need a grammar generator or full parser combinator.
|
|
49
49
|
// ============================================================================
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
* see across the call site. Validating `undefined` here, instead of
|
|
61
|
-
* asserting non-null at each call site, turns a hypothetical violation into
|
|
62
|
-
* a clear, descriptive error rather than a raw `undefined` crash.
|
|
63
|
-
*/
|
|
64
|
-
export function toDirection(raw: string | undefined): Direction {
|
|
65
|
-
const upper = raw?.toUpperCase()
|
|
66
|
-
if (upper === undefined || !isDirection(upper)) {
|
|
67
|
-
throw new Error(`Invalid direction: "${raw}"`)
|
|
68
|
-
}
|
|
69
|
-
return upper
|
|
70
|
-
}
|
|
51
|
+
// `toDirection` used to be defined here, with this file as its only caller.
|
|
52
|
+
// #624 gave it a second caller — `packages/mermaid-parser/src/er/parser.ts`,
|
|
53
|
+
// which cannot import this umbrella file without creating a cycle
|
|
54
|
+
// (mermaid-parser -> umbrella -> mermaid-parser) — so it moved to
|
|
55
|
+
// `packages/core/src/direction.ts` alongside `isDirection`, for the same
|
|
56
|
+
// reason that one moved under #625. Re-exported here so existing importers
|
|
57
|
+
// of `toDirection` from `./parser.ts` (this file's own tests included) keep
|
|
58
|
+
// working unchanged.
|
|
59
|
+
export { toDirection } from '@zombie-mermaid/core'
|
|
71
60
|
|
|
72
61
|
/**
|
|
73
62
|
* All diagram-type headers this library recognizes, for the "supported
|
|
@@ -103,6 +92,75 @@ function suggestedHeaderFor(header: string): string | undefined {
|
|
|
103
92
|
return undefined
|
|
104
93
|
}
|
|
105
94
|
|
|
95
|
+
/**
|
|
96
|
+
* Matches the start of a statement that continues the *previous* one's edge
|
|
97
|
+
* chain rather than beginning a new one: Mermaid lets a vertex-chain
|
|
98
|
+
* statement break across lines, with the link operator leading the next
|
|
99
|
+
* line — e.g.
|
|
100
|
+
*
|
|
101
|
+
* start([Start])
|
|
102
|
+
* ==> green([Change some code])
|
|
103
|
+
* ==> finish([Finish])
|
|
104
|
+
*
|
|
105
|
+
* is one chained statement (`start ==> green ==> finish`), identical to
|
|
106
|
+
* writing it on one line. `splitStatementsByLine` only knows about newlines
|
|
107
|
+
* and `;` as separators, so without this it hands `parseFlowchart` three
|
|
108
|
+
* unrelated-looking statements — the continuation lines start with a bare
|
|
109
|
+
* arrow and no node group, so `parseEdgeLine` can't find a source node and
|
|
110
|
+
* drops them entirely (see issue mermaid-js/mermaid#6049's repro, reported
|
|
111
|
+
* against this parser).
|
|
112
|
+
*
|
|
113
|
+
* Covers every arrow opener `parseEdgeLine` itself recognizes (ARROW_REGEX /
|
|
114
|
+
* TEXT_ARROW_REGEX below): a solid/thick run (`--`, `===`), a dotted run
|
|
115
|
+
* (`-.`, `-.-`), a `~~~` run, each optionally preceded by a `<` marker and/or
|
|
116
|
+
* an edge id (`e1@-->`).
|
|
117
|
+
*
|
|
118
|
+
* Deliberately excludes the `o`/`x` start markers ARROW_REGEX also accepts
|
|
119
|
+
* (`o--o`, `x--x`): unlike `<`, both are also valid bare node ids, so a
|
|
120
|
+
* first-body-line statement like `x-->Y` would otherwise be misread as an
|
|
121
|
+
* `x`-marked continuation of the header and merged into it, corrupting the
|
|
122
|
+
* header line (`flowchart TD x-->Y`) instead of parsing `x` as its own node.
|
|
123
|
+
* A genuine marked-start continuation line is rare enough that losing it is
|
|
124
|
+
* the safer tradeoff.
|
|
125
|
+
*/
|
|
126
|
+
const CONTINUATION_START_REGEX = /^(?:[\w-]+@)?<?(?:-{2,}|={2,}|-\.+-?|~{3,})/
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Rejoin a continuation statement onto the one it continues.
|
|
130
|
+
*
|
|
131
|
+
* `splitStatementsByLine` groups statements by their originating physical
|
|
132
|
+
* line, which is what makes this safe: only the *first* statement in a
|
|
133
|
+
* group is eligible to merge backward into the previous group's last
|
|
134
|
+
* statement (a genuine multi-line continuation, see
|
|
135
|
+
* `CONTINUATION_START_REGEX`). A later statement in the same group got
|
|
136
|
+
* there via an explicit `;` on that line (`A --> B; --> C`) — that boundary
|
|
137
|
+
* must stay a boundary, or `--> C` would wrongly become part of the chain
|
|
138
|
+
* instead of the source-less fragment it actually is.
|
|
139
|
+
*/
|
|
140
|
+
function mergeContinuationLines(groups: Statement[][]): Statement[] {
|
|
141
|
+
const merged: Statement[] = []
|
|
142
|
+
for (const group of groups) {
|
|
143
|
+
group.forEach((statement, index) => {
|
|
144
|
+
if (
|
|
145
|
+
index === 0 &&
|
|
146
|
+
merged.length > 0 &&
|
|
147
|
+
CONTINUATION_START_REGEX.test(statement.text)
|
|
148
|
+
) {
|
|
149
|
+
// Keep the *first* line's number: a merged statement is reported at
|
|
150
|
+
// the line its logical statement began, not the continuation line.
|
|
151
|
+
const prev = merged[merged.length - 1]!
|
|
152
|
+
merged[merged.length - 1] = {
|
|
153
|
+
text: `${prev.text} ${statement.text}`,
|
|
154
|
+
line: prev.line,
|
|
155
|
+
}
|
|
156
|
+
} else {
|
|
157
|
+
merged.push(statement)
|
|
158
|
+
}
|
|
159
|
+
})
|
|
160
|
+
}
|
|
161
|
+
return merged
|
|
162
|
+
}
|
|
163
|
+
|
|
106
164
|
/**
|
|
107
165
|
* Parse Mermaid text into a logical graph structure.
|
|
108
166
|
* Auto-detects diagram type (flowchart or state diagram).
|
|
@@ -111,23 +169,23 @@ function suggestedHeaderFor(header: string): string | undefined {
|
|
|
111
169
|
export function parseMermaid(text: string): MermaidGraph {
|
|
112
170
|
/*
|
|
113
171
|
* Init directives must be read from the raw lines: `%%{init: ...}%%` begins
|
|
114
|
-
* with `%%`, so
|
|
172
|
+
* with `%%`, so splitStatementsByLine — which treats `%%` as a comment and
|
|
115
173
|
* truncates the line there — would otherwise discard it along with real
|
|
116
174
|
* comments before it could be seen.
|
|
117
175
|
*/
|
|
118
176
|
const initConfig = extractInitConfig(text.split('\n').map((l) => l.trim()))
|
|
119
177
|
|
|
120
|
-
const lines =
|
|
178
|
+
const lines = mergeContinuationLines(splitStatementsByLine(text))
|
|
121
179
|
|
|
122
180
|
if (lines.length === 0) {
|
|
123
181
|
throw new Error('Empty mermaid diagram')
|
|
124
182
|
}
|
|
125
183
|
|
|
126
184
|
// Detect diagram type from header
|
|
127
|
-
const
|
|
185
|
+
const headerStmt = lines[0]!
|
|
128
186
|
|
|
129
187
|
// State diagram: "stateDiagram-v2" or "stateDiagram"
|
|
130
|
-
const graph = /^stateDiagram(-v2)?\s*$/i.test(
|
|
188
|
+
const graph = /^stateDiagram(-v2)?\s*$/i.test(headerStmt.text)
|
|
131
189
|
? parseStateDiagram(lines)
|
|
132
190
|
: parseFlowchart(lines)
|
|
133
191
|
|
|
@@ -139,16 +197,17 @@ export function parseMermaid(text: string): MermaidGraph {
|
|
|
139
197
|
// Flowchart parser
|
|
140
198
|
// ============================================================================
|
|
141
199
|
|
|
142
|
-
function parseFlowchart(lines:
|
|
200
|
+
function parseFlowchart(lines: Statement[]): MermaidGraph {
|
|
143
201
|
// parseFlowchart is only ever invoked by parseMermaid, which has already
|
|
144
202
|
// verified `lines` is non-empty — but that invariant isn't visible to the
|
|
145
203
|
// type checker across the function boundary, so validate it here instead
|
|
146
204
|
// of asserting past it.
|
|
147
|
-
const
|
|
148
|
-
if (
|
|
205
|
+
const headerStmt = lines[0]
|
|
206
|
+
if (headerStmt === undefined) {
|
|
149
207
|
/* v8 ignore next */
|
|
150
208
|
throw new Error('parseFlowchart called with no lines')
|
|
151
209
|
}
|
|
210
|
+
const header = headerStmt.text
|
|
152
211
|
|
|
153
212
|
const headerMatch = header.match(
|
|
154
213
|
/^(?:graph|flowchart)\s+(TD|TB|LR|BT|RL)\s*$/i,
|
|
@@ -164,8 +223,8 @@ function parseFlowchart(lines: string[]): MermaidGraph {
|
|
|
164
223
|
const rest = partialFlowchartMatch[1]!.trim()
|
|
165
224
|
throw new Error(
|
|
166
225
|
rest.length > 0
|
|
167
|
-
? `Invalid direction "${rest}" in header "${header}". Expected one of: TD, TB, LR, BT, RL.`
|
|
168
|
-
: `Missing direction in header "${header}". Expected e.g. "graph TD" or "flowchart LR" — one of: TD, TB, LR, BT, RL.`,
|
|
226
|
+
? `Line ${headerStmt.line}: Invalid direction "${rest}" in header "${header}". Expected one of: TD, TB, LR, BT, RL.`
|
|
227
|
+
: `Line ${headerStmt.line}: Missing direction in header "${header}". Expected e.g. "graph TD" or "flowchart LR" — one of: TD, TB, LR, BT, RL.`,
|
|
169
228
|
)
|
|
170
229
|
}
|
|
171
230
|
|
|
@@ -178,7 +237,7 @@ function parseFlowchart(lines: string[]): MermaidGraph {
|
|
|
178
237
|
? ` Did you mean "${suggestion}"?`
|
|
179
238
|
: ''
|
|
180
239
|
throw new Error(
|
|
181
|
-
`Invalid mermaid header: "${header}".${hint} Supported headers: ${SUPPORTED_HEADERS}.`,
|
|
240
|
+
`Line ${headerStmt.line}: Invalid mermaid header: "${header}".${hint} Supported headers: ${SUPPORTED_HEADERS}.`,
|
|
182
241
|
)
|
|
183
242
|
}
|
|
184
243
|
|
|
@@ -200,7 +259,8 @@ function parseFlowchart(lines: string[]): MermaidGraph {
|
|
|
200
259
|
const subgraphStack: MermaidSubgraph[] = []
|
|
201
260
|
|
|
202
261
|
for (let i = 1; i < lines.length; i++) {
|
|
203
|
-
const
|
|
262
|
+
const stmt = lines[i]!
|
|
263
|
+
const line = stmt.text
|
|
204
264
|
|
|
205
265
|
// --- classDef / class assignment / style — shared with the class-diagram
|
|
206
266
|
// parser, see packages/core/src/style-directives.ts ---
|
|
@@ -313,7 +373,7 @@ function parseFlowchart(lines: string[]): MermaidGraph {
|
|
|
313
373
|
// }
|
|
314
374
|
// ============================================================================
|
|
315
375
|
|
|
316
|
-
function parseStateDiagram(lines:
|
|
376
|
+
function parseStateDiagram(lines: Statement[]): MermaidGraph {
|
|
317
377
|
const graph: MermaidGraph = {
|
|
318
378
|
direction: 'TD',
|
|
319
379
|
nodes: new Map(),
|
|
@@ -335,7 +395,8 @@ function parseStateDiagram(lines: string[]): MermaidGraph {
|
|
|
335
395
|
let endCount = 0
|
|
336
396
|
|
|
337
397
|
for (let i = 1; i < lines.length; i++) {
|
|
338
|
-
const
|
|
398
|
+
const stmt = lines[i]!
|
|
399
|
+
const line = stmt.text
|
|
339
400
|
|
|
340
401
|
// --- direction override ---
|
|
341
402
|
const dirMatch = line.match(/^direction\s+(TD|TB|LR|BT|RL)\s*$/i)
|
|
@@ -803,8 +864,9 @@ function expandedNodeLabel(id: string, meta: ExpandedNodeMeta): string {
|
|
|
803
864
|
* browser without script.
|
|
804
865
|
*
|
|
805
866
|
* The actual grammar and href-safety rules live in packages/core/src/click-directive.ts,
|
|
806
|
-
* shared with the class diagram parser
|
|
807
|
-
*
|
|
867
|
+
* shared with the class diagram parser
|
|
868
|
+
* (packages/mermaid-parser/src/class/parser.ts) — this is a thin wrapper
|
|
869
|
+
* binding it to this parser's `graph.interactions` map.
|
|
808
870
|
*/
|
|
809
871
|
function applyClickStatement(line: string, graph: MermaidGraph): void {
|
|
810
872
|
applyClickStatementShared(line, graph.interactions)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|