@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.
- 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 +897 -849
- package/dist/index.js.map +1 -1
- package/package.json +14 -5
- package/src/__tests__/c4-label-clearance-1290.test.ts +0 -112
- package/src/__tests__/c4-line-ends-1208.test.ts +0 -52
- package/src/__tests__/c4-mermaid-reference.test.ts +0 -124
- package/src/__tests__/c4-svg.test.ts +0 -337
- package/src/__tests__/c4-text-width-1210.test.ts +0 -43
- package/src/__tests__/class-component-order-1249.test.ts +0 -40
- package/src/__tests__/class-diamond-markers-1232.test.ts +0 -59
- package/src/__tests__/class-member-right-padding-1238.test.ts +0 -43
- package/src/__tests__/class-namespace-1196.test.ts +0 -165
- package/src/__tests__/class-namespace-sparse-elk-1196.test.ts +0 -96
- package/src/__tests__/class-visibility-markers-1237.test.ts +0 -27
- package/src/__tests__/edge-jog-straightening-1388.test.ts +0 -57
- package/src/__tests__/elk-adapter-utils.test.ts +0 -166
- package/src/__tests__/er-attribute-right-padding-1262.test.ts +0 -47
- package/src/__tests__/er-cardinality-markers-1233.test.ts +0 -35
- package/src/__tests__/er-default-direction-1250.test.ts +0 -69
- package/src/__tests__/er-edge-label-contrast-1244.test.ts +0 -58
- package/src/__tests__/fixtures/c4-mermaid-reference.json +0 -626
- package/src/__tests__/flowchart-parallel-edge-lanes-1308.test.ts +0 -168
- package/src/__tests__/pie-layout.test.ts +0 -215
- package/src/__tests__/pie-svg.test.ts +0 -194
- package/src/__tests__/render-mermaid-svg.test.ts +0 -64
- package/src/__tests__/sequence-label-clearance-1242.test.ts +0 -162
- package/src/__tests__/sequence-nested-activation-1241.test.ts +0 -37
- package/src/__tests__/svg-edge-to-own-cluster-1310.test.ts +0 -32
- package/src/__tests__/xychart-smooth-curve.test.ts +0 -42
- package/src/__tests__/xychart-x-label-overlap-1243.test.ts +0 -62
- 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 -277
- 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
package/src/er/layout.ts
DELETED
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ER diagram layout engine (ELK.js).
|
|
3
|
-
*
|
|
4
|
-
* Each entity box has:
|
|
5
|
-
* 1. Header (entity name)
|
|
6
|
-
* 2. Attribute rows (type, name, keys)
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import type { ElkNode, ElkExtendedEdge } from 'elkjs'
|
|
10
|
-
import type {
|
|
11
|
-
ErDiagram,
|
|
12
|
-
ErEntity,
|
|
13
|
-
PositionedErDiagram,
|
|
14
|
-
PositionedErEntity,
|
|
15
|
-
PositionedErRelationship,
|
|
16
|
-
} from '@zombie-mermaid/mermaid-parser'
|
|
17
|
-
import type { ErRenderOptions } from '@zombie-mermaid/core'
|
|
18
|
-
import {
|
|
19
|
-
estimateTextWidth,
|
|
20
|
-
estimateMonoTextWidth,
|
|
21
|
-
FONT_WEIGHTS,
|
|
22
|
-
resolveFontSizes,
|
|
23
|
-
} from '../styles.ts'
|
|
24
|
-
import { elkLayoutSync } from '../elk-instance.ts'
|
|
25
|
-
import { extractEdgePoints } from '../layout-engine/elk-adapter-utils.ts'
|
|
26
|
-
import {
|
|
27
|
-
ELK_DIRECTION_FALLBACK,
|
|
28
|
-
baseElkLayoutOptions,
|
|
29
|
-
buildElkEdge,
|
|
30
|
-
buildElkLeafNode,
|
|
31
|
-
directionToElk,
|
|
32
|
-
} from '../layout-engine/elk-graph-builder.ts'
|
|
33
|
-
|
|
34
|
-
/** Layout constants for ER diagrams */
|
|
35
|
-
const ER = {
|
|
36
|
-
padding: 40,
|
|
37
|
-
boxPadX: 14,
|
|
38
|
-
headerHeight: 34,
|
|
39
|
-
rowHeight: 22,
|
|
40
|
-
minWidth: 140,
|
|
41
|
-
attrFontSize: 11,
|
|
42
|
-
attrFontWeight: 400,
|
|
43
|
-
nodeSpacing: 70,
|
|
44
|
-
layerSpacing: 90,
|
|
45
|
-
} as const
|
|
46
|
-
|
|
47
|
-
type EntitySizeMap = Map<string, { width: number; height: number }>
|
|
48
|
-
|
|
49
|
-
/** Build ELK graph and size map from an ER diagram. */
|
|
50
|
-
/**
|
|
51
|
-
* Width of an attribute row sized for the worst-case glyph advance.
|
|
52
|
-
*
|
|
53
|
-
* The mono face advances 0.6em per glyph (6.6px at the 11px attribute size),
|
|
54
|
-
* but browsers that don't position glyphs at subpixel offsets (headless
|
|
55
|
-
* Chromium on Linux) round each advance to a whole pixel, so a long row draws
|
|
56
|
-
* wider than `estimateMonoTextWidth` says and the type runs into the
|
|
57
|
-
* right-aligned name (#1262, same cause as class members in #1238).
|
|
58
|
-
*/
|
|
59
|
-
function attrTextWidth(text: string): number {
|
|
60
|
-
return text.length * Math.ceil(estimateMonoTextWidth('M', ER.attrFontSize))
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function buildErElkGraph(
|
|
64
|
-
diagram: ErDiagram,
|
|
65
|
-
options: ErRenderOptions,
|
|
66
|
-
): { elkGraph: ElkNode; entitySizes: EntitySizeMap } {
|
|
67
|
-
const entitySizes: EntitySizeMap = new Map()
|
|
68
|
-
const fontSizes = resolveFontSizes(options.fontSizes)
|
|
69
|
-
|
|
70
|
-
for (const entity of diagram.entities) {
|
|
71
|
-
const headerTextW = estimateTextWidth(
|
|
72
|
-
entity.label,
|
|
73
|
-
fontSizes.nodeLabel,
|
|
74
|
-
FONT_WEIGHTS.nodeLabel,
|
|
75
|
-
)
|
|
76
|
-
let maxAttrW = 0
|
|
77
|
-
for (const attr of entity.attributes) {
|
|
78
|
-
const attrText = `${attr.type} ${attr.name}${attr.keys.length > 0 ? ' ' + attr.keys.join(',') : ''}`
|
|
79
|
-
const w = attrTextWidth(attrText)
|
|
80
|
-
if (w > maxAttrW) maxAttrW = w
|
|
81
|
-
}
|
|
82
|
-
const width = Math.max(
|
|
83
|
-
ER.minWidth,
|
|
84
|
-
headerTextW + ER.boxPadX * 2,
|
|
85
|
-
maxAttrW + ER.boxPadX * 2,
|
|
86
|
-
)
|
|
87
|
-
const height =
|
|
88
|
-
ER.headerHeight + Math.max(entity.attributes.length, 1) * ER.rowHeight
|
|
89
|
-
entitySizes.set(entity.id, { width, height })
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Iterate entitySizes directly (populated above, in diagram.entities order)
|
|
93
|
-
// rather than looking each entity back up by id — sidesteps needing an
|
|
94
|
-
// assertion or invariant check for a lookup that can't actually miss.
|
|
95
|
-
const children: ElkNode[] = []
|
|
96
|
-
for (const [id, size] of entitySizes) {
|
|
97
|
-
children.push(buildElkLeafNode(id, size))
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// ER edge labels carry no per-label layout options — placement is set
|
|
101
|
-
// once on the root graph below (`elk.edgeLabels.placement: CENTER`).
|
|
102
|
-
const labelStyle = { fontSize: fontSizes.edgeLabel }
|
|
103
|
-
|
|
104
|
-
const edges: ElkExtendedEdge[] = []
|
|
105
|
-
for (const [i, rel] of diagram.relationships.entries()) {
|
|
106
|
-
edges.push(
|
|
107
|
-
buildElkEdge({
|
|
108
|
-
id: `e${i}`,
|
|
109
|
-
source: rel.entity1,
|
|
110
|
-
target: rel.entity2,
|
|
111
|
-
label: rel.label,
|
|
112
|
-
labelStyle,
|
|
113
|
-
}),
|
|
114
|
-
)
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const elkGraph: ElkNode = {
|
|
118
|
-
id: 'root',
|
|
119
|
-
layoutOptions: {
|
|
120
|
-
...baseElkLayoutOptions({
|
|
121
|
-
// A source with no `direction` statement lays out top-to-bottom,
|
|
122
|
-
// as official Mermaid does (#1250). See ELK_DIRECTION_FALLBACK.
|
|
123
|
-
direction: directionToElk(diagram.direction, ELK_DIRECTION_FALLBACK.er),
|
|
124
|
-
nodeSpacing: ER.nodeSpacing,
|
|
125
|
-
layerSpacing: ER.layerSpacing,
|
|
126
|
-
padding: ER.padding,
|
|
127
|
-
}),
|
|
128
|
-
'elk.edgeLabels.placement': 'CENTER',
|
|
129
|
-
// Keep declaration order as the crossing-minimization tie-break and
|
|
130
|
-
// center children under their parents, as official Mermaid does.
|
|
131
|
-
'elk.layered.considerModelOrder.strategy': 'NODES_AND_EDGES',
|
|
132
|
-
'elk.layered.nodePlacement.bk.fixedAlignment': 'BALANCED',
|
|
133
|
-
},
|
|
134
|
-
children,
|
|
135
|
-
edges,
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
return { elkGraph, entitySizes }
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/** Extract positioned entities and relationships from ELK result. */
|
|
142
|
-
function extractErLayout(
|
|
143
|
-
result: ElkNode,
|
|
144
|
-
diagram: ErDiagram,
|
|
145
|
-
entitySizes: EntitySizeMap,
|
|
146
|
-
): PositionedErDiagram {
|
|
147
|
-
const entityLookup = new Map<string, ErEntity>()
|
|
148
|
-
for (const entity of diagram.entities) entityLookup.set(entity.id, entity)
|
|
149
|
-
|
|
150
|
-
const positionedEntities: PositionedErEntity[] = []
|
|
151
|
-
for (const child of result.children ?? []) {
|
|
152
|
-
const entity = entityLookup.get(child.id)
|
|
153
|
-
if (entity) {
|
|
154
|
-
const size = entitySizes.get(entity.id)
|
|
155
|
-
if (!size) {
|
|
156
|
-
// Unreachable — entitySizes is populated for every diagram.entities
|
|
157
|
-
// entry, and entityLookup/entity.id come from that same list.
|
|
158
|
-
/* v8 ignore next */
|
|
159
|
-
throw new Error(`Missing computed size for entity "${entity.id}"`)
|
|
160
|
-
}
|
|
161
|
-
positionedEntities.push({
|
|
162
|
-
id: entity.id,
|
|
163
|
-
label: entity.label,
|
|
164
|
-
attributes: entity.attributes,
|
|
165
|
-
x: child.x ?? 0,
|
|
166
|
-
y: child.y ?? 0,
|
|
167
|
-
width: child.width ?? size.width,
|
|
168
|
-
height: child.height ?? size.height,
|
|
169
|
-
headerHeight: ER.headerHeight,
|
|
170
|
-
rowHeight: ER.rowHeight,
|
|
171
|
-
})
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const relationships: PositionedErRelationship[] = []
|
|
176
|
-
for (const [i, elkEdge] of (result.edges ?? []).entries()) {
|
|
177
|
-
// diagram.relationships[i] is guaranteed by construction: buildErElkGraph
|
|
178
|
-
// creates exactly one ELK edge per relationship, in the same order.
|
|
179
|
-
const rel = diagram.relationships[i]!
|
|
180
|
-
|
|
181
|
-
const points = extractEdgePoints(elkEdge)
|
|
182
|
-
|
|
183
|
-
relationships.push({
|
|
184
|
-
entity1: rel.entity1,
|
|
185
|
-
entity2: rel.entity2,
|
|
186
|
-
cardinality1: rel.cardinality1,
|
|
187
|
-
cardinality2: rel.cardinality2,
|
|
188
|
-
label: rel.label,
|
|
189
|
-
identifying: rel.identifying,
|
|
190
|
-
points,
|
|
191
|
-
})
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
return {
|
|
195
|
-
width: result.width ?? 600,
|
|
196
|
-
height: result.height ?? 400,
|
|
197
|
-
entities: positionedEntities,
|
|
198
|
-
relationships,
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* Lay out a parsed ER diagram using ELK.js (synchronous).
|
|
204
|
-
*/
|
|
205
|
-
export function layoutErDiagramSync(
|
|
206
|
-
diagram: ErDiagram,
|
|
207
|
-
options: ErRenderOptions = {},
|
|
208
|
-
): PositionedErDiagram {
|
|
209
|
-
if (diagram.entities.length === 0) {
|
|
210
|
-
return { width: 0, height: 0, entities: [], relationships: [] }
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
const { elkGraph, entitySizes } = buildErElkGraph(diagram, options)
|
|
214
|
-
const result = elkLayoutSync(elkGraph, options.layoutCache)
|
|
215
|
-
return extractErLayout(result, diagram, entitySizes)
|
|
216
|
-
}
|