@zombie-mermaid/svg-renderer 4.2.2 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +15 -1
  2. package/dist/index.cjs +52 -52
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +23 -4
  5. package/dist/index.d.ts +23 -4
  6. package/dist/index.js +897 -849
  7. package/dist/index.js.map +1 -1
  8. package/package.json +14 -5
  9. package/src/__tests__/c4-label-clearance-1290.test.ts +0 -112
  10. package/src/__tests__/c4-line-ends-1208.test.ts +0 -52
  11. package/src/__tests__/c4-mermaid-reference.test.ts +0 -124
  12. package/src/__tests__/c4-svg.test.ts +0 -337
  13. package/src/__tests__/c4-text-width-1210.test.ts +0 -43
  14. package/src/__tests__/class-component-order-1249.test.ts +0 -40
  15. package/src/__tests__/class-diamond-markers-1232.test.ts +0 -59
  16. package/src/__tests__/class-member-right-padding-1238.test.ts +0 -43
  17. package/src/__tests__/class-namespace-1196.test.ts +0 -165
  18. package/src/__tests__/class-namespace-sparse-elk-1196.test.ts +0 -96
  19. package/src/__tests__/class-visibility-markers-1237.test.ts +0 -27
  20. package/src/__tests__/edge-jog-straightening-1388.test.ts +0 -57
  21. package/src/__tests__/elk-adapter-utils.test.ts +0 -166
  22. package/src/__tests__/er-attribute-right-padding-1262.test.ts +0 -47
  23. package/src/__tests__/er-cardinality-markers-1233.test.ts +0 -35
  24. package/src/__tests__/er-default-direction-1250.test.ts +0 -69
  25. package/src/__tests__/er-edge-label-contrast-1244.test.ts +0 -58
  26. package/src/__tests__/fixtures/c4-mermaid-reference.json +0 -626
  27. package/src/__tests__/flowchart-parallel-edge-lanes-1308.test.ts +0 -168
  28. package/src/__tests__/pie-layout.test.ts +0 -215
  29. package/src/__tests__/pie-svg.test.ts +0 -194
  30. package/src/__tests__/render-mermaid-svg.test.ts +0 -64
  31. package/src/__tests__/sequence-label-clearance-1242.test.ts +0 -162
  32. package/src/__tests__/sequence-nested-activation-1241.test.ts +0 -37
  33. package/src/__tests__/svg-edge-to-own-cluster-1310.test.ts +0 -32
  34. package/src/__tests__/xychart-smooth-curve.test.ts +0 -42
  35. package/src/__tests__/xychart-x-label-overlap-1243.test.ts +0 -62
  36. package/src/c4/arial-widths.ts +0 -59
  37. package/src/c4/layout.ts +0 -680
  38. package/src/c4/metrics.ts +0 -261
  39. package/src/c4/renderer.ts +0 -366
  40. package/src/class/layout.ts +0 -525
  41. package/src/class/renderer.ts +0 -669
  42. package/src/edge-curves.ts +0 -205
  43. package/src/elk-instance.ts +0 -292
  44. package/src/er/layout.ts +0 -216
  45. package/src/er/renderer.ts +0 -516
  46. package/src/generated/mono-font-subset.ts +0 -32
  47. package/src/index.ts +0 -277
  48. package/src/layout-engine/back-edges.ts +0 -73
  49. package/src/layout-engine/compound-flat.ts +0 -916
  50. package/src/layout-engine/constants.ts +0 -19
  51. package/src/layout-engine/edge-bundling.ts +0 -458
  52. package/src/layout-engine/elk-adapter-utils.ts +0 -81
  53. package/src/layout-engine/elk-graph-builder.ts +0 -245
  54. package/src/layout-engine/from-elk.ts +0 -767
  55. package/src/layout-engine/inner-edges.ts +0 -329
  56. package/src/layout-engine/jog-straightening.ts +0 -52
  57. package/src/layout-engine/layer-alignment.ts +0 -174
  58. package/src/layout-engine/layout-hints.ts +0 -27
  59. package/src/layout-engine/to-elk.ts +0 -855
  60. package/src/layout-engine.ts +0 -115
  61. package/src/pie/layout.ts +0 -234
  62. package/src/pie/renderer.ts +0 -161
  63. package/src/registry.ts +0 -441
  64. package/src/renderer.ts +0 -1510
  65. package/src/resolve-colors.ts +0 -339
  66. package/src/sequence/layout.ts +0 -766
  67. package/src/sequence/renderer.ts +0 -687
  68. package/src/shape-clipping.ts +0 -197
  69. package/src/styles.ts +0 -145
  70. package/src/title-gaps.ts +0 -161
  71. package/src/xychart/layout.ts +0 -727
  72. package/src/xychart/renderer.ts +0 -676
package/src/registry.ts DELETED
@@ -1,441 +0,0 @@
1
- // ============================================================================
2
- // zombie-mermaid — SVG diagram-type registry
3
- //
4
- // A per-type registration table `renderMermaidSVG` (./index.ts) looks up
5
- // instead of hand-maintaining its own `switch (diagramType)` over the same
6
- // `DiagramType`. Moved here from the umbrella's `src/diagram-registry.ts`
7
- // under issue #1111, for parity with `@zombie-mermaid/ascii-renderer`'s own
8
- // `registry.ts` — see docs/decisions/diagram-type-registry-partial.md for
9
- // why the SVG and ASCII halves stayed two separate tables rather than one
10
- // shared `DiagramModule` with both a `renderSvg` and a `renderAscii` method
11
- // (short version: one table made this module import out of
12
- // `packages/ascii-renderer/`, while that package's `index.ts` imported this
13
- // one back, a cycle that blocked the monorepo split and dragged `elkjs`
14
- // into `dist/ascii.js`).
15
- //
16
- // Every diagram type is registered here, including 'flowchart' — see the
17
- // decision doc for why it was the last holdout (its ASCII path had no
18
- // per-type wrapper function to slot in until #745 extracted
19
- // `renderFlowchartAscii`, and its SVG path carries `%%{init: ...}%%`
20
- // directive handling no other type has — see `flowchartModule.layoutForSvg`
21
- // below for how that's folded in without growing `SvgRenderContext`). The
22
- // front door (`renderMermaidSVG` in ./index.ts) has no fallback switch left;
23
- // every `DiagramType` is a hit here.
24
- //
25
- // `packages/core/src/diagram-type.ts` (the `DiagramType` union + `detectDiagramType`)
26
- // stays exactly as-is and is what the front door uses to key into this
27
- // table — this module doesn't touch detection.
28
- //
29
- // `parseMermaid` (flowchart/state parsing) reaches out to the umbrella's
30
- // `../../../src/parser.ts` rather than a `@zombie-mermaid/*` package
31
- // specifier — flowchart/state parsing was deliberately never extracted into
32
- // `@zombie-mermaid/mermaid-parser` (see that package's scoping doc), the same
33
- // pre-existing boundary call `packages/ascii-renderer/src/flowchart.ts`
34
- // already reaches across for the ASCII side. `vite.config.ts` bundles that
35
- // file straight into this package's own dist, exactly as it already does
36
- // for `ascii-renderer` — see that file's header comment.
37
- // ============================================================================
38
-
39
- import type {
40
- DiagramType,
41
- RenderOptions,
42
- DiagramColors,
43
- SvgEmitOptions,
44
- MermaidGraph,
45
- PositionedGraph,
46
- CurveStyle,
47
- Statement,
48
- } from '@zombie-mermaid/core'
49
- import type { FontSizes } from './styles.ts'
50
- import { withDirectionOverride } from '@zombie-mermaid/core'
51
-
52
- import {
53
- parseXYChart,
54
- parseErDiagram,
55
- parseSequenceDiagram,
56
- parseClassDiagram,
57
- parseArchitecture,
58
- architectureToGraph,
59
- parseC4Diagram,
60
- parsePieChart,
61
- } from '@zombie-mermaid/mermaid-parser'
62
- import type {
63
- XYChart,
64
- PositionedXYChart,
65
- ErDiagram,
66
- PositionedErDiagram,
67
- SequenceDiagram,
68
- PositionedSequenceDiagram,
69
- ClassDiagram,
70
- PositionedClassDiagram,
71
- ArchitectureDiagram,
72
- C4Diagram,
73
- PositionedC4Diagram,
74
- PieChart,
75
- PositionedPieChart,
76
- } from '@zombie-mermaid/mermaid-parser'
77
- import { layoutXYChart } from './xychart/layout.ts'
78
- import { renderXYChartSvg } from './xychart/renderer.ts'
79
- import { layoutErDiagramSync } from './er/layout.ts'
80
- import { renderErSvg } from './er/renderer.ts'
81
- import { layoutSequenceDiagram } from './sequence/layout.ts'
82
- import { renderSequenceSvg } from './sequence/renderer.ts'
83
- import { layoutClassDiagramSync } from './class/layout.ts'
84
- import { renderClassSvg } from './class/renderer.ts'
85
- import { layoutC4DiagramSync } from './c4/layout.ts'
86
- import { renderC4Svg } from './c4/renderer.ts'
87
- import { layoutPieChart } from './pie/layout.ts'
88
- import { renderPieSvg } from './pie/renderer.ts'
89
- import { layoutFlowchartSync, layoutGraphSync } from './layout-engine.ts'
90
- import { renderSvg as renderFlowchartSvg } from './renderer.ts'
91
- import { parseMermaid } from '@zombie-mermaid/mermaid-parser'
92
-
93
- /**
94
- * Parameters shared by every per-type SVG renderer today, factored out of
95
- * the positional-argument lists that otherwise differ type to type (the
96
- * inconsistency issue #533 flags — confirmed by reading all five renderer
97
- * signatures: `embedSource`/`title`/`decorative`/`emit` shift position
98
- * across `renderSvg`, `renderSequenceSvg`, `renderClassSvg`, `renderErSvg`,
99
- * `renderXYChartSvg`, and `renderErSvg` drops `linksEnabled` entirely).
100
- *
101
- * Fields only one or two types need (`curve`, `animationEnabled`,
102
- * `linksEnabled`, `interactive`) are deliberately left OUT of this shared
103
- * shape rather than grown in for every exception — each type's own
104
- * `renderSvg` adapter below derives those straight from `options`, exactly
105
- * as each existing `renderMermaidSVGRaw` switch case already did.
106
- */
107
- export interface SvgRenderContext {
108
- colors: DiagramColors
109
- font: string
110
- transparent: boolean
111
- fontSizes: FontSizes
112
- embedSource?: string
113
- title?: string
114
- decorative?: boolean
115
- emit: SvgEmitOptions
116
- }
117
-
118
- /**
119
- * One diagram type's full registration.
120
- *
121
- * `layoutForSvg` is deliberately SVG-only — it is NOT shared with the ASCII
122
- * side, unlike the issue's original `{ detect, parse, layout, renderSvg,
123
- * renderAscii }` sketch. Reading every ASCII per-type module confirmed why a
124
- * single shared `layout` step would be fiction, not simplification, for this
125
- * codebase: SVG layout produces pixel coordinates (`PositionedXYChart`,
126
- * `PositionedErDiagram`, …), while every ASCII renderer does its own,
127
- * unrelated grid/canvas layout internally — see e.g.
128
- * `packages/ascii-renderer/src/xychart.ts`'s file header: "Uses the parsed
129
- * XYChart type directly (not PositionedXYChart) since pixel coordinates
130
- * don't map to character grids." `parse` genuinely is shared in the sense
131
- * that both front doors call the same `parseXYChart`/`parseErDiagram`, but
132
- * each ASCII renderer reruns that parse itself from raw text — which is why
133
- * the ASCII entries live in `packages/ascii-renderer/src/registry.ts` as
134
- * plain `(text, …) => string` functions instead of a `renderAscii` method on
135
- * this interface.
136
- *
137
- * `parse` takes both `lines` (the pre-split statement list from
138
- * `splitStatements(decoded)`, computed once by the front door — what every
139
- * already-registered type's parser wants) and `text` (the raw, un-split
140
- * source `flowchartModule` below needs instead): `parseMermaid`'s
141
- * `%%{init: ...}%%` directive extraction reads raw, un-commented lines that
142
- * `splitStatements` has already discarded by the time `lines` exists, and
143
- * its multi-line-statement continuation merging needs each statement's
144
- * *originating physical line* grouping, which `splitStatements`'s flattened
145
- * array has already lost. `xychartModule`/`erModule`/`sequenceModule`/
146
- * `classModule` all ignore the second parameter — JS/TS functions may take
147
- * fewer parameters than their declared type allows, so `parse: parseXYChart`
148
- * (etc.) is unchanged from before this parameter was added.
149
- */
150
- export interface DiagramModule<TDiagram = unknown, TPositioned = unknown> {
151
- readonly type: DiagramType
152
- parse(lines: Statement[], text: string): TDiagram
153
- layoutForSvg(diagram: TDiagram, options: RenderOptions): TPositioned
154
- renderSvg(
155
- positioned: TPositioned,
156
- ctx: SvgRenderContext,
157
- options: RenderOptions,
158
- ): string
159
- }
160
-
161
- const xychartModule: DiagramModule<XYChart, PositionedXYChart> = {
162
- type: 'xychart',
163
- parse: parseXYChart,
164
- layoutForSvg: layoutXYChart,
165
- renderSvg(positioned, ctx, options) {
166
- // Mirrors resolveXYChartInteractive() in the umbrella's src/index.ts
167
- // exactly — `interactivity` wins when set, otherwise the deprecated
168
- // `interactive` boolean keeps controlling this as before.
169
- const interactive =
170
- options.interactivity !== undefined
171
- ? options.interactivity === 'full'
172
- : (options.interactive ?? false)
173
- return renderXYChartSvg(
174
- positioned,
175
- ctx.colors,
176
- ctx.font,
177
- ctx.transparent,
178
- interactive,
179
- ctx.embedSource,
180
- ctx.title,
181
- ctx.decorative,
182
- ctx.emit,
183
- )
184
- },
185
- }
186
-
187
- const sequenceModule: DiagramModule<
188
- SequenceDiagram,
189
- PositionedSequenceDiagram
190
- > = {
191
- type: 'sequence',
192
- parse: parseSequenceDiagram,
193
- layoutForSvg: layoutSequenceDiagram,
194
- renderSvg(positioned, ctx) {
195
- return renderSequenceSvg(
196
- positioned,
197
- ctx.colors,
198
- ctx.font,
199
- ctx.transparent,
200
- ctx.fontSizes,
201
- ctx.embedSource,
202
- ctx.title,
203
- ctx.decorative,
204
- ctx.emit,
205
- )
206
- },
207
- }
208
-
209
- /**
210
- * Mirrors `resolveLinksEnabled()` in the umbrella's src/index.ts exactly
211
- * (`interactivity` defaults unset to `'static'`; only `'none'` turns links
212
- * off) — duplicated here rather than imported since that helper is private
213
- * to src/index.ts, which now imports this module (importing it back would
214
- * cycle).
215
- */
216
- function resolveLinksEnabled(options: RenderOptions): boolean {
217
- const interactivity = options.interactivity ?? 'static'
218
- return interactivity !== 'none'
219
- }
220
-
221
- /**
222
- * Mirrors `resolveAnimationEnabled()` in the umbrella's src/index.ts exactly
223
- * (`interactivity` defaults unset to `'static'`; only `'full'` turns
224
- * animation on) — duplicated here for the same import-direction reason
225
- * `resolveLinksEnabled` above is.
226
- */
227
- function resolveAnimationEnabled(options: RenderOptions): boolean {
228
- const interactivity = options.interactivity ?? 'static'
229
- return interactivity === 'full'
230
- }
231
-
232
- const classModule: DiagramModule<ClassDiagram, PositionedClassDiagram> = {
233
- type: 'class',
234
- parse: parseClassDiagram,
235
- layoutForSvg: layoutClassDiagramSync,
236
- renderSvg(positioned, ctx, options) {
237
- return renderClassSvg(
238
- positioned,
239
- ctx.colors,
240
- ctx.font,
241
- ctx.transparent,
242
- ctx.fontSizes,
243
- ctx.embedSource,
244
- ctx.title,
245
- ctx.decorative,
246
- resolveLinksEnabled(options),
247
- ctx.emit,
248
- )
249
- },
250
- }
251
-
252
- const erModule: DiagramModule<ErDiagram, PositionedErDiagram> = {
253
- type: 'er',
254
- parse: parseErDiagram,
255
- // `options.direction` replaces the diagram's own top-level `direction`
256
- // line, if any, before layout — same order as the umbrella's original
257
- // 'er' case: parse, then withDirectionOverride, then layout.
258
- layoutForSvg(diagram, options) {
259
- return layoutErDiagramSync(
260
- withDirectionOverride(diagram, options.direction),
261
- options,
262
- )
263
- },
264
- renderSvg(positioned, ctx) {
265
- return renderErSvg(
266
- positioned,
267
- ctx.colors,
268
- ctx.font,
269
- ctx.transparent,
270
- ctx.fontSizes,
271
- ctx.embedSource,
272
- ctx.title,
273
- ctx.decorative,
274
- ctx.emit,
275
- )
276
- },
277
- }
278
-
279
- /**
280
- * `renderSvg`'s (the low-level flowchart/state SVG emitter, imported above
281
- * as `renderFlowchartSvg`) `curve` parameter is the one piece of
282
- * `SvgRenderContext`-adjacent state no other registered type needs: a
283
- * `%%{init: {"flowchart": {"curve": ...}}}%%` directive on the diagram
284
- * itself can supply a default, and `options.curve` always wins when set —
285
- * see `applyInitConfig()` in `packages/core/src/init-directive.ts`, which
286
- * the umbrella's pre-registry flowchart path used to call directly.
287
- *
288
- * That resolution needs the parsed diagram (for `initConfig`) AND the
289
- * caller's `options` together, and the *result* is only needed later, by
290
- * `renderSvg` — so rather than teach `SvgRenderContext` a diagram-specific
291
- * `curve` field (every other field there is genuinely shared across types),
292
- * `layoutForSvg` below resolves it once and carries it forward on
293
- * `PositionedFlowchart`, right next to the `PositionedGraph` it was
294
- * resolved alongside. `animationEnabled`/`linksEnabled` need no such
295
- * carry-through: both derive from `options` alone via the
296
- * `resolveAnimationEnabled`/`resolveLinksEnabled` helpers above, exactly
297
- * like `class`'s `linksEnabled` already does, so `flowchartModule.renderSvg`
298
- * just calls them directly.
299
- */
300
- export interface PositionedFlowchart {
301
- graph: PositionedGraph
302
- curve: CurveStyle
303
- }
304
-
305
- const flowchartModule: DiagramModule<MermaidGraph, PositionedFlowchart> = {
306
- type: 'flowchart',
307
- // Ignores `lines` — see the `parse` doc comment on `DiagramModule` above
308
- // for why flowchart/state needs the raw `text` instead.
309
- parse: (_lines, text) => parseMermaid(text),
310
- layoutForSvg(diagram, options) {
311
- // Same order as the umbrella's original fallback: direction override,
312
- // then layout. `options.curve` wins over the diagram's own
313
- // `%%{init: ...}%%` directive, which wins over the 'linear' default —
314
- // see the doc comment on `PositionedFlowchart` above.
315
- const graph = withDirectionOverride(diagram, options.direction)
316
- return {
317
- graph: layoutFlowchartSync(graph, options),
318
- curve: options.curve ?? diagram.initConfig?.curve ?? 'linear',
319
- }
320
- },
321
- renderSvg(positioned, ctx, options) {
322
- return renderFlowchartSvg(
323
- positioned.graph,
324
- ctx.colors,
325
- ctx.font,
326
- ctx.transparent,
327
- ctx.fontSizes,
328
- positioned.curve,
329
- ctx.embedSource,
330
- resolveAnimationEnabled(options),
331
- resolveLinksEnabled(options),
332
- ctx.title,
333
- ctx.decorative,
334
- ctx.emit,
335
- )
336
- },
337
- }
338
-
339
- const c4Module: DiagramModule<C4Diagram, PositionedC4Diagram> = {
340
- type: 'c4',
341
- parse: parseC4Diagram,
342
- // Mermaid's C4 renderer has no direction: shapes are placed in rows in
343
- // declaration order, so `options.direction` does not apply to the SVG.
344
- layoutForSvg(diagram, options) {
345
- return layoutC4DiagramSync(diagram, options)
346
- },
347
- renderSvg(positioned, ctx) {
348
- return renderC4Svg(
349
- positioned,
350
- ctx.colors,
351
- ctx.font,
352
- ctx.transparent,
353
- ctx.fontSizes,
354
- ctx.embedSource,
355
- ctx.title,
356
- ctx.decorative,
357
- ctx.emit,
358
- )
359
- },
360
- }
361
-
362
- /**
363
- * Architecture diagrams are lowered to the flowchart model
364
- * (`architectureToGraph` in `@zombie-mermaid/mermaid-parser`) and ride the
365
- * flowchart layout + renderer, so this module is `flowchartModule` with a
366
- * different `parse`. The lowered graph carries no `%%{init}%%` config, so
367
- * `curve` is `options.curve` or 'linear'.
368
- */
369
- const architectureModule: DiagramModule<
370
- ArchitectureDiagram,
371
- PositionedFlowchart
372
- > = {
373
- type: 'architecture',
374
- parse: parseArchitecture,
375
- layoutForSvg(diagram, options) {
376
- const graph = withDirectionOverride(
377
- architectureToGraph(diagram),
378
- options.direction,
379
- )
380
- return {
381
- graph: layoutGraphSync(graph, options),
382
- curve: options.curve ?? 'linear',
383
- }
384
- },
385
- renderSvg: flowchartModule.renderSvg,
386
- }
387
-
388
- /**
389
- * Pie charts parse from the raw `text` rather than `lines` (see
390
- * `parsePieChart`'s doc: `splitStatements` would split `title A; B` and
391
- * treat `'` as a quote), then lay out and render to Mermaid's geometry —
392
- * see ./pie/layout.ts. No direction or interactivity applies.
393
- */
394
- const pieModule: DiagramModule<PieChart, PositionedPieChart> = {
395
- type: 'pie',
396
- parse: (_lines, text) => parsePieChart(text),
397
- layoutForSvg: layoutPieChart,
398
- renderSvg(positioned, ctx) {
399
- return renderPieSvg(
400
- positioned,
401
- ctx.colors,
402
- ctx.font,
403
- ctx.transparent,
404
- ctx.embedSource,
405
- ctx.title,
406
- ctx.decorative,
407
- ctx.emit,
408
- )
409
- },
410
- }
411
-
412
- /**
413
- * The registry proper — every `DiagramType` is looked up here by the SVG
414
- * front door (`renderMermaidSVG` in ./index.ts), which has no fallback
415
- * switch left. The ASCII front door's equivalent table is `asciiRegistry`
416
- * in `packages/ascii-renderer/src/registry.ts`.
417
- *
418
- * Typed with `any` type parameters at the map level: each entry's own
419
- * `TDiagram`/`TPositioned` are only known inside that entry's own closure
420
- * (see `xychartModule`/`erModule`/`flowchartModule` above, which are fully
421
- * typed); the map just needs one consistent shape to hold heterogeneous
422
- * entries in.
423
- */
424
- type AnyDiagramModule = DiagramModule<
425
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- see comment above; each entry is fully typed at its own definition site.
426
- any,
427
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- see comment above; each entry is fully typed at its own definition site.
428
- any
429
- >
430
-
431
- export const diagramRegistry: Record<DiagramType, AnyDiagramModule> = {
432
- xychart: xychartModule,
433
- er: erModule,
434
- sequence: sequenceModule,
435
- class: classModule,
436
- flowchart: flowchartModule,
437
- architecture: architectureModule,
438
-
439
- c4: c4Module,
440
- pie: pieModule,
441
- }