zombie-mermaid 4.2.2 → 4.2.3
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/package.json +9 -7
- package/src/__tests__/architecture-integration.test.ts +0 -217
- package/src/__tests__/ascii-ansi.test.ts +0 -539
- package/src/__tests__/ascii-draw-bundles.test.ts +0 -849
- package/src/__tests__/ascii-edge-bundling-routing.test.ts +0 -214
- package/src/__tests__/ascii-edge-cross-style-overlap.test.ts +0 -216
- package/src/__tests__/ascii-grid-deep-chain.test.ts +0 -64
- package/src/__tests__/ascii-hyperlinks.test.ts +0 -364
- package/src/__tests__/ascii-nested-subgraph-sibling-order-444.test.ts +0 -108
- package/src/__tests__/ascii-nonmember-beside-frame-1283.test.ts +0 -113
- package/src/__tests__/ascii-package-boundary.test.ts +0 -291
- package/src/__tests__/ascii-parallel-edges-329.test.ts +0 -315
- package/src/__tests__/ascii-parallel-lane-border-1230.test.ts +0 -71
- package/src/__tests__/ascii-reverse-direction-edges-629.test.ts +0 -282
- package/src/__tests__/ascii-stacked-frame-geometry-1285.test.ts +0 -107
- package/src/__tests__/ascii-subgraph-bbox.test.ts +0 -139
- package/src/__tests__/ascii-subgraph-later-edgeless-301.test.ts +0 -277
- package/src/__tests__/browser.test.ts +0 -34
- package/src/__tests__/c4-integration.test.ts +0 -161
- package/src/__tests__/c4-orientation.test.ts +0 -162
- package/src/__tests__/c4-upstream-integration.test.ts +0 -211
- package/src/__tests__/class-click-interactions.test.ts +0 -232
- package/src/__tests__/class-integration.test.ts +0 -154
- package/src/__tests__/class-notes.test.ts +0 -317
- package/src/__tests__/class-parser-error-messages.test.ts +0 -162
- package/src/__tests__/class-parser.test.ts +0 -347
- package/src/__tests__/class-styling.test.ts +0 -485
- package/src/__tests__/cli-diagrams.test.ts +0 -106
- package/src/__tests__/cli-e2e.test.ts +0 -275
- package/src/__tests__/cli-entrypoint.test.ts +0 -146
- package/src/__tests__/cli-mcp-dispatch.test.ts +0 -68
- package/src/__tests__/cli-mcp.test.ts +0 -44
- package/src/__tests__/cli-png.test.ts +0 -35
- package/src/__tests__/cli-render.test.ts +0 -988
- package/src/__tests__/cli-test-helpers.ts +0 -54
- package/src/__tests__/cli-web-dispatch.test.ts +0 -62
- package/src/__tests__/cli-web.test.ts +0 -203
- package/src/__tests__/cli.test.ts +0 -1027
- package/src/__tests__/compound-flat-layout.test.ts +0 -901
- package/src/__tests__/direction-override.test.ts +0 -397
- package/src/__tests__/edge-approach-direction.test.ts +0 -295
- package/src/__tests__/edge-bundling-node-clearance.test.ts +0 -179
- package/src/__tests__/elk-layout-cache.test.ts +0 -223
- package/src/__tests__/er-click-unsupported.test.ts +0 -69
- package/src/__tests__/er-integration.test.ts +0 -531
- package/src/__tests__/er-parser-error-messages.test.ts +0 -82
- package/src/__tests__/er-parser.test.ts +0 -294
- package/src/__tests__/expanded-shapes.test.ts +0 -229
- package/src/__tests__/flowchart-back-edge-prereversal-1239.test.ts +0 -212
- package/src/__tests__/flowchart-syntax-gaps.test.ts +0 -371
- package/src/__tests__/guides-examples.test.ts +0 -181
- package/src/__tests__/integration.test.ts +0 -729
- package/src/__tests__/interactivity-config.test.ts +0 -723
- package/src/__tests__/interactivity-option.test.ts +0 -173
- package/src/__tests__/layout-disconnected.test.ts +0 -384
- package/src/__tests__/layout-engine.test.ts +0 -91
- package/src/__tests__/linkstyle.test.ts +0 -133
- package/src/__tests__/mcp-render-ascii-tool.test.ts +0 -95
- package/src/__tests__/mcp-render-svg-theme-guard.test.ts +0 -36
- package/src/__tests__/mcp-render-svg-tool.test.ts +0 -118
- package/src/__tests__/mermaid-entity-codes.test.ts +0 -114
- package/src/__tests__/monospace-metrics.test.ts +0 -74
- package/src/__tests__/multiline-labels.test.ts +0 -924
- package/src/__tests__/nested-subgraph-direction-crossing.test.ts +0 -322
- package/src/__tests__/nested-subgraph-edge-container-offset.test.ts +0 -151
- package/src/__tests__/package-info.test.ts +0 -51
- package/src/__tests__/parser.test.ts +0 -1544
- package/src/__tests__/render-options-overrides.test.ts +0 -257
- package/src/__tests__/render-options-per-type.test.ts +0 -178
- package/src/__tests__/renderer.test.ts +0 -743
- package/src/__tests__/resolve-colors.test.ts +0 -448
- package/src/__tests__/self-loop-edges.test.ts +0 -112
- package/src/__tests__/sequence-activation-check.test.ts +0 -219
- package/src/__tests__/sequence-integration.test.ts +0 -312
- package/src/__tests__/sequence-layout.test.ts +0 -1103
- package/src/__tests__/sequence-parser-syntax-errors.test.ts +0 -179
- package/src/__tests__/sequence-parser.test.ts +0 -821
- package/src/__tests__/start-marker-only-links-1386.test.ts +0 -104
- package/src/__tests__/state-composite-order-1287.test.ts +0 -132
- package/src/__tests__/state-flow-order-1240.test.ts +0 -113
- package/src/__tests__/state-styling.test.ts +0 -150
- package/src/__tests__/statements.test.ts +0 -264
- package/src/__tests__/styles.test.ts +0 -220
- package/src/__tests__/subgraph-title-edge-gap-1239.test.ts +0 -238
- package/src/__tests__/svg-accessible-name-conformance.test.ts +0 -276
- package/src/__tests__/svg-accessible-name.test.ts +0 -421
- package/src/__tests__/svg-csp-style-options.test.ts +0 -427
- package/src/__tests__/workspace-package-boundaries.test.ts +0 -336
- package/src/__tests__/xychart-integration.test.ts +0 -137
- package/src/__tests__/xychart-layout.test.ts +0 -205
- package/src/__tests__/xychart-parser-categories.test.ts +0 -78
- package/src/__tests__/xychart-parser-errors.test.ts +0 -95
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zombie-mermaid",
|
|
3
|
-
"version": "4.2.
|
|
3
|
+
"version": "4.2.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Render Mermaid diagrams as beautiful SVGs or ASCII art. Ultra-fast, fully themeable, zero DOM dependencies. Maintained fork of beautiful-mermaid.",
|
|
6
6
|
"type": "module",
|
|
@@ -79,6 +79,7 @@
|
|
|
79
79
|
},
|
|
80
80
|
"files": [
|
|
81
81
|
"src/",
|
|
82
|
+
"!src/**/__tests__",
|
|
82
83
|
"dist/",
|
|
83
84
|
"LICENSE",
|
|
84
85
|
"README.md"
|
|
@@ -90,11 +91,11 @@
|
|
|
90
91
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
91
92
|
"elkjs": "^0.11.0",
|
|
92
93
|
"entities": "^7.0.1",
|
|
93
|
-
"@zombie-mermaid/ascii-renderer": "4.2.
|
|
94
|
-
"@zombie-mermaid/
|
|
95
|
-
"@zombie-mermaid/
|
|
96
|
-
"@zombie-mermaid/
|
|
97
|
-
"@zombie-mermaid/
|
|
94
|
+
"@zombie-mermaid/ascii-renderer": "4.2.3",
|
|
95
|
+
"@zombie-mermaid/mcp": "4.2.3",
|
|
96
|
+
"@zombie-mermaid/svg-renderer": "4.2.3",
|
|
97
|
+
"@zombie-mermaid/mermaid-parser": "4.2.3",
|
|
98
|
+
"@zombie-mermaid/core": "4.2.3"
|
|
98
99
|
},
|
|
99
100
|
"devDependencies": {
|
|
100
101
|
"@changesets/changelog-github": "^1.0.0",
|
|
@@ -181,6 +182,7 @@
|
|
|
181
182
|
"dashboard:data": "tsx scripts/generate-dashboard-data.ts",
|
|
182
183
|
"upstream:pr-candidates": "tsx scripts/list-upstream-pr-rescue-candidates.ts",
|
|
183
184
|
"audit:responsive": "tsx scripts/audit-responsive.ts",
|
|
184
|
-
"layout:oracle": "tsx scripts/layout-oracle.ts"
|
|
185
|
+
"layout:oracle": "tsx scripts/layout-oracle.ts",
|
|
186
|
+
"label:oracle": "tsx scripts/label-position-oracle.ts"
|
|
185
187
|
}
|
|
186
188
|
}
|
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest'
|
|
2
|
-
import { splitStatements, detectDiagramType } from '@zombie-mermaid/core'
|
|
3
|
-
import {
|
|
4
|
-
parseArchitecture,
|
|
5
|
-
architectureToGraph,
|
|
6
|
-
} from '@zombie-mermaid/mermaid-parser'
|
|
7
|
-
import { renderMermaidSVG, renderMermaidASCII } from '../index.ts'
|
|
8
|
-
|
|
9
|
-
const parse = (src: string) => parseArchitecture(splitStatements(src))
|
|
10
|
-
const lower = (src: string) => architectureToGraph(parse(src))
|
|
11
|
-
|
|
12
|
-
const DOC = `architecture-beta
|
|
13
|
-
group api(cloud)[API]
|
|
14
|
-
group edge(internet)[Edge] in api
|
|
15
|
-
service db(database)[Database] in api
|
|
16
|
-
service server(server)[Server] in api
|
|
17
|
-
service gw[Gateway] in edge
|
|
18
|
-
junction j in api
|
|
19
|
-
service client(internet)[Client]
|
|
20
|
-
db:L -- R:server
|
|
21
|
-
server:T <--> B:j
|
|
22
|
-
gw{group}:R --> L:client
|
|
23
|
-
align row db server`
|
|
24
|
-
|
|
25
|
-
describe('architecture-beta parsing', () => {
|
|
26
|
-
it('detects both header spellings', () => {
|
|
27
|
-
expect(detectDiagramType('architecture-beta\nservice a')).toBe(
|
|
28
|
-
'architecture',
|
|
29
|
-
)
|
|
30
|
-
expect(detectDiagramType('architecture\nservice a')).toBe('architecture')
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
it('parses groups, nesting, services, junctions and edges', () => {
|
|
34
|
-
const d = parse(DOC)
|
|
35
|
-
expect(d.groups.map((g) => [g.id, g.title, g.parent])).toEqual([
|
|
36
|
-
['api', 'API', undefined],
|
|
37
|
-
['edge', 'Edge', 'api'],
|
|
38
|
-
])
|
|
39
|
-
expect(d.services.find((s) => s.id === 'db')).toMatchObject({
|
|
40
|
-
icon: 'database',
|
|
41
|
-
title: 'Database',
|
|
42
|
-
parent: 'api',
|
|
43
|
-
})
|
|
44
|
-
expect(d.services.find((s) => s.id === 'gw')?.icon).toBeUndefined()
|
|
45
|
-
expect(d.junctions).toEqual([{ id: 'j', parent: 'api' }])
|
|
46
|
-
expect(d.edges).toHaveLength(3)
|
|
47
|
-
expect(d.edges[1]).toMatchObject({ arrowStart: true, arrowEnd: true })
|
|
48
|
-
expect(d.edges[2]).toMatchObject({ sourceGroup: true, arrowEnd: true })
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
it('titles default to the id', () => {
|
|
52
|
-
expect(parse('architecture-beta\nservice a').services[0]?.title).toBe('a')
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
it.each([
|
|
56
|
-
['service a\nservice a', /line 3.*duplicate id "a"/s],
|
|
57
|
-
['service a in nope', /line 2.*must name a declared group/s],
|
|
58
|
-
['group g in g', /line 2.*inside itself/s],
|
|
59
|
-
['group a in b\ngroup b in a', /nested inside itself/],
|
|
60
|
-
['service a\na:R -- L:zzz', /line 3.*unknown id "zzz"/s],
|
|
61
|
-
['group g\nservice a\na:R -- L:g', /line 4.*not the group/s],
|
|
62
|
-
['service a\nservice b\na{group}:R -- L:b', /needs "a" to be declared/],
|
|
63
|
-
['service a\nbogus line', /line 3.*unrecognized/s],
|
|
64
|
-
])('rejects %j', (body, message) => {
|
|
65
|
-
expect(() => parse(`architecture-beta\n${body}`)).toThrow(message)
|
|
66
|
-
})
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
describe('architecture-beta lowering', () => {
|
|
70
|
-
it('maps groups to nested subgraphs and icons to shapes', () => {
|
|
71
|
-
const g = lower(DOC)
|
|
72
|
-
expect(g.subgraphs).toHaveLength(1)
|
|
73
|
-
const api = g.subgraphs[0]!
|
|
74
|
-
expect(api.id).toBe('api')
|
|
75
|
-
expect(api.nodeIds).toEqual(['db', 'server', 'j'])
|
|
76
|
-
expect(api.children.map((c) => [c.id, c.nodeIds])).toEqual([
|
|
77
|
-
['edge', ['gw']],
|
|
78
|
-
])
|
|
79
|
-
expect(g.nodes.get('db')?.shape).toBe('cylinder')
|
|
80
|
-
expect(g.nodes.get('server')?.shape).toBe('rectangle')
|
|
81
|
-
expect(g.nodes.get('j')).toMatchObject({
|
|
82
|
-
shape: 'filled-circle',
|
|
83
|
-
label: '',
|
|
84
|
-
})
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
it('attaches {group} ends to the enclosing group', () => {
|
|
88
|
-
const e = lower(DOC).edges[2]!
|
|
89
|
-
expect(e).toMatchObject({ source: 'edge', target: 'client' })
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
it('picks the flow axis from the ports', () => {
|
|
93
|
-
expect(
|
|
94
|
-
lower('architecture-beta\nservice a\nservice b\na:R -- L:b').direction,
|
|
95
|
-
).toBe('LR')
|
|
96
|
-
expect(
|
|
97
|
-
lower('architecture-beta\nservice a\nservice b\na:B -- T:b').direction,
|
|
98
|
-
).toBe('TB')
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
it('reverses edges that run against the flow, keeping arrowheads on the true ends', () => {
|
|
102
|
-
// `a:L --> R:b` puts a to the right of b, arrow pointing at b.
|
|
103
|
-
const [e] = lower(
|
|
104
|
-
'architecture-beta\nservice a\nservice b\na:L --> R:b\n',
|
|
105
|
-
).edges
|
|
106
|
-
expect(e).toMatchObject({
|
|
107
|
-
source: 'b',
|
|
108
|
-
target: 'a',
|
|
109
|
-
hasArrowStart: true,
|
|
110
|
-
hasArrowEnd: false,
|
|
111
|
-
})
|
|
112
|
-
})
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
describe('architecture-beta rendering', () => {
|
|
116
|
-
it('renders SVG with group titles and service labels', () => {
|
|
117
|
-
const svg = renderMermaidSVG(DOC)
|
|
118
|
-
for (const label of [
|
|
119
|
-
'API',
|
|
120
|
-
'Edge',
|
|
121
|
-
'Database',
|
|
122
|
-
'Server',
|
|
123
|
-
'Gateway',
|
|
124
|
-
'Client',
|
|
125
|
-
]) {
|
|
126
|
-
expect(svg).toContain(label)
|
|
127
|
-
}
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
it('renders ASCII', () => {
|
|
131
|
-
const out = renderMermaidASCII(
|
|
132
|
-
'architecture-beta\n service a[Alpha]\n service b[Beta]\n a:R --> L:b',
|
|
133
|
-
)
|
|
134
|
-
expect(out).toContain('Alpha')
|
|
135
|
-
expect(out).toContain('Beta')
|
|
136
|
-
})
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
const NESTED = `architecture-beta
|
|
140
|
-
group api(cloud)[API]
|
|
141
|
-
group inner(cloud)[Inner] in api
|
|
142
|
-
service a[Alpha] in inner
|
|
143
|
-
service b[Beta] in api
|
|
144
|
-
junction j in api
|
|
145
|
-
a:R -- L:j
|
|
146
|
-
j:R --> L:b`
|
|
147
|
-
|
|
148
|
-
describe('architecture-beta nested groups and junctions', () => {
|
|
149
|
-
it('SVG draws nested groups and a junction dot', () => {
|
|
150
|
-
const svg = renderMermaidSVG(NESTED)
|
|
151
|
-
expect(svg).toContain('data-id="api" data-label="API"')
|
|
152
|
-
expect(svg).toContain('data-id="inner" data-label="Inner"')
|
|
153
|
-
expect(svg).toContain(
|
|
154
|
-
'data-id="j" data-label="" data-shape="filled-circle"',
|
|
155
|
-
)
|
|
156
|
-
expect(svg.match(/class="subgraph"/g)).toHaveLength(2)
|
|
157
|
-
expect(svg.match(/class="edge"/g)).toHaveLength(2)
|
|
158
|
-
// The inner group is drawn after (on top of) its parent.
|
|
159
|
-
expect(svg.indexOf('data-id="api"')).toBeLessThan(
|
|
160
|
-
svg.indexOf('data-id="inner"'),
|
|
161
|
-
)
|
|
162
|
-
})
|
|
163
|
-
|
|
164
|
-
it('ASCII draws the inner group inside the outer one', () => {
|
|
165
|
-
const lines = renderMermaidASCII(NESTED).split('\n')
|
|
166
|
-
const find = (s: string) => lines.find((l) => l.includes(s))!
|
|
167
|
-
// The outer border encloses the inner box: both its left and right
|
|
168
|
-
// borders flank the inner group's own title row.
|
|
169
|
-
expect(find('API')).toMatch(/^│\s+API\s+│$/)
|
|
170
|
-
expect(find('Inner')).toMatch(/^│\s*│\s+Inner\s+│/)
|
|
171
|
-
expect(find('Inner')).toMatch(/│$/)
|
|
172
|
-
expect(find('Alpha')).toMatch(/^│\s*│\s*│\s+Alpha/)
|
|
173
|
-
expect(find('Beta')).toMatch(/^│.*Beta.*│$/)
|
|
174
|
-
})
|
|
175
|
-
|
|
176
|
-
it('ASCII draws a junction as a small box and keeps its edge arrow', () => {
|
|
177
|
-
const out = renderMermaidASCII(NESTED)
|
|
178
|
-
expect(out).toContain('●')
|
|
179
|
-
expect(out).toContain('►')
|
|
180
|
-
})
|
|
181
|
-
|
|
182
|
-
it('SVG and ASCII both render {group} edges', () => {
|
|
183
|
-
const src = `architecture-beta
|
|
184
|
-
group g(cloud)[Group]
|
|
185
|
-
service a[Alpha] in g
|
|
186
|
-
service b[Beta]
|
|
187
|
-
a{group}:R --> L:b`
|
|
188
|
-
expect(renderMermaidSVG(src)).toContain('data-id="g"')
|
|
189
|
-
const out = renderMermaidASCII(src)
|
|
190
|
-
expect(out).toContain('Group')
|
|
191
|
-
expect(out).toContain('Beta')
|
|
192
|
-
})
|
|
193
|
-
|
|
194
|
-
it('SVG reversed edges still render', () => {
|
|
195
|
-
const svg = renderMermaidSVG(
|
|
196
|
-
'architecture-beta\nservice a[Alpha]\nservice b[Beta]\na:L --> R:b',
|
|
197
|
-
)
|
|
198
|
-
expect(svg).toContain('data-id="a"')
|
|
199
|
-
expect(svg.match(/class="edge"/g)).toHaveLength(1)
|
|
200
|
-
})
|
|
201
|
-
|
|
202
|
-
// https://github.com/dfadler/zombie-mermaid/issues/1197: a back-edge across
|
|
203
|
-
// sibling groups used to throw in the ASCII grid layout.
|
|
204
|
-
it('ASCII renders a back-edge across sibling groups (#1197)', () => {
|
|
205
|
-
const out = renderMermaidASCII(`architecture-beta
|
|
206
|
-
group g1(cloud)[G1]
|
|
207
|
-
group g2(cloud)[G2]
|
|
208
|
-
group g3(cloud)[G3]
|
|
209
|
-
service a(server)[A] in g1
|
|
210
|
-
service b(server)[B] in g2
|
|
211
|
-
service c(server)[C] in g3
|
|
212
|
-
a:R --> L:b
|
|
213
|
-
b:R --> L:c
|
|
214
|
-
c:B --> B:a`)
|
|
215
|
-
for (const g of ['G1', 'G2', 'G3']) expect(out).toContain(g)
|
|
216
|
-
})
|
|
217
|
-
})
|