@diagrammo/dgmo 0.47.0 → 0.48.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/dist/auto.js +1 -1
- package/dist/auto.mjs +1 -1
- package/dist/element.js +1 -1
- package/dist/element.mjs +1 -1
- package/package.json +19 -70
- package/dist/advanced.cjs +0 -71648
- package/dist/advanced.d.cts +0 -5719
- package/dist/auto.cjs +0 -70648
- package/dist/auto.d.cts +0 -54
- package/dist/block.cjs +0 -70208
- package/dist/block.d.cts +0 -115
- package/dist/editor.cjs +0 -526
- package/dist/editor.d.cts +0 -26
- package/dist/element.cjs +0 -70530
- package/dist/element.d.cts +0 -62
- package/dist/highlight.cjs +0 -852
- package/dist/highlight.d.cts +0 -49
- package/dist/index.cjs +0 -70491
- package/dist/index.d.cts +0 -160
- package/dist/pert.cjs +0 -325
- package/dist/pert.d.cts +0 -559
- package/dist/themes-1-CuKpeH.d.cts +0 -908
- package/src/advanced.ts +0 -873
- package/src/arc/parser.ts +0 -15
- package/src/arc/renderer.ts +0 -633
- package/src/auto/index.ts +0 -621
- package/src/auto/shared.ts +0 -370
- package/src/auto/styles.ts +0 -73
- package/src/block/layout.ts +0 -198
- package/src/block/parser.ts +0 -427
- package/src/block/renderer.ts +0 -484
- package/src/block/types.ts +0 -67
- package/src/boxes-and-lines/collapse.ts +0 -96
- package/src/boxes-and-lines/focus.ts +0 -257
- package/src/boxes-and-lines/label-placement.ts +0 -339
- package/src/boxes-and-lines/layout-grouped.ts +0 -912
- package/src/boxes-and-lines/layout-layered.ts +0 -722
- package/src/boxes-and-lines/layout-search.ts +0 -1678
- package/src/boxes-and-lines/layout.ts +0 -398
- package/src/boxes-and-lines/parser.ts +0 -1181
- package/src/boxes-and-lines/renderer.ts +0 -1465
- package/src/boxes-and-lines/types.ts +0 -66
- package/src/c4/layout.ts +0 -2441
- package/src/c4/parser.ts +0 -1158
- package/src/c4/renderer.ts +0 -2008
- package/src/c4/types.ts +0 -89
- package/src/chart-type-registry.ts +0 -529
- package/src/chart-types.ts +0 -225
- package/src/chart.ts +0 -685
- package/src/charts-d3/bar.ts +0 -338
- package/src/charts-d3/chord.ts +0 -140
- package/src/charts-d3/function.ts +0 -147
- package/src/charts-d3/funnel.ts +0 -104
- package/src/charts-d3/heatmap.ts +0 -145
- package/src/charts-d3/index.ts +0 -337
- package/src/charts-d3/interactions.ts +0 -477
- package/src/charts-d3/line.ts +0 -344
- package/src/charts-d3/mount.ts +0 -151
- package/src/charts-d3/pie.ts +0 -117
- package/src/charts-d3/polar.ts +0 -89
- package/src/charts-d3/radar.ts +0 -0
- package/src/charts-d3/sankey.ts +0 -0
- package/src/charts-d3/scatter.ts +0 -185
- package/src/charts-d3/shared.ts +0 -208
- package/src/class/layout.ts +0 -326
- package/src/class/parser.ts +0 -635
- package/src/class/renderer.ts +0 -793
- package/src/class/types.ts +0 -58
- package/src/cli-banner.ts +0 -106
- package/src/cli.ts +0 -1080
- package/src/colors-diagnostics.ts +0 -35
- package/src/colors.ts +0 -379
- package/src/completion-types.ts +0 -27
- package/src/completion.ts +0 -2668
- package/src/cycle/layout.ts +0 -1026
- package/src/cycle/parser.ts +0 -387
- package/src/cycle/renderer.ts +0 -653
- package/src/cycle/types.ts +0 -101
- package/src/d3.ts +0 -1434
- package/src/data-chart-parser.ts +0 -1007
- package/src/dgmo-router.ts +0 -296
- package/src/diagnostics-registry.ts +0 -108
- package/src/diagnostics.ts +0 -0
- package/src/dimensions.ts +0 -20
- package/src/directives-registry.ts +0 -396
- package/src/editor/dgmo.grammar +0 -76
- package/src/editor/dgmo.grammar.d.ts +0 -2
- package/src/editor/dgmo.grammar.js +0 -18
- package/src/editor/dgmo.grammar.terms.d.ts +0 -5
- package/src/editor/dgmo.grammar.terms.js +0 -35
- package/src/editor/highlight-api.ts +0 -596
- package/src/editor/highlight.ts +0 -36
- package/src/editor/index.ts +0 -27
- package/src/editor/keywords.ts +0 -128
- package/src/editor/tokens.ts +0 -30
- package/src/element/index.ts +0 -432
- package/src/embed/css.ts +0 -312
- package/src/embed/escape.ts +0 -15
- package/src/embed/index.ts +0 -280
- package/src/er/classify.ts +0 -228
- package/src/er/layout.ts +0 -530
- package/src/er/parser.ts +0 -750
- package/src/er/renderer.ts +0 -725
- package/src/er/types.ts +0 -52
- package/src/error-card.ts +0 -269
- package/src/event-line/diagnostics.ts +0 -117
- package/src/event-line/parser.ts +0 -643
- package/src/event-line/renderer.ts +0 -1742
- package/src/event-line/types.ts +0 -74
- package/src/fonts.ts +0 -3
- package/src/gantt/calculator.ts +0 -979
- package/src/gantt/parser.ts +0 -1641
- package/src/gantt/renderer.ts +0 -3787
- package/src/gantt/resolver.ts +0 -172
- package/src/gantt/types.ts +0 -206
- package/src/graph/diagnostics.ts +0 -64
- package/src/graph/edge-spline.ts +0 -29
- package/src/graph/flowchart-parser.ts +0 -759
- package/src/graph/flowchart-renderer.ts +0 -817
- package/src/graph/layout.ts +0 -472
- package/src/graph/notes.ts +0 -21
- package/src/graph/state-collapse.ts +0 -78
- package/src/graph/state-parser.ts +0 -574
- package/src/graph/state-renderer.ts +0 -653
- package/src/graph/types.ts +0 -65
- package/src/index.ts +0 -261
- package/src/infra/compute.ts +0 -1385
- package/src/infra/layout.ts +0 -888
- package/src/infra/parser.ts +0 -1234
- package/src/infra/renderer.ts +0 -2534
- package/src/infra/roles.ts +0 -75
- package/src/infra/types.ts +0 -216
- package/src/infra/validation.ts +0 -201
- package/src/journey-map/layout.ts +0 -490
- package/src/journey-map/parser.ts +0 -557
- package/src/journey-map/renderer.ts +0 -1580
- package/src/journey-map/types.ts +0 -47
- package/src/kanban/mutations.ts +0 -175
- package/src/kanban/parser.ts +0 -509
- package/src/kanban/renderer.ts +0 -1449
- package/src/kanban/types.ts +0 -39
- package/src/label-layout.ts +0 -368
- package/src/map/colorize.ts +0 -54
- package/src/map/completion.ts +0 -316
- package/src/map/context-labels.ts +0 -609
- package/src/map/data/PROVENANCE.json +0 -1
- package/src/map/data/README.md +0 -40
- package/src/map/data/airport-collisions.json +0 -1
- package/src/map/data/airports.json +0 -1
- package/src/map/data/gazetteer.json +0 -1
- package/src/map/data/lakes.json +0 -1
- package/src/map/data/mountain-ranges.json +0 -1
- package/src/map/data/na-lakes.json +0 -1
- package/src/map/data/na-land.json +0 -1
- package/src/map/data/region-names.json +0 -1
- package/src/map/data/rivers.json +0 -1
- package/src/map/data/types.ts +0 -121
- package/src/map/data/us-states.json +0 -1
- package/src/map/data/water-bodies.json +0 -1
- package/src/map/data/world-coarse.json +0 -1
- package/src/map/data/world-detail.json +0 -1
- package/src/map/diagnostics.ts +0 -134
- package/src/map/dimensions.ts +0 -150
- package/src/map/geo-query.ts +0 -295
- package/src/map/geo.ts +0 -438
- package/src/map/invert.ts +0 -111
- package/src/map/layout.ts +0 -5069
- package/src/map/legend-band.ts +0 -127
- package/src/map/load-data.ts +0 -186
- package/src/map/parser.ts +0 -783
- package/src/map/renderer.ts +0 -1445
- package/src/map/resolved-types.ts +0 -160
- package/src/map/resolver.ts +0 -1146
- package/src/map/types.ts +0 -194
- package/src/mindmap/collapse.ts +0 -67
- package/src/mindmap/layout.ts +0 -649
- package/src/mindmap/parser.ts +0 -430
- package/src/mindmap/renderer.ts +0 -637
- package/src/mindmap/text-wrap.ts +0 -218
- package/src/mindmap/types.ts +0 -56
- package/src/org/collapse.ts +0 -151
- package/src/org/layout.ts +0 -1262
- package/src/org/parser.ts +0 -519
- package/src/org/renderer.ts +0 -866
- package/src/org/resolver.ts +0 -636
- package/src/palettes/atlas.ts +0 -77
- package/src/palettes/blueprint.ts +0 -73
- package/src/palettes/catppuccin.ts +0 -84
- package/src/palettes/color-utils.ts +0 -443
- package/src/palettes/index.ts +0 -67
- package/src/palettes/nord.ts +0 -67
- package/src/palettes/registry.ts +0 -114
- package/src/palettes/slate.ts +0 -73
- package/src/palettes/tidewater.ts +0 -73
- package/src/palettes/tokyo-night.ts +0 -86
- package/src/palettes/types.ts +0 -88
- package/src/pert/analyzer.ts +0 -1183
- package/src/pert/diagnostics.ts +0 -110
- package/src/pert/index.ts +0 -43
- package/src/pert/internal.ts +0 -252
- package/src/pert/layout.ts +0 -971
- package/src/pert/monte-carlo.ts +0 -446
- package/src/pert/parser.ts +0 -1606
- package/src/pert/renderer.ts +0 -4009
- package/src/pert/share-normalize.ts +0 -62
- package/src/pert/types.ts +0 -604
- package/src/pyramid/parser.ts +0 -185
- package/src/pyramid/renderer.ts +0 -768
- package/src/pyramid/types.ts +0 -28
- package/src/quadrant/parser.ts +0 -18
- package/src/quadrant/renderer.ts +0 -638
- package/src/raci/diagnostics.ts +0 -213
- package/src/raci/index.ts +0 -23
- package/src/raci/mutations.ts +0 -321
- package/src/raci/parser.ts +0 -699
- package/src/raci/renderer.ts +0 -1627
- package/src/raci/types.ts +0 -82
- package/src/raci/variants.ts +0 -320
- package/src/render.ts +0 -268
- package/src/ring/parser.ts +0 -212
- package/src/ring/renderer.ts +0 -490
- package/src/ring/types.ts +0 -27
- package/src/sequence/collapse.ts +0 -174
- package/src/sequence/parser.ts +0 -1596
- package/src/sequence/participant-inference.ts +0 -152
- package/src/sequence/renderer.ts +0 -3168
- package/src/sequence/tag-resolution.ts +0 -164
- package/src/sharing.ts +0 -211
- package/src/sitemap/collapse.ts +0 -100
- package/src/sitemap/layout.ts +0 -925
- package/src/sitemap/parser.ts +0 -755
- package/src/sitemap/renderer.ts +0 -828
- package/src/sitemap/types.ts +0 -42
- package/src/slope/parser.ts +0 -18
- package/src/slope/renderer.ts +0 -378
- package/src/swimlane/diagnostics.ts +0 -94
- package/src/swimlane/layout.ts +0 -597
- package/src/swimlane/parser.ts +0 -613
- package/src/swimlane/renderer.ts +0 -681
- package/src/swimlane/types.ts +0 -151
- package/src/tech-radar/interactive.ts +0 -1129
- package/src/tech-radar/layout.ts +0 -197
- package/src/tech-radar/parser.ts +0 -436
- package/src/tech-radar/renderer.ts +0 -1239
- package/src/tech-radar/shared.ts +0 -151
- package/src/tech-radar/types.ts +0 -86
- package/src/themes.ts +0 -22
- package/src/timeline/parser.ts +0 -472
- package/src/timeline/renderer.ts +0 -3024
- package/src/timeline/types.ts +0 -33
- package/src/timeline/viz-parser.ts +0 -21
- package/src/treemap/diagnostics.ts +0 -62
- package/src/treemap/layout-radial.ts +0 -233
- package/src/treemap/layout.ts +0 -189
- package/src/treemap/parser.ts +0 -463
- package/src/treemap/renderer-radial.ts +0 -438
- package/src/treemap/renderer.ts +0 -572
- package/src/treemap/treemap-shared.ts +0 -309
- package/src/treemap/types.ts +0 -60
- package/src/utils/arrow-markers.ts +0 -51
- package/src/utils/arrows-diagnostics.ts +0 -62
- package/src/utils/arrows.ts +0 -227
- package/src/utils/brand.ts +0 -61
- package/src/utils/card.ts +0 -183
- package/src/utils/collapse-engine/tree-edges.ts +0 -115
- package/src/utils/collapse-engine/tree.ts +0 -117
- package/src/utils/d3-helpers.ts +0 -219
- package/src/utils/d3-types.ts +0 -9
- package/src/utils/description-helpers.ts +0 -38
- package/src/utils/duration.ts +0 -312
- package/src/utils/export-container.ts +0 -41
- package/src/utils/expr-eval.ts +0 -27
- package/src/utils/fit-canvas.ts +0 -64
- package/src/utils/hover-styles.ts +0 -673
- package/src/utils/inline-markdown.ts +0 -96
- package/src/utils/legend-constants.ts +0 -48
- package/src/utils/legend-d3.ts +0 -618
- package/src/utils/legend-integration.ts +0 -107
- package/src/utils/legend-layout.ts +0 -776
- package/src/utils/legend-svg.ts +0 -214
- package/src/utils/legend-types.ts +0 -272
- package/src/utils/name-normalize.ts +0 -163
- package/src/utils/note-box/constants.ts +0 -25
- package/src/utils/note-box/index.ts +0 -11
- package/src/utils/note-box/metrics.ts +0 -90
- package/src/utils/note-box/svg.ts +0 -331
- package/src/utils/notes/bounds.ts +0 -30
- package/src/utils/notes/build.ts +0 -131
- package/src/utils/notes/index.ts +0 -18
- package/src/utils/notes/model.ts +0 -19
- package/src/utils/notes/parse.ts +0 -131
- package/src/utils/notes/place.ts +0 -177
- package/src/utils/notes/resolve.ts +0 -88
- package/src/utils/number-format.ts +0 -36
- package/src/utils/parsing.ts +0 -953
- package/src/utils/reserved-key-registry.ts +0 -239
- package/src/utils/safe-href.ts +0 -38
- package/src/utils/scaling.ts +0 -97
- package/src/utils/svg-embed.ts +0 -251
- package/src/utils/tag-groups.ts +0 -607
- package/src/utils/text-measure.ts +0 -122
- package/src/utils/time-ticks.ts +0 -253
- package/src/utils/title-constants.ts +0 -24
- package/src/utils/visual-conventions.ts +0 -61
- package/src/utils/wrapped-desc.ts +0 -87
- package/src/venn/parser.ts +0 -18
- package/src/venn/renderer.ts +0 -1047
- package/src/version-control/diagnostics.ts +0 -67
- package/src/version-control/parser.ts +0 -544
- package/src/version-control/renderer.ts +0 -724
- package/src/version-control/types.ts +0 -100
- package/src/visualizations/parse.ts +0 -1560
- package/src/visualizations/types.ts +0 -262
- package/src/wireframe/layout.ts +0 -479
- package/src/wireframe/parser.ts +0 -1114
- package/src/wireframe/renderer.ts +0 -1318
- package/src/wireframe/types.ts +0 -110
- package/src/wordcloud/parser.ts +0 -18
- package/src/wordcloud/renderer.ts +0 -357
package/src/class/layout.ts
DELETED
|
@@ -1,326 +0,0 @@
|
|
|
1
|
-
import dagre from '@dagrejs/dagre';
|
|
2
|
-
import { measureText } from '../utils/text-measure';
|
|
3
|
-
import {
|
|
4
|
-
resolveNotes,
|
|
5
|
-
buildPlacedNotes,
|
|
6
|
-
noteCanvasShift,
|
|
7
|
-
type PlacedNote,
|
|
8
|
-
} from '../utils/notes';
|
|
9
|
-
import type { ParsedClassDiagram, ClassNode, RelationshipType } from './types';
|
|
10
|
-
|
|
11
|
-
// ============================================================
|
|
12
|
-
// Layout types
|
|
13
|
-
// ============================================================
|
|
14
|
-
|
|
15
|
-
export interface ClassLayoutNode extends ClassNode {
|
|
16
|
-
readonly x: number;
|
|
17
|
-
readonly y: number;
|
|
18
|
-
readonly width: number;
|
|
19
|
-
readonly height: number;
|
|
20
|
-
readonly headerHeight: number;
|
|
21
|
-
readonly fieldsHeight: number;
|
|
22
|
-
readonly methodsHeight: number;
|
|
23
|
-
/** A note floated beside this class (never moves the box). */
|
|
24
|
-
readonly note?: PlacedNote;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export interface ClassLayoutOptions {
|
|
28
|
-
/**
|
|
29
|
-
* 1-based source line numbers of notes the user has collapsed. A
|
|
30
|
-
* collapsed note renders as a corner badge and reserves no space.
|
|
31
|
-
*/
|
|
32
|
-
collapsedNotes?: ReadonlySet<number>;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export interface ClassLayoutEdge {
|
|
36
|
-
readonly source: string;
|
|
37
|
-
readonly target: string;
|
|
38
|
-
readonly type: RelationshipType;
|
|
39
|
-
readonly points: ReadonlyArray<{ readonly x: number; readonly y: number }>;
|
|
40
|
-
readonly label?: string;
|
|
41
|
-
readonly lineNumber: number;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export interface ClassLayoutResult {
|
|
45
|
-
readonly nodes: readonly ClassLayoutNode[];
|
|
46
|
-
readonly edges: readonly ClassLayoutEdge[];
|
|
47
|
-
readonly width: number;
|
|
48
|
-
readonly height: number;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// ============================================================
|
|
52
|
-
// Sizing constants
|
|
53
|
-
// ============================================================
|
|
54
|
-
|
|
55
|
-
const MIN_WIDTH = 140;
|
|
56
|
-
const PADDING_X = 24;
|
|
57
|
-
const HEADER_BASE = 36;
|
|
58
|
-
// Font sizes mirror the renderer: class name at CLASS_FONT_SIZE, members and
|
|
59
|
-
// the modifier badge at MEMBER_FONT_SIZE. Keep these in sync with renderer.ts.
|
|
60
|
-
const CLASS_FONT_SIZE = 13;
|
|
61
|
-
const MEMBER_FONT_SIZE = 11;
|
|
62
|
-
const MODIFIER_BADGE = 16; // extra height for <<interface>> etc.
|
|
63
|
-
const MEMBER_LINE_HEIGHT = 18;
|
|
64
|
-
const COMPARTMENT_PADDING_Y = 8;
|
|
65
|
-
const SEPARATOR_HEIGHT = 1;
|
|
66
|
-
|
|
67
|
-
// ============================================================
|
|
68
|
-
// Node sizing
|
|
69
|
-
// ============================================================
|
|
70
|
-
|
|
71
|
-
function computeNodeDimensions(node: ClassNode): {
|
|
72
|
-
width: number;
|
|
73
|
-
height: number;
|
|
74
|
-
headerHeight: number;
|
|
75
|
-
fieldsHeight: number;
|
|
76
|
-
methodsHeight: number;
|
|
77
|
-
} {
|
|
78
|
-
const fields = node.members.filter((m) => !m.isMethod);
|
|
79
|
-
const methods = node.members.filter((m) => m.isMethod);
|
|
80
|
-
const isEnum = node.modifier === 'enum';
|
|
81
|
-
|
|
82
|
-
// Width: max rendered pixel width of class name, modifier badge, and members.
|
|
83
|
-
// Measure each at the font size the renderer draws it with.
|
|
84
|
-
let maxTextWidth = measureText(node.name, CLASS_FONT_SIZE);
|
|
85
|
-
if (node.modifier) {
|
|
86
|
-
// Renderer draws the badge as «modifier» at MEMBER_FONT_SIZE.
|
|
87
|
-
maxTextWidth = Math.max(
|
|
88
|
-
maxTextWidth,
|
|
89
|
-
measureText(`«${node.modifier}»`, MEMBER_FONT_SIZE)
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
for (const m of node.members) {
|
|
93
|
-
let memberText = m.name;
|
|
94
|
-
if (m.isMethod) {
|
|
95
|
-
memberText += `(${m.params ?? ''})`;
|
|
96
|
-
if (m.type) memberText += `: ${m.type}`;
|
|
97
|
-
} else if (m.type) {
|
|
98
|
-
memberText += `: ${m.type}`;
|
|
99
|
-
}
|
|
100
|
-
// Add visibility prefix width
|
|
101
|
-
memberText = `+ ${memberText}`;
|
|
102
|
-
maxTextWidth = Math.max(
|
|
103
|
-
maxTextWidth,
|
|
104
|
-
measureText(memberText, MEMBER_FONT_SIZE)
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
const width = Math.max(MIN_WIDTH, maxTextWidth + PADDING_X);
|
|
108
|
-
|
|
109
|
-
// Header height
|
|
110
|
-
const headerHeight = HEADER_BASE + (node.modifier ? MODIFIER_BADGE : 0);
|
|
111
|
-
|
|
112
|
-
// Fields compartment
|
|
113
|
-
let fieldsHeight: number;
|
|
114
|
-
if (isEnum) {
|
|
115
|
-
// Enum values go in fields compartment
|
|
116
|
-
const enumValues = node.members; // all members are enum values
|
|
117
|
-
if (enumValues.length > 0) {
|
|
118
|
-
fieldsHeight =
|
|
119
|
-
COMPARTMENT_PADDING_Y * 2 +
|
|
120
|
-
enumValues.length * MEMBER_LINE_HEIGHT +
|
|
121
|
-
SEPARATOR_HEIGHT;
|
|
122
|
-
} else {
|
|
123
|
-
fieldsHeight = SEPARATOR_HEIGHT + COMPARTMENT_PADDING_Y;
|
|
124
|
-
}
|
|
125
|
-
} else {
|
|
126
|
-
if (fields.length > 0) {
|
|
127
|
-
fieldsHeight =
|
|
128
|
-
COMPARTMENT_PADDING_Y * 2 +
|
|
129
|
-
fields.length * MEMBER_LINE_HEIGHT +
|
|
130
|
-
SEPARATOR_HEIGHT;
|
|
131
|
-
} else {
|
|
132
|
-
// UML: always show attributes compartment
|
|
133
|
-
fieldsHeight = SEPARATOR_HEIGHT + COMPARTMENT_PADDING_Y;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Methods compartment (not for enums)
|
|
138
|
-
let methodsHeight = 0;
|
|
139
|
-
if (!isEnum) {
|
|
140
|
-
if (methods.length > 0) {
|
|
141
|
-
methodsHeight =
|
|
142
|
-
COMPARTMENT_PADDING_Y * 2 +
|
|
143
|
-
methods.length * MEMBER_LINE_HEIGHT +
|
|
144
|
-
SEPARATOR_HEIGHT;
|
|
145
|
-
} else {
|
|
146
|
-
// UML: always show methods compartment
|
|
147
|
-
methodsHeight = SEPARATOR_HEIGHT + COMPARTMENT_PADDING_Y;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const height = headerHeight + fieldsHeight + methodsHeight;
|
|
152
|
-
|
|
153
|
-
return { width, height, headerHeight, fieldsHeight, methodsHeight };
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// ============================================================
|
|
157
|
-
// Layout engine
|
|
158
|
-
// ============================================================
|
|
159
|
-
|
|
160
|
-
export function layoutClassDiagram(
|
|
161
|
-
parsed: ParsedClassDiagram,
|
|
162
|
-
options?: ClassLayoutOptions
|
|
163
|
-
): ClassLayoutResult {
|
|
164
|
-
if (parsed.classes.length === 0) {
|
|
165
|
-
return { nodes: [], edges: [], width: 0, height: 0 };
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const g = new dagre.graphlib.Graph();
|
|
169
|
-
g.setGraph({
|
|
170
|
-
rankdir: 'TB',
|
|
171
|
-
nodesep: 60,
|
|
172
|
-
ranksep: 80,
|
|
173
|
-
edgesep: 20,
|
|
174
|
-
});
|
|
175
|
-
g.setDefaultEdgeLabel(() => ({}));
|
|
176
|
-
|
|
177
|
-
// Compute dimensions and add nodes
|
|
178
|
-
const dimMap = new Map<
|
|
179
|
-
string,
|
|
180
|
-
{
|
|
181
|
-
width: number;
|
|
182
|
-
height: number;
|
|
183
|
-
headerHeight: number;
|
|
184
|
-
fieldsHeight: number;
|
|
185
|
-
methodsHeight: number;
|
|
186
|
-
}
|
|
187
|
-
>();
|
|
188
|
-
|
|
189
|
-
for (const node of parsed.classes) {
|
|
190
|
-
const dims = computeNodeDimensions(node);
|
|
191
|
-
dimMap.set(node.id, dims);
|
|
192
|
-
g.setNode(node.id, {
|
|
193
|
-
label: node.name,
|
|
194
|
-
width: dims.width,
|
|
195
|
-
height: dims.height,
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// Add edges
|
|
200
|
-
for (const rel of parsed.relationships) {
|
|
201
|
-
g.setEdge(rel.source, rel.target, { label: rel.label ?? '' });
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Run layout
|
|
205
|
-
dagre.layout(g);
|
|
206
|
-
|
|
207
|
-
// ── Notes ──────────────────────────────────────────────────
|
|
208
|
-
// Resolve note anchors (no diagnostics here — the parser already emitted
|
|
209
|
-
// them). `no-notes` drops the reserved footprint so layout matches an
|
|
210
|
-
// un-annotated diagram. The note floats beside its class WITHOUT moving
|
|
211
|
-
// it (class TB layout → default side right).
|
|
212
|
-
const notesSuppressed = parsed.options?.['no-notes'] === 'on';
|
|
213
|
-
const noteByNode =
|
|
214
|
-
notesSuppressed || !parsed.notes
|
|
215
|
-
? new Map()
|
|
216
|
-
: resolveNotes(
|
|
217
|
-
parsed.notes,
|
|
218
|
-
parsed.classes.map((c) => ({ id: c.id, label: c.name }))
|
|
219
|
-
);
|
|
220
|
-
const placedNotes = buildPlacedNotes(
|
|
221
|
-
parsed.classes.map((node) => {
|
|
222
|
-
const pos = g.node(node.id);
|
|
223
|
-
return {
|
|
224
|
-
id: node.id,
|
|
225
|
-
x: pos.x,
|
|
226
|
-
y: pos.y,
|
|
227
|
-
width: pos.width,
|
|
228
|
-
height: pos.height,
|
|
229
|
-
};
|
|
230
|
-
}),
|
|
231
|
-
noteByNode,
|
|
232
|
-
'TB',
|
|
233
|
-
options?.collapsedNotes
|
|
234
|
-
);
|
|
235
|
-
|
|
236
|
-
// Extract positioned nodes
|
|
237
|
-
const layoutNodes: ClassLayoutNode[] = parsed.classes.map((node) => {
|
|
238
|
-
const pos = g.node(node.id);
|
|
239
|
-
const dims = dimMap.get(node.id)!;
|
|
240
|
-
const note = placedNotes.get(node.id);
|
|
241
|
-
return {
|
|
242
|
-
...node,
|
|
243
|
-
x: pos.x,
|
|
244
|
-
y: pos.y,
|
|
245
|
-
width: dims.width,
|
|
246
|
-
height: dims.height,
|
|
247
|
-
headerHeight: dims.headerHeight,
|
|
248
|
-
fieldsHeight: dims.fieldsHeight,
|
|
249
|
-
methodsHeight: dims.methodsHeight,
|
|
250
|
-
...(note && { note }),
|
|
251
|
-
};
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
// Extract edge waypoints
|
|
255
|
-
const layoutEdges: ClassLayoutEdge[] = parsed.relationships.map((rel) => {
|
|
256
|
-
const edgeData = g.edge(rel.source, rel.target);
|
|
257
|
-
const layoutEdge: ClassLayoutEdge = {
|
|
258
|
-
source: rel.source,
|
|
259
|
-
target: rel.target,
|
|
260
|
-
type: rel.type,
|
|
261
|
-
points: edgeData?.points ?? [],
|
|
262
|
-
...(rel.label !== undefined && { label: rel.label }),
|
|
263
|
-
lineNumber: rel.lineNumber,
|
|
264
|
-
};
|
|
265
|
-
return layoutEdge;
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
// Content bbox over nodes and their (floated) notes. A note placed
|
|
269
|
-
// above/left can land at negative coords; when it does, shift everything
|
|
270
|
-
// so nothing clips. Un-annotated diagrams keep min ≥ 0 → no shift.
|
|
271
|
-
let bbMinX = Infinity;
|
|
272
|
-
let bbMinY = Infinity;
|
|
273
|
-
let bbMaxX = -Infinity;
|
|
274
|
-
let bbMaxY = -Infinity;
|
|
275
|
-
const extend = (l: number, t: number, r: number, b: number): void => {
|
|
276
|
-
if (l < bbMinX) bbMinX = l;
|
|
277
|
-
if (t < bbMinY) bbMinY = t;
|
|
278
|
-
if (r > bbMaxX) bbMaxX = r;
|
|
279
|
-
if (b > bbMaxY) bbMaxY = b;
|
|
280
|
-
};
|
|
281
|
-
for (const node of layoutNodes) {
|
|
282
|
-
extend(
|
|
283
|
-
node.x - node.width / 2,
|
|
284
|
-
node.y - node.height / 2,
|
|
285
|
-
node.x + node.width / 2,
|
|
286
|
-
node.y + node.height / 2
|
|
287
|
-
);
|
|
288
|
-
if (node.note && !node.note.collapsed) {
|
|
289
|
-
extend(
|
|
290
|
-
node.x + node.note.x,
|
|
291
|
-
node.y + node.note.y,
|
|
292
|
-
node.x + node.note.x + node.note.width,
|
|
293
|
-
node.y + node.note.y + node.note.height
|
|
294
|
-
);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
if (!Number.isFinite(bbMinX)) {
|
|
298
|
-
bbMinX = 0;
|
|
299
|
-
bbMinY = 0;
|
|
300
|
-
bbMaxX = 0;
|
|
301
|
-
bbMaxY = 0;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
const { shiftX, shiftY } = noteCanvasShift(bbMinX, bbMinY);
|
|
305
|
-
const shifted = shiftX !== 0 || shiftY !== 0;
|
|
306
|
-
const finalNodes = shifted
|
|
307
|
-
? layoutNodes.map((n) => ({ ...n, x: n.x + shiftX, y: n.y + shiftY }))
|
|
308
|
-
: layoutNodes;
|
|
309
|
-
const finalEdges = shifted
|
|
310
|
-
? layoutEdges.map((e) => ({
|
|
311
|
-
...e,
|
|
312
|
-
points: e.points.map((pt) => ({ x: pt.x + shiftX, y: pt.y + shiftY })),
|
|
313
|
-
}))
|
|
314
|
-
: layoutEdges;
|
|
315
|
-
|
|
316
|
-
// Totals: max extent (incl. notes) + the prior 40 px margin.
|
|
317
|
-
const totalWidth = bbMaxX + shiftX + 40;
|
|
318
|
-
const totalHeight = bbMaxY + shiftY + 40;
|
|
319
|
-
|
|
320
|
-
return {
|
|
321
|
-
nodes: finalNodes,
|
|
322
|
-
edges: finalEdges,
|
|
323
|
-
width: totalWidth,
|
|
324
|
-
height: totalHeight,
|
|
325
|
-
};
|
|
326
|
-
}
|