@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
@@ -1,245 +0,0 @@
1
- /**
2
- * Shared ELK graph-*construction* helpers.
3
- *
4
- * The reverse direction (reading geometry back out of an ELK result) lives
5
- * in `./elk-adapter-utils.ts`; this module is its input-side counterpart.
6
- *
7
- * Three renderers build ELK's typed JSON input independently —
8
- * `./to-elk.ts` (flowchart + state), `../class/layout.ts`, and
9
- * `../er/layout.ts`. They differ in domain model and in which extra
10
- * `elk.*` options they set, but the primitives underneath are identical:
11
- * one direction mapping, one `elk.padding` string format, one leaf-node
12
- * shape, and one measured edge-label box. Those primitives live here so
13
- * the three call sites can't drift (issue #616).
14
- *
15
- * This module deliberately does **not** try to abstract over the three
16
- * diagram types' own graph shapes (subgraph nesting, hierarchical ports,
17
- * note links) — that would be an engine-neutral intermediate graph, which
18
- * is the separately-scoped work in #538.
19
- */
20
-
21
- import type { ElkExtendedEdge, ElkLabel, ElkNode, LayoutOptions } from 'elkjs'
22
- import type { Direction } from '@zombie-mermaid/core'
23
- import { measureMultilineText } from '@zombie-mermaid/core'
24
- import { FONT_WEIGHTS } from '../styles.ts'
25
-
26
- // ============================================================================
27
- // Direction
28
- // ============================================================================
29
-
30
- /** The four values ELK's `elk.direction` option accepts in this codebase. */
31
- export type ElkDirection = 'DOWN' | 'UP' | 'LEFT' | 'RIGHT'
32
-
33
- /**
34
- * The `elk.direction` each diagram type falls back to when its source
35
- * carries no `direction` statement.
36
- *
37
- * These genuinely differ per diagram type, and the difference is
38
- * intentional rather than an accident of three separate implementations:
39
- *
40
- * - **flowchart / state** — `DOWN`. `MermaidGraph.direction` is a required
41
- * field the parser always fills in (defaulting to `TD`), so the fallback
42
- * is only a type-level backstop; the effective default is mermaid's own
43
- * top-down flowchart default.
44
- * - **class** — `DOWN`. `ClassDiagram` has no direction concept at all (see
45
- * `ClassRenderOptions` in `packages/core/src/types.ts`: class diagrams
46
- * "have no `direction` or `curve` concept"), so this is the renderer's
47
- * single fixed orientation, matching Mermaid's own TB class rendering —
48
- * which `../class/layout.ts` relies on to put a `note for X` above its
49
- * class.
50
- * - **C4** — `DOWN`. `C4Diagram.direction` is never set by the parser (C4
51
- * sources have no direction statement), only by `RenderOptions.direction`,
52
- * so an unset one is the top-down layout every C4 diagram is drawn in.
53
- * - **ER** — `DOWN`. An ER diagram's `direction` is optional
54
- * (`ErDiagram.direction?`), left `undefined` when the source has no
55
- * `direction` statement, and official Mermaid lays those out top-to-bottom
56
- * (#1250; this renderer used to lay them out left-to-right).
57
- * `direction TB`/`LR`/`BT`/`RL` in the source (or
58
- * `RenderOptions.direction`, applied via `withDirectionOverride`) still
59
- * wins over it.
60
- *
61
- * The *mappings* were never in conflict — both hand-rolled
62
- * `directionToElk()` implementations agreed on all five `Direction` values
63
- * (`LR`→`RIGHT`, `RL`→`LEFT`, `BT`→`UP`, `TD`/`TB`→`DOWN`). Only the
64
- * no-direction fallback differed, which is why it is a parameter here
65
- * rather than something to reconcile away.
66
- */
67
- export const ELK_DIRECTION_FALLBACK = {
68
- flowchart: 'DOWN',
69
- state: 'DOWN',
70
- class: 'DOWN',
71
- er: 'DOWN',
72
- c4: 'DOWN',
73
- } as const satisfies Record<string, ElkDirection>
74
-
75
- /**
76
- * Convert a Mermaid `direction` to ELK's `elk.direction` value.
77
- *
78
- * `fallback` covers the no-`direction`-statement case only — every member
79
- * of `Direction` has an explicit mapping. Pass the diagram type's entry
80
- * from `ELK_DIRECTION_FALLBACK` rather than a bare string literal, so the
81
- * per-type defaults stay documented in one place.
82
- */
83
- export function directionToElk(
84
- dir: Direction | undefined,
85
- fallback: ElkDirection,
86
- ): ElkDirection {
87
- switch (dir) {
88
- case 'LR':
89
- return 'RIGHT'
90
- case 'RL':
91
- return 'LEFT'
92
- case 'BT':
93
- return 'UP'
94
- case 'TD':
95
- case 'TB':
96
- return 'DOWN'
97
- default:
98
- return fallback
99
- }
100
- }
101
-
102
- // ============================================================================
103
- // Layout options
104
- // ============================================================================
105
-
106
- /** Per-side padding, for the asymmetric case (a subgraph's header gap). */
107
- export interface ElkPaddingSides {
108
- top: number
109
- left: number
110
- bottom: number
111
- right: number
112
- }
113
-
114
- /**
115
- * Format ELK's `elk.padding` value. A single number applies to all four
116
- * sides; an object sets them individually.
117
- */
118
- export function elkPadding(padding: number | ElkPaddingSides): string {
119
- const sides: ElkPaddingSides =
120
- typeof padding === 'number'
121
- ? { top: padding, left: padding, bottom: padding, right: padding }
122
- : padding
123
- return `[top=${sides.top},left=${sides.left},bottom=${sides.bottom},right=${sides.right}]`
124
- }
125
-
126
- /**
127
- * The `elk.*` options every one of the three graph builders sets, with the
128
- * values they all agree on. Callers spread the result and add their own
129
- * diagram-specific options on top.
130
- */
131
- export function baseElkLayoutOptions(spec: {
132
- direction: ElkDirection
133
- nodeSpacing: number
134
- layerSpacing: number
135
- padding: number | ElkPaddingSides
136
- }): LayoutOptions {
137
- return {
138
- 'elk.algorithm': 'layered',
139
- 'elk.direction': spec.direction,
140
- 'elk.spacing.nodeNode': String(spec.nodeSpacing),
141
- 'elk.layered.spacing.nodeNodeBetweenLayers': String(spec.layerSpacing),
142
- 'elk.padding': elkPadding(spec.padding),
143
- 'elk.edgeRouting': 'ORTHOGONAL',
144
- }
145
- }
146
-
147
- // ============================================================================
148
- // Nodes
149
- // ============================================================================
150
-
151
- /**
152
- * Build a leaf ELK node.
153
- *
154
- * `label` is attached as an ELK label when supplied — the flowchart/state
155
- * path does that (ELK reads it for nothing, but `from-elk.ts` reads it
156
- * back); class and ER carry labels in their own side tables instead and
157
- * omit it. An empty-string label is still a label, so the check is
158
- * `undefined`, not truthiness.
159
- */
160
- export function buildElkLeafNode(
161
- id: string,
162
- size: { width: number; height: number },
163
- label?: string,
164
- ): ElkNode {
165
- const node: ElkNode = { id, width: size.width, height: size.height }
166
- if (label !== undefined) node.labels = [{ text: label }]
167
- return node
168
- }
169
-
170
- // ============================================================================
171
- // Edges
172
- // ============================================================================
173
-
174
- /**
175
- * Per-label layout options the flowchart/state path sets on every edge
176
- * label. Class and ER instead set `elk.edgeLabels.placement` once on the
177
- * root graph, so they pass no per-label options.
178
- */
179
- export const INLINE_CENTERED_EDGE_LABEL: LayoutOptions = {
180
- 'elk.edgeLabels.inline': 'true',
181
- 'elk.edgeLabels.placement': 'CENTER',
182
- }
183
-
184
- /**
185
- * How a caller wants its edge labels measured and placed. `fontSize` is
186
- * the resolved `fontSizes.edgeLabel`; `layoutOptions`, when given, is
187
- * attached to the ELK label itself.
188
- */
189
- export interface ElkEdgeLabelStyle {
190
- fontSize: number
191
- layoutOptions?: LayoutOptions
192
- }
193
-
194
- /**
195
- * Measure an edge label and build ELK's label box for it.
196
- *
197
- * The `+8` / `+6` are the horizontal/vertical breathing room all three
198
- * builders have always added around the measured text so ELK reserves a
199
- * slightly larger channel than the glyphs strictly need.
200
- */
201
- export function buildElkEdgeLabel(
202
- text: string,
203
- style: ElkEdgeLabelStyle,
204
- ): ElkLabel {
205
- const metrics = measureMultilineText(
206
- text,
207
- style.fontSize,
208
- FONT_WEIGHTS.edgeLabel,
209
- )
210
- const label: ElkLabel = {
211
- text,
212
- width: metrics.width + 8,
213
- height: metrics.height + 6,
214
- }
215
- // Copied, not aliased: every label previously got its own fresh options
216
- // literal, and ELK receives this graph by reference (see
217
- // `elkLayoutSync`'s `saveDispatch`) rather than through a structured
218
- // clone — so a shared object would be shared into ELK's own hands too.
219
- if (style.layoutOptions) label.layoutOptions = { ...style.layoutOptions }
220
- return label
221
- }
222
-
223
- /**
224
- * Build a single-source/single-target ELK edge, with a measured label when
225
- * `label` is non-empty. An absent or empty label leaves `labels` off the
226
- * edge entirely (rather than setting it to an empty array or `undefined`),
227
- * matching what all three builders did by hand.
228
- */
229
- export function buildElkEdge(spec: {
230
- id: string
231
- source: string
232
- target: string
233
- label?: string
234
- labelStyle: ElkEdgeLabelStyle
235
- }): ElkExtendedEdge {
236
- const edge: ElkExtendedEdge = {
237
- id: spec.id,
238
- sources: [spec.source],
239
- targets: [spec.target],
240
- }
241
- if (spec.label) {
242
- edge.labels = [buildElkEdgeLabel(spec.label, spec.labelStyle)]
243
- }
244
- return edge
245
- }