@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.
Files changed (45) 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 +890 -850
  7. package/dist/index.js.map +1 -1
  8. package/package.json +14 -6
  9. package/src/c4/arial-widths.ts +0 -59
  10. package/src/c4/layout.ts +0 -680
  11. package/src/c4/metrics.ts +0 -261
  12. package/src/c4/renderer.ts +0 -366
  13. package/src/class/layout.ts +0 -525
  14. package/src/class/renderer.ts +0 -669
  15. package/src/edge-curves.ts +0 -205
  16. package/src/elk-instance.ts +0 -292
  17. package/src/er/layout.ts +0 -216
  18. package/src/er/renderer.ts +0 -516
  19. package/src/generated/mono-font-subset.ts +0 -32
  20. package/src/index.ts +0 -310
  21. package/src/layout-engine/back-edges.ts +0 -73
  22. package/src/layout-engine/compound-flat.ts +0 -916
  23. package/src/layout-engine/constants.ts +0 -19
  24. package/src/layout-engine/edge-bundling.ts +0 -458
  25. package/src/layout-engine/elk-adapter-utils.ts +0 -81
  26. package/src/layout-engine/elk-graph-builder.ts +0 -245
  27. package/src/layout-engine/from-elk.ts +0 -767
  28. package/src/layout-engine/inner-edges.ts +0 -329
  29. package/src/layout-engine/jog-straightening.ts +0 -52
  30. package/src/layout-engine/layer-alignment.ts +0 -174
  31. package/src/layout-engine/layout-hints.ts +0 -27
  32. package/src/layout-engine/to-elk.ts +0 -855
  33. package/src/layout-engine.ts +0 -115
  34. package/src/pie/layout.ts +0 -234
  35. package/src/pie/renderer.ts +0 -161
  36. package/src/registry.ts +0 -441
  37. package/src/renderer.ts +0 -1510
  38. package/src/resolve-colors.ts +0 -339
  39. package/src/sequence/layout.ts +0 -766
  40. package/src/sequence/renderer.ts +0 -687
  41. package/src/shape-clipping.ts +0 -197
  42. package/src/styles.ts +0 -145
  43. package/src/title-gaps.ts +0 -161
  44. package/src/xychart/layout.ts +0 -727
  45. 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
- }