dsh-model-everything 0.5.0 → 0.5.1
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.en-US.md +12 -0
- package/README.md +4 -0
- package/lib/client.js +2437 -216
- package/lib/render/channels.js +243 -0
- package/lib/render/collapse.js +12 -20
- package/lib/render/components.js +99 -0
- package/lib/render/coords.js +288 -0
- package/lib/render/cycle-break.js +147 -0
- package/lib/render/dummy.js +43 -0
- package/lib/render/from-mermaid.js +34 -10
- package/lib/render/from-plantuml.js +318 -46
- package/lib/render/layer.js +91 -0
- package/lib/render/layout.js +27 -11
- package/lib/render/network-simplex.js +272 -0
- package/lib/render/order.js +122 -0
- package/lib/render/paint.js +764 -67
- package/lib/render/place.js +393 -121
- package/lib/render/route.js +225 -0
- package/lib/render/svg.js +143 -21
- package/lib/render/symbol.js +108 -0
- package/lib/render/text.js +74 -0
- package/lib/render/wrap.js +87 -0
- package/lib/types/render/channels.d.ts +63 -0
- package/lib/types/render/components.d.ts +57 -0
- package/lib/types/render/coords.d.ts +64 -0
- package/lib/types/render/cycle-break.d.ts +45 -0
- package/lib/types/render/dummy.d.ts +32 -0
- package/lib/types/render/from-plantuml.d.ts +12 -6
- package/lib/types/render/layer.d.ts +28 -0
- package/lib/types/render/layout.d.ts +43 -11
- package/lib/types/render/model.d.ts +17 -0
- package/lib/types/render/network-simplex.d.ts +54 -0
- package/lib/types/render/order.d.ts +27 -0
- package/lib/types/render/paint.d.ts +42 -9
- package/lib/types/render/place.d.ts +35 -19
- package/lib/types/render/route.d.ts +77 -0
- package/lib/types/render/svg.d.ts +1 -1
- package/lib/types/render/symbol.d.ts +73 -0
- package/lib/types/render/text.d.ts +38 -0
- package/lib/types/render/wrap.d.ts +27 -0
- package/package.json +148 -148
- package/skills/model-everything-diagram/SKILL.md +84 -82
- package/src/render/channels.ts +309 -0
- package/src/render/collapse.ts +150 -155
- package/src/render/components.ts +126 -0
- package/src/render/coords.ts +328 -0
- package/src/render/cycle-break.ts +164 -0
- package/src/render/dummy.ts +65 -0
- package/src/render/from-mermaid.ts +261 -236
- package/src/render/from-plantuml.ts +469 -178
- package/src/render/layer.ts +98 -0
- package/src/render/layout.ts +101 -62
- package/src/render/model.ts +86 -67
- package/src/render/network-simplex.ts +290 -0
- package/src/render/order.ts +139 -0
- package/src/render/paint.ts +1006 -290
- package/src/render/place.ts +527 -234
- package/src/render/route.ts +269 -0
- package/src/render/svg.ts +270 -127
- package/src/render/symbol.ts +137 -0
- package/src/render/text.ts +86 -0
- package/src/render/wrap.ts +103 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wrapping: turning one endless column into a page.
|
|
3
|
+
*
|
|
4
|
+
* A chain of twelve boxes has twelve layers, and layering alone draws it as a single column taller than anything a
|
|
5
|
+
* reader can take in - a strip, not a drawing. Graphviz and ELK both answer this with a wrapping pass: cut the layer
|
|
6
|
+
* sequence into bands and stand the bands side by side, so reading order becomes "down the page, then the next
|
|
7
|
+
* column", the way text wraps.
|
|
8
|
+
*
|
|
9
|
+
* The cut is chosen, not guessed: each candidate number of bands is scored by how close the packed page gets to the
|
|
10
|
+
* aspect ratio a page and a landscape screen share, and the best one wins. A drawing that is already close to that
|
|
11
|
+
* shape is left alone - wrapping exists for the strip, not for every tall drawing.
|
|
12
|
+
*
|
|
13
|
+
* Pure: layer sizes in, band ranges and offsets out. The caller applies them.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/** The aspect ratio a page and a landscape screen share. */
|
|
17
|
+
const PAGE_ASPECT = 1.6
|
|
18
|
+
|
|
19
|
+
/** A drawing shorter than this many layers is read better stacked, whatever its proportions. */
|
|
20
|
+
const MIN_LAYERS_TO_WRAP = 4
|
|
21
|
+
|
|
22
|
+
/** A drawing that is not this tall relative to its width is not a strip. */
|
|
23
|
+
const STRIP_RATIO = 2
|
|
24
|
+
|
|
25
|
+
export interface BandRange {
|
|
26
|
+
/** The first and last layer the band holds, inclusive. */
|
|
27
|
+
first: number
|
|
28
|
+
last: number
|
|
29
|
+
/** How far right the band stands, relative to the first one. */
|
|
30
|
+
offsetX: number
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface BandPlan {
|
|
34
|
+
bands: BandRange[]
|
|
35
|
+
width: number
|
|
36
|
+
height: number
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** The height of a run of layers with the gap between them. */
|
|
40
|
+
function runHeight(layerHeight: number[], first: number, last: number, gap: number): number {
|
|
41
|
+
let total = 0
|
|
42
|
+
for (let index = first; index <= last; index += 1) {
|
|
43
|
+
total += layerHeight[index]
|
|
44
|
+
if (index < last) total += gap
|
|
45
|
+
}
|
|
46
|
+
return total
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** The width of a run of layers: the widest layer sets it. */
|
|
50
|
+
function runWidth(layerWidth: number[], first: number, last: number): number {
|
|
51
|
+
let widest = 0
|
|
52
|
+
for (let index = first; index <= last; index += 1) widest = Math.max(widest, layerWidth[index])
|
|
53
|
+
return widest
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** How far the packed page is from the target shape, in log space so half and double count the same. */
|
|
57
|
+
function shapeError(width: number, height: number, aspect: number): number {
|
|
58
|
+
if (width <= 0 || height <= 0) return Infinity
|
|
59
|
+
const ratio = Math.max(width, height) / Math.min(width, height)
|
|
60
|
+
return Math.abs(Math.log(ratio / aspect))
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function planBands(layerWidth: number[], layerHeight: number[], gap: number, aspect: number = PAGE_ASPECT): BandPlan {
|
|
64
|
+
const count = layerWidth.length
|
|
65
|
+
if (count === 0) return { bands: [], width: 0, height: 0 }
|
|
66
|
+
const single: BandPlan = {
|
|
67
|
+
bands: [{ first: 0, last: count - 1, offsetX: 0 }],
|
|
68
|
+
width: runWidth(layerWidth, 0, count - 1),
|
|
69
|
+
height: runHeight(layerHeight, 0, count - 1, gap),
|
|
70
|
+
}
|
|
71
|
+
if (count < MIN_LAYERS_TO_WRAP || single.height <= single.width * STRIP_RATIO) return single
|
|
72
|
+
|
|
73
|
+
const columnGap = gap * 2
|
|
74
|
+
let best = single
|
|
75
|
+
let bestError = shapeError(single.width, single.height, aspect)
|
|
76
|
+
for (let bands = 2; bands < count; bands += 1) {
|
|
77
|
+
const base = Math.floor(count / bands)
|
|
78
|
+
const extra = count % bands
|
|
79
|
+
const ranges: Array<{ first: number; last: number }> = []
|
|
80
|
+
let cursor = 0
|
|
81
|
+
for (let band = 0; band < bands; band += 1) {
|
|
82
|
+
const size = base + (band < extra ? 1 : 0)
|
|
83
|
+
ranges.push({ first: cursor, last: cursor + size - 1 })
|
|
84
|
+
cursor += size
|
|
85
|
+
}
|
|
86
|
+
let width = columnGap * (bands - 1)
|
|
87
|
+
let height = 0
|
|
88
|
+
for (const range of ranges) {
|
|
89
|
+
width += runWidth(layerWidth, range.first, range.last)
|
|
90
|
+
height = Math.max(height, runHeight(layerHeight, range.first, range.last, gap))
|
|
91
|
+
}
|
|
92
|
+
if (shapeError(width, height, aspect) >= bestError) continue
|
|
93
|
+
const planned: BandRange[] = []
|
|
94
|
+
let offsetX = 0
|
|
95
|
+
for (const range of ranges) {
|
|
96
|
+
planned.push({ first: range.first, last: range.last, offsetX })
|
|
97
|
+
offsetX += runWidth(layerWidth, range.first, range.last) + columnGap
|
|
98
|
+
}
|
|
99
|
+
best = { bands: planned, width, height }
|
|
100
|
+
bestError = shapeError(width, height, aspect)
|
|
101
|
+
}
|
|
102
|
+
return best
|
|
103
|
+
}
|