@zombie-mermaid/svg-renderer 4.2.3 → 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.
- package/README.md +15 -1
- package/dist/index.cjs +52 -52
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -4
- package/dist/index.d.ts +23 -4
- package/dist/index.js +890 -850
- package/dist/index.js.map +1 -1
- package/package.json +14 -6
- package/src/c4/arial-widths.ts +0 -59
- package/src/c4/layout.ts +0 -680
- package/src/c4/metrics.ts +0 -261
- package/src/c4/renderer.ts +0 -366
- package/src/class/layout.ts +0 -525
- package/src/class/renderer.ts +0 -669
- package/src/edge-curves.ts +0 -205
- package/src/elk-instance.ts +0 -292
- package/src/er/layout.ts +0 -216
- package/src/er/renderer.ts +0 -516
- package/src/generated/mono-font-subset.ts +0 -32
- package/src/index.ts +0 -310
- package/src/layout-engine/back-edges.ts +0 -73
- package/src/layout-engine/compound-flat.ts +0 -916
- package/src/layout-engine/constants.ts +0 -19
- package/src/layout-engine/edge-bundling.ts +0 -458
- package/src/layout-engine/elk-adapter-utils.ts +0 -81
- package/src/layout-engine/elk-graph-builder.ts +0 -245
- package/src/layout-engine/from-elk.ts +0 -767
- package/src/layout-engine/inner-edges.ts +0 -329
- package/src/layout-engine/jog-straightening.ts +0 -52
- package/src/layout-engine/layer-alignment.ts +0 -174
- package/src/layout-engine/layout-hints.ts +0 -27
- package/src/layout-engine/to-elk.ts +0 -855
- package/src/layout-engine.ts +0 -115
- package/src/pie/layout.ts +0 -234
- package/src/pie/renderer.ts +0 -161
- package/src/registry.ts +0 -441
- package/src/renderer.ts +0 -1510
- package/src/resolve-colors.ts +0 -339
- package/src/sequence/layout.ts +0 -766
- package/src/sequence/renderer.ts +0 -687
- package/src/shape-clipping.ts +0 -197
- package/src/styles.ts +0 -145
- package/src/title-gaps.ts +0 -161
- package/src/xychart/layout.ts +0 -727
- 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
|
-
}
|