hexwright 0.1.0 → 0.3.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 +121 -4
- package/dist/cli.js +408 -70
- package/dist/client.js +1 -1
- package/package.json +2 -2
- package/profiles/hexagonal-kotlin.yml +12 -0
package/README.md
CHANGED
|
@@ -90,19 +90,63 @@ as a hub with the domains that touch it around it.
|
|
|
90
90
|
| `impact` | the above plus everything that depends on a changed type |
|
|
91
91
|
| `core` | Entity · Service · UseCase · Port · Event — the whole shape |
|
|
92
92
|
| `all` | everything, adapters and DTOs included |
|
|
93
|
+
| `violations` | only the breaches, and the types they run through |
|
|
93
94
|
| `domain:<name>` | one bounded context and what it touches |
|
|
94
95
|
|
|
96
|
+
`violations` is a **state** view: it draws what is wrong now, not what this branch
|
|
97
|
+
changed. Unlike the toggle in the web UI it is not narrowed by component, because
|
|
98
|
+
a violation with one end hidden reads as no violation at all.
|
|
99
|
+
|
|
100
|
+
### Before and after
|
|
101
|
+
|
|
102
|
+
A branch that *removes* violations, or swaps one port for another, is not
|
|
103
|
+
described by the delta alone. The picture worth showing is the state it started
|
|
104
|
+
from — which is exactly the state the working tree no longer has. `--at base`
|
|
105
|
+
draws the same types in their pre-branch state:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
hexwright render --repo . --base main --at base --image before.png
|
|
109
|
+
hexwright render --repo . --base main --image after.png
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The before picture carries **no delta styling** — nothing in a picture of the past
|
|
113
|
+
can be added or modified — and violations stay red, which is the question it
|
|
114
|
+
exists to answer. It needs `--base`. A branch that only adds types has no before
|
|
115
|
+
state at all; the command says so and exits 0.
|
|
116
|
+
|
|
117
|
+
A before/after pair **lines up**. Positions, domain boxes, colours and canvas
|
|
118
|
+
width all follow the set of types being laid out, and the two halves differ by
|
|
119
|
+
whatever the branch added or removed — so each render lays out from the union of
|
|
120
|
+
both and draws only its own half. A type keeps its place across the pair, and a
|
|
121
|
+
deletion leaves the gap where it used to be. Neither command needs a flag for
|
|
122
|
+
this and neither can be run "wrong": both derive the union from the same two
|
|
123
|
+
graphs.
|
|
124
|
+
|
|
95
125
|
There is no browser involved — the coordinates are a pure function, so the SVG
|
|
96
126
|
is written directly and CI needs no headless Chrome. The same graph always draws
|
|
97
|
-
the same file
|
|
127
|
+
the same file.
|
|
98
128
|
|
|
99
129
|
`--image x.png` also writes `x.svg`. PNG needs the optional `@resvg/resvg-js`;
|
|
100
130
|
without it the SVG is still written and the command says so. GitHub does not
|
|
101
131
|
render SVG in comments, so attach the PNG there and keep the SVG as the artifact.
|
|
102
132
|
|
|
103
|
-
Layout follows the view — `organic` for `delta` and `
|
|
104
|
-
and `all` (concentric rings, read as a shape). `--layout
|
|
105
|
-
overrides; `grid` lists domains left to right, ignoring
|
|
133
|
+
Layout follows the view — `organic` for `delta`, `domain:` and `violations`, `hex`
|
|
134
|
+
for `core` and `all` (concentric rings, read as a shape). `--layout
|
|
135
|
+
organic|grid|hex` overrides; `grid` lists domains left to right, ignoring
|
|
136
|
+
coupling.
|
|
137
|
+
|
|
138
|
+
## Exit codes
|
|
139
|
+
|
|
140
|
+
| command | 1 | 0 |
|
|
141
|
+
|---|---|---|
|
|
142
|
+
| `check` | the repository has a violation — with `--scope delta`, only one the branch introduced | otherwise |
|
|
143
|
+
| `render` | a bad argument, or a base ref that is not in the clone | an image was written, **or there was nothing to draw** |
|
|
144
|
+
| `extract` | the source root or the base ref cannot be read | otherwise |
|
|
145
|
+
|
|
146
|
+
`render` treats an empty picture as an answer rather than a failure. `--view
|
|
147
|
+
violations` on the branch that removed the last one, and `--at base` on a branch
|
|
148
|
+
that only adds types, both print what happened and exit 0 — a non-zero exit there
|
|
149
|
+
would break the very script that produces the pair.
|
|
106
150
|
|
|
107
151
|
## MCP
|
|
108
152
|
|
|
@@ -184,6 +228,22 @@ package prefix, which is inferred automatically:
|
|
|
184
228
|
<base>.common Shared
|
|
185
229
|
```
|
|
186
230
|
|
|
231
|
+
### What a companion object contributes
|
|
232
|
+
|
|
233
|
+
Nothing. A `companion object` is a separate object with its own type, so what it
|
|
234
|
+
names belongs to it rather than to the class it is written inside. The graph
|
|
235
|
+
models types, and a companion is not one.
|
|
236
|
+
|
|
237
|
+
Attributing its contents to the enclosing class is what made a sealed root appear
|
|
238
|
+
to depend on its own variants — the factory naming them lives in the companion —
|
|
239
|
+
and made a value class wrapping a `UUID` appear to depend on an id generator.
|
|
240
|
+
|
|
241
|
+
The cost is deliberate and worth knowing: **a coupling that exists only inside a
|
|
242
|
+
companion is not reported.** A domain entity whose companion holds
|
|
243
|
+
`fun fromRow(row: JpaRow)` would otherwise be caught as a layer back-reference.
|
|
244
|
+
Mapping belongs in the adapter in this architecture, so it should be rare, but it
|
|
245
|
+
is not impossible.
|
|
246
|
+
|
|
187
247
|
## What it produces
|
|
188
248
|
|
|
189
249
|
```
|
|
@@ -320,6 +380,39 @@ domains 16
|
|
|
320
380
|
Zero Ports or a domain count of 1 means the paths or the base package are not
|
|
321
381
|
matching your layout yet.
|
|
322
382
|
|
|
383
|
+
## Identity
|
|
384
|
+
|
|
385
|
+
A type keeping another aggregate's id — `MediaItem` holding a `BlobId`, not a
|
|
386
|
+
`Blob` — is referencing that aggregate, and referencing it the deliberately weaker
|
|
387
|
+
way. That is drawn as `REFERENCES`, pointed at the aggregate rather than at the id,
|
|
388
|
+
and styled lighter than a direct dependency so the two do not read alike. It never
|
|
389
|
+
counts as a boundary violation: pointing at another context by id is how you avoid
|
|
390
|
+
coupling to it, and reporting it would penalise the design that got it right.
|
|
391
|
+
|
|
392
|
+
Nothing in the source says which id belongs to what, so the profile says which
|
|
393
|
+
convention to read:
|
|
394
|
+
|
|
395
|
+
```yaml
|
|
396
|
+
identity:
|
|
397
|
+
from: property # the type declaring `val id: T` owns T
|
|
398
|
+
property: id
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
```yaml
|
|
402
|
+
identity:
|
|
403
|
+
from: suffix # BlobId → Blob
|
|
404
|
+
suffix: Id
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
`property` is the default because it is structural, and because it survives an
|
|
408
|
+
aggregate whose name is not the identifier's stem — `MediaId` identifies
|
|
409
|
+
`MediaItem`, and stripping the suffix would look for a `Media` that does not
|
|
410
|
+
exist. Use `suffix` when aggregates do not carry their own id.
|
|
411
|
+
|
|
412
|
+
Where an identifier cannot be resolved — its aggregate is outside the analysed
|
|
413
|
+
source, or two unrelated types claim it — the edge stays on the identifier rather
|
|
414
|
+
than being pointed at a guess. Remove the `identity` block and none are resolved.
|
|
415
|
+
|
|
323
416
|
## Boundary rules
|
|
324
417
|
|
|
325
418
|
An Entity may be touched by, within the same domain: `Service`, `Port`, `Entity`,
|
|
@@ -331,6 +424,30 @@ is a violation:
|
|
|
331
424
|
- a DTO or UseCase exposing an Entity — domain model leaked into a contract
|
|
332
425
|
- application/domain referencing adapter — layer back-reference
|
|
333
426
|
|
|
427
|
+
## Releasing
|
|
428
|
+
|
|
429
|
+
Trunk-based, tag-triggered. There is no release branch: `main` is the only branch
|
|
430
|
+
that ships, and one can always be cut from a tag later if a backport ever needs
|
|
431
|
+
one.
|
|
432
|
+
|
|
433
|
+
```bash
|
|
434
|
+
npm version minor -m "release: v%s" # bumps package.json, commits, tags
|
|
435
|
+
git push --follow-tags
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
Pushing the tag runs [`release.yml`](.github/workflows/release.yml), which
|
|
439
|
+
refuses to publish unless the tagged commit is on `main` and the tag matches the
|
|
440
|
+
version in `package.json` — a tag that disagrees with what npm receives is worse
|
|
441
|
+
than a failed release, because it is only found out later. It then runs the same
|
|
442
|
+
gate a pull request has to clear, publishes with provenance, and opens a GitHub
|
|
443
|
+
Release for the tag.
|
|
444
|
+
|
|
445
|
+
There is no npm token. npm is configured to trust this repository and this
|
|
446
|
+
workflow **by filename**, and the OIDC token GitHub mints for the job is exchanged
|
|
447
|
+
for publish rights — so nothing has to be stored, rotated, or kept from expiring.
|
|
448
|
+
The catch is the filename: renaming `release.yml` breaks publishing until npm's
|
|
449
|
+
trusted-publisher entry is updated to match.
|
|
450
|
+
|
|
334
451
|
## Status
|
|
335
452
|
|
|
336
453
|
Early. Kotlin extractor only; validated against one production codebase
|
package/dist/cli.js
CHANGED
|
@@ -146,6 +146,10 @@ async function serveStdio(getQuery, project) {
|
|
|
146
146
|
await server.connect(new StdioServerTransport());
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
+
// src/model.ts
|
|
150
|
+
var nodeIndex = (g) => new Map(g.nodes.map((n) => [n.id, n]));
|
|
151
|
+
var edgeKey = (e) => `${e.src}\0${e.dst}\0${e.rel}`;
|
|
152
|
+
|
|
149
153
|
// src/output/tsv.ts
|
|
150
154
|
function toTsv(g) {
|
|
151
155
|
const prefix = commonPrefix(g.nodes.map((n) => n.id));
|
|
@@ -583,7 +587,9 @@ function gridLayout(g, maxWidth = 3e3) {
|
|
|
583
587
|
}
|
|
584
588
|
|
|
585
589
|
// src/render/select.ts
|
|
586
|
-
|
|
590
|
+
var NothingToDraw = class extends Error {
|
|
591
|
+
};
|
|
592
|
+
function select(g, view, showIdentifiers = false, changed) {
|
|
587
593
|
const byId = new Map(g.nodes.map((n) => [n.id, n]));
|
|
588
594
|
const real = g.edges.filter((e) => showIdentifiers || !e.identifierOnly);
|
|
589
595
|
const withNeighbours = (seed) => {
|
|
@@ -595,6 +601,13 @@ function select(g, view, showIdentifiers = false) {
|
|
|
595
601
|
return out;
|
|
596
602
|
};
|
|
597
603
|
const changedSet = () => {
|
|
604
|
+
if (changed) {
|
|
605
|
+
const seed2 = new Set([...changed].filter((id) => byId.has(id)));
|
|
606
|
+
if (!seed2.size) {
|
|
607
|
+
throw new NothingToDraw("nothing this branch touches exists here \u2014 nothing to draw");
|
|
608
|
+
}
|
|
609
|
+
return seed2;
|
|
610
|
+
}
|
|
598
611
|
const seed = new Set(
|
|
599
612
|
g.nodes.filter((n) => n.status === "added" || n.status === "modified").map((n) => n.id)
|
|
600
613
|
);
|
|
@@ -613,7 +626,18 @@ function select(g, view, showIdentifiers = false) {
|
|
|
613
626
|
};
|
|
614
627
|
let keep;
|
|
615
628
|
let label;
|
|
616
|
-
|
|
629
|
+
let violatingEdgesOnly = false;
|
|
630
|
+
if (view === "violations") {
|
|
631
|
+
keep = /* @__PURE__ */ new Set();
|
|
632
|
+
for (const e of real) {
|
|
633
|
+
if (!e.violation) continue;
|
|
634
|
+
keep.add(e.src);
|
|
635
|
+
keep.add(e.dst);
|
|
636
|
+
}
|
|
637
|
+
if (!keep.size) throw new NothingToDraw("no violations \u2014 nothing to draw");
|
|
638
|
+
violatingEdgesOnly = true;
|
|
639
|
+
label = "every boundary violation, and the types they run through";
|
|
640
|
+
} else if (view === "all") {
|
|
617
641
|
keep = new Set(g.nodes.map((n) => n.id));
|
|
618
642
|
label = "all types";
|
|
619
643
|
} else if (view === "core") {
|
|
@@ -632,14 +656,16 @@ function select(g, view, showIdentifiers = false) {
|
|
|
632
656
|
keep = changedSet();
|
|
633
657
|
const linked = real.filter((e) => keep.has(e.src) && keep.has(e.dst)).length;
|
|
634
658
|
if (linked) {
|
|
635
|
-
label = "what this branch added and changed";
|
|
659
|
+
label = changed ? "the types this branch touches, as they stand" : "what this branch added and changed";
|
|
636
660
|
} else {
|
|
637
661
|
keep = dependents(keep);
|
|
638
|
-
label = "what this branch changed (no new relations \u2014 showing dependents)";
|
|
662
|
+
label = changed ? "the types this branch touches, and their dependents, as they stand" : "what this branch changed (no new relations \u2014 showing dependents)";
|
|
639
663
|
}
|
|
640
664
|
}
|
|
641
665
|
const nodes = g.nodes.filter((n) => keep.has(n.id));
|
|
642
|
-
const edges = real.filter(
|
|
666
|
+
const edges = real.filter(
|
|
667
|
+
(e) => keep.has(e.src) && keep.has(e.dst) && (!violatingEdgesOnly || e.violation)
|
|
668
|
+
);
|
|
643
669
|
return { graph: { ...g, nodes, edges }, label };
|
|
644
670
|
}
|
|
645
671
|
|
|
@@ -724,6 +750,10 @@ function trim(a, c, b, ab, bb) {
|
|
|
724
750
|
}
|
|
725
751
|
var EDGE = {
|
|
726
752
|
DEPENDS_ON: { width: 1.9, dash: "", bow: 0, arrow: "vee", scale: 0.95 },
|
|
753
|
+
// Thinner and broken up than DEPENDS_ON, because it is a lighter coupling: the
|
|
754
|
+
// reference runs through an identifier, not the type. The distinction is only
|
|
755
|
+
// worth drawing if it reads as weaker at a glance.
|
|
756
|
+
REFERENCES: { width: 1.4, dash: "2 4", bow: 24, arrow: "vee", scale: 0.9 },
|
|
727
757
|
IMPLEMENTS: { width: 2.2, dash: "9 5", bow: 42, arrow: "triangle", scale: 1.35 },
|
|
728
758
|
EXTENDS: { width: 3.4, dash: "3 3", bow: 58, arrow: "triangle", scale: 1.6 }
|
|
729
759
|
};
|
|
@@ -762,16 +792,18 @@ function gridWidthFor(g) {
|
|
|
762
792
|
}
|
|
763
793
|
function renderSvg(g, opt = {}) {
|
|
764
794
|
const layout = opt.layout ?? "hex";
|
|
765
|
-
const
|
|
766
|
-
const
|
|
795
|
+
const frame = opt.frame ?? g;
|
|
796
|
+
const hueOf = hueMap(frame.nodes.map((n) => n.domain));
|
|
797
|
+
const place = layout === "hex" ? hexLayout(frame) : layout === "organic" ? organicLayout(frame) : gridLayout(frame, gridWidthFor(frame));
|
|
767
798
|
const coords = new Map(place.map((p) => [p.id, p]));
|
|
768
|
-
const
|
|
799
|
+
const sit = (n) => {
|
|
769
800
|
const c = coords.get(n.id) ?? { x: 0, y: 0 };
|
|
770
801
|
return { n, x: c.x, y: c.y, ...sizeOf(n) };
|
|
771
|
-
}
|
|
802
|
+
};
|
|
803
|
+
const placed = g.nodes.map(sit);
|
|
772
804
|
const at = new Map(placed.map((p) => [p.n.id, p]));
|
|
773
805
|
const domains = /* @__PURE__ */ new Map();
|
|
774
|
-
for (const p of placed) {
|
|
806
|
+
for (const p of frame === g ? placed : frame.nodes.map(sit)) {
|
|
775
807
|
const b = domains.get(p.n.domain);
|
|
776
808
|
const x1 = Math.min(b ? b.x : Number.POSITIVE_INFINITY, p.x - p.w / 2);
|
|
777
809
|
const y1 = Math.min(b ? b.y : Number.POSITIVE_INFINITY, p.y - p.h / 2);
|
|
@@ -965,13 +997,15 @@ function legendBlock(g, w, top, hueOf) {
|
|
|
965
997
|
`<path d="M${x},${y} L${x + 34},${y}" stroke="${VIOLATION}" stroke-width="3.4" fill="none"/>`,
|
|
966
998
|
`<text x="${x + 40}" y="${y + 4}" font-size="11" fill="${VIOLATION}">boundary violation</text>`
|
|
967
999
|
);
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
1000
|
+
if (g.nodes.some((n) => n.status === "added" || n.status === "modified")) {
|
|
1001
|
+
x += 150;
|
|
1002
|
+
rows.push(
|
|
1003
|
+
`<rect x="${x}" y="${y - 7}" width="14" height="14" rx="3" fill="none" stroke="${ADDED}" stroke-width="3"/>`,
|
|
1004
|
+
`<text x="${x + 20}" y="${y + 4}" font-size="11" fill="${ADDED}">added</text>`,
|
|
1005
|
+
`<rect x="${x + 66}" y="${y - 7}" width="14" height="14" rx="3" fill="none" stroke="${MODIFIED}" stroke-width="2.6" stroke-dasharray="7 4"/>`,
|
|
1006
|
+
`<text x="${x + 86}" y="${y + 4}" font-size="11" fill="${MODIFIED}">modified</text>`
|
|
1007
|
+
);
|
|
1008
|
+
}
|
|
975
1009
|
y += 26;
|
|
976
1010
|
x = 26;
|
|
977
1011
|
rows.push(`<text x="${x}" y="${y + 4}" font-size="11" fill="${DIM}">domain</text>`);
|
|
@@ -998,10 +1032,6 @@ function legendBlock(g, w, top, hueOf) {
|
|
|
998
1032
|
import { readdirSync as readdirSync3, statSync as statSync3 } from "fs";
|
|
999
1033
|
import { join as join4 } from "path";
|
|
1000
1034
|
|
|
1001
|
-
// src/model.ts
|
|
1002
|
-
var nodeIndex = (g) => new Map(g.nodes.map((n) => [n.id, n]));
|
|
1003
|
-
var edgeKey = (e) => `${e.src}\0${e.dst}\0${e.rel}`;
|
|
1004
|
-
|
|
1005
1035
|
// src/delta.ts
|
|
1006
1036
|
function diff(base, head) {
|
|
1007
1037
|
const b = nodeIndex(base);
|
|
@@ -1088,6 +1118,13 @@ var MODS = "(?:public |internal |private |protected |open |abstract |sealed |dat
|
|
|
1088
1118
|
var DECL = new RegExp(
|
|
1089
1119
|
`^(?<mods>${MODS})(?<kw>class|interface|object)\\s+(?<name>[A-Za-z_]\\w*)`
|
|
1090
1120
|
);
|
|
1121
|
+
var TOP_MODS = "(?:public |internal |private |expect |actual |external |inline |suspend |operator |infix |tailrec |const |lateinit )*";
|
|
1122
|
+
var TYPEALIAS = new RegExp(
|
|
1123
|
+
`^${TOP_MODS}typealias\\s+(\\w+)(?:<[^>]*>)?\\s*=\\s*(.+?)\\s*$`
|
|
1124
|
+
);
|
|
1125
|
+
var TOP_LEVEL = new RegExp(
|
|
1126
|
+
`^(?:@\\w+(?:\\([^)]*\\))?\\s+)*${TOP_MODS}(?:typealias|fun|va[lr])\\s`
|
|
1127
|
+
);
|
|
1091
1128
|
var FUN_MODS = "(?:override |open |abstract |suspend |operator |private |internal |protected |inline |final )*";
|
|
1092
1129
|
var SIG = new RegExp(
|
|
1093
1130
|
`^\\s+(?:@\\w+(?:\\([^)]*\\))?\\s*)*(?<mods>${FUN_MODS})fun\\s+(?<name>\\w+)\\s*\\(`
|
|
@@ -1113,45 +1150,97 @@ function structOf(kind) {
|
|
|
1113
1150
|
if (kind === "object") return "Object";
|
|
1114
1151
|
return "Class";
|
|
1115
1152
|
}
|
|
1116
|
-
function
|
|
1153
|
+
function stripNonCode(text) {
|
|
1117
1154
|
const out = [];
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1155
|
+
const n = text.length;
|
|
1156
|
+
const stack = [{ kind: "code", raw: false, depth: 0 }];
|
|
1157
|
+
const blank = (c) => out.push(c === "\n" ? "\n" : " ");
|
|
1158
|
+
let i = 0;
|
|
1159
|
+
while (i < n) {
|
|
1160
|
+
const f = stack[stack.length - 1];
|
|
1122
1161
|
const c = text[i];
|
|
1123
|
-
if (
|
|
1124
|
-
if (c === "
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
if (c === "
|
|
1132
|
-
out.push("
|
|
1162
|
+
if (f.kind === "code") {
|
|
1163
|
+
if (c === "/" && text[i + 1] === "/") {
|
|
1164
|
+
while (i < n && text[i] !== "\n") {
|
|
1165
|
+
out.push(" ");
|
|
1166
|
+
i++;
|
|
1167
|
+
}
|
|
1168
|
+
continue;
|
|
1169
|
+
}
|
|
1170
|
+
if (c === "/" && text[i + 1] === "*") {
|
|
1171
|
+
out.push(" ", " ");
|
|
1172
|
+
i += 2;
|
|
1173
|
+
while (i < n && !(text[i] === "*" && text[i + 1] === "/")) blank(text[i++]);
|
|
1174
|
+
if (i < n) {
|
|
1175
|
+
out.push(" ", " ");
|
|
1176
|
+
i += 2;
|
|
1177
|
+
}
|
|
1178
|
+
continue;
|
|
1179
|
+
}
|
|
1180
|
+
if (c === '"') {
|
|
1181
|
+
const raw = text[i + 1] === '"' && text[i + 2] === '"';
|
|
1182
|
+
const q = raw ? 3 : 1;
|
|
1183
|
+
for (let k = 0; k < q; k++) out.push('"');
|
|
1184
|
+
i += q;
|
|
1185
|
+
stack.push({ kind: "str", raw, depth: 0 });
|
|
1186
|
+
continue;
|
|
1187
|
+
}
|
|
1188
|
+
if (c === "'") {
|
|
1189
|
+
out.push("'");
|
|
1133
1190
|
i++;
|
|
1134
|
-
|
|
1191
|
+
while (i < n && text[i] !== "'" && text[i] !== "\n") {
|
|
1192
|
+
if (text[i] === "\\" && i + 1 < n) {
|
|
1193
|
+
out.push(" ");
|
|
1194
|
+
i++;
|
|
1195
|
+
}
|
|
1196
|
+
blank(text[i++]);
|
|
1197
|
+
}
|
|
1198
|
+
if (i < n && text[i] === "'") {
|
|
1199
|
+
out.push("'");
|
|
1200
|
+
i++;
|
|
1201
|
+
}
|
|
1135
1202
|
continue;
|
|
1136
1203
|
}
|
|
1137
|
-
|
|
1204
|
+
if (c === "{") f.depth++;
|
|
1205
|
+
else if (c === "}") {
|
|
1206
|
+
if (f.depth === 0 && stack.length > 1) {
|
|
1207
|
+
out.push("}");
|
|
1208
|
+
stack.pop();
|
|
1209
|
+
i++;
|
|
1210
|
+
continue;
|
|
1211
|
+
}
|
|
1212
|
+
f.depth--;
|
|
1213
|
+
}
|
|
1214
|
+
out.push(c);
|
|
1215
|
+
i++;
|
|
1138
1216
|
continue;
|
|
1139
1217
|
}
|
|
1140
|
-
if (!
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
i++;
|
|
1218
|
+
if (!f.raw && c === "\\" && i + 1 < n) {
|
|
1219
|
+
out.push(" ", " ");
|
|
1220
|
+
i += 2;
|
|
1144
1221
|
continue;
|
|
1145
1222
|
}
|
|
1146
|
-
if (!
|
|
1147
|
-
|
|
1148
|
-
|
|
1223
|
+
if (!f.raw && c === "\n") {
|
|
1224
|
+
out.push("\n");
|
|
1225
|
+
stack.pop();
|
|
1149
1226
|
i++;
|
|
1150
1227
|
continue;
|
|
1151
1228
|
}
|
|
1152
|
-
if (c === '"'
|
|
1153
|
-
|
|
1154
|
-
|
|
1229
|
+
if (c === '"' && (!f.raw || text[i + 1] === '"' && text[i + 2] === '"')) {
|
|
1230
|
+
const q = f.raw ? 3 : 1;
|
|
1231
|
+
for (let k = 0; k < q; k++) out.push('"');
|
|
1232
|
+
i += q;
|
|
1233
|
+
stack.pop();
|
|
1234
|
+
continue;
|
|
1235
|
+
}
|
|
1236
|
+
if (c === "$" && text[i + 1] === "{") {
|
|
1237
|
+
out.push("$", "{");
|
|
1238
|
+
i += 2;
|
|
1239
|
+
stack.push({ kind: "code", raw: false, depth: 0 });
|
|
1240
|
+
continue;
|
|
1241
|
+
}
|
|
1242
|
+
blank(c);
|
|
1243
|
+
i++;
|
|
1155
1244
|
}
|
|
1156
1245
|
return out.join("");
|
|
1157
1246
|
}
|
|
@@ -1190,7 +1279,7 @@ function collectSigs(body) {
|
|
|
1190
1279
|
}
|
|
1191
1280
|
return out;
|
|
1192
1281
|
}
|
|
1193
|
-
function
|
|
1282
|
+
function ctorParts(header2) {
|
|
1194
1283
|
const i = header2.indexOf("(");
|
|
1195
1284
|
if (i < 0) return [];
|
|
1196
1285
|
let depth = 0;
|
|
@@ -1216,6 +1305,22 @@ function ctorParams(header2) {
|
|
|
1216
1305
|
} else cur.push(ch);
|
|
1217
1306
|
}
|
|
1218
1307
|
parts.push(cur.join(""));
|
|
1308
|
+
return parts;
|
|
1309
|
+
}
|
|
1310
|
+
function ctorDeclared(header2) {
|
|
1311
|
+
const out = [];
|
|
1312
|
+
for (let p of ctorParts(header2)) {
|
|
1313
|
+
p = (p.split("=")[0] ?? "").replace(/\s+/g, " ").trim();
|
|
1314
|
+
p = p.replace(/^(?:@\w+(?:\([^)]*\))?\s*)*/, "");
|
|
1315
|
+
const m = /^(?:private |internal |protected |override )*(?:val|var)\s+(\w+)\s*:\s*(.+)$/.exec(
|
|
1316
|
+
p
|
|
1317
|
+
);
|
|
1318
|
+
if (m) out.push({ name: m[1], type: m[2].trim() });
|
|
1319
|
+
}
|
|
1320
|
+
return out;
|
|
1321
|
+
}
|
|
1322
|
+
function ctorParams(header2) {
|
|
1323
|
+
const parts = ctorParts(header2);
|
|
1219
1324
|
const res = [];
|
|
1220
1325
|
for (let p of parts) {
|
|
1221
1326
|
p = (p.split("=")[0] ?? "").replace(/\s+/g, " ").trim();
|
|
@@ -1316,6 +1421,47 @@ function supertypeNames(text, seenColon) {
|
|
|
1316
1421
|
}
|
|
1317
1422
|
|
|
1318
1423
|
// src/extract/kotlin.ts
|
|
1424
|
+
function bodyEnd(fi, di) {
|
|
1425
|
+
const d = fi.decls[di];
|
|
1426
|
+
let end = di + 1 < fi.decls.length ? fi.decls[di + 1].line : fi.lines.length;
|
|
1427
|
+
for (const s of fi.stops) if (s > d.line && s < end) end = s;
|
|
1428
|
+
return end;
|
|
1429
|
+
}
|
|
1430
|
+
var COMPANION = /^\s+(?:public |internal |private |protected )*companion\s+object\b/;
|
|
1431
|
+
function bodyOf(fi, di) {
|
|
1432
|
+
const d = fi.decls[di];
|
|
1433
|
+
const lines = fi.lines.slice(d.line, bodyEnd(fi, di));
|
|
1434
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1435
|
+
if (!COMPANION.test(lines[i])) continue;
|
|
1436
|
+
let open = lines[i].includes("{") ? i : -1;
|
|
1437
|
+
if (open < 0) {
|
|
1438
|
+
for (let k = i + 1; k < lines.length; k++) {
|
|
1439
|
+
const t = lines[k].trim();
|
|
1440
|
+
if (!t) continue;
|
|
1441
|
+
if (t.startsWith("{")) open = k;
|
|
1442
|
+
break;
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
if (open < 0) {
|
|
1446
|
+
lines[i] = "";
|
|
1447
|
+
continue;
|
|
1448
|
+
}
|
|
1449
|
+
let depth = 0;
|
|
1450
|
+
let j = i;
|
|
1451
|
+
for (; j < lines.length; j++) {
|
|
1452
|
+
if (j >= open) {
|
|
1453
|
+
for (const ch of lines[j]) {
|
|
1454
|
+
if (ch === "{") depth++;
|
|
1455
|
+
else if (ch === "}") depth--;
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
lines[j] = "";
|
|
1459
|
+
if (j >= open && depth <= 0) break;
|
|
1460
|
+
}
|
|
1461
|
+
i = j;
|
|
1462
|
+
}
|
|
1463
|
+
return lines;
|
|
1464
|
+
}
|
|
1319
1465
|
function walk(dir, out = []) {
|
|
1320
1466
|
for (const e of readdirSync2(dir)) {
|
|
1321
1467
|
const p = join2(dir, e);
|
|
@@ -1343,10 +1489,12 @@ function extractKotlin(srcRoot, profile, project, ref) {
|
|
|
1343
1489
|
for (const abs of files) {
|
|
1344
1490
|
const rel = relative2(srcRoot, abs);
|
|
1345
1491
|
if (isExcluded(profile, `/${rel}`)) continue;
|
|
1346
|
-
const lines =
|
|
1492
|
+
const lines = stripNonCode(readFileSync3(abs, "utf8")).split("\n");
|
|
1347
1493
|
let pkg = "";
|
|
1348
1494
|
const imports = /* @__PURE__ */ new Map();
|
|
1349
1495
|
const decls = [];
|
|
1496
|
+
const aliases = /* @__PURE__ */ new Map();
|
|
1497
|
+
const stops = [];
|
|
1350
1498
|
for (let i = 0; i < lines.length; i++) {
|
|
1351
1499
|
const line = lines[i];
|
|
1352
1500
|
const pm = PACKAGE.exec(line);
|
|
@@ -1367,10 +1515,58 @@ function extractKotlin(srcRoot, profile, project, ref) {
|
|
|
1367
1515
|
line: i,
|
|
1368
1516
|
kind: kindOf(dm.groups.mods ?? "", dm.groups.kw)
|
|
1369
1517
|
});
|
|
1518
|
+
continue;
|
|
1519
|
+
}
|
|
1520
|
+
const am = TYPEALIAS.exec(line);
|
|
1521
|
+
if (am) {
|
|
1522
|
+
aliases.set(am[1], am[2]);
|
|
1523
|
+
stops.push(i);
|
|
1524
|
+
continue;
|
|
1370
1525
|
}
|
|
1526
|
+
if (TOP_LEVEL.test(line)) stops.push(i);
|
|
1371
1527
|
}
|
|
1372
1528
|
rawPkgs.push(pkg);
|
|
1373
|
-
infos.push({
|
|
1529
|
+
infos.push({
|
|
1530
|
+
rel,
|
|
1531
|
+
pkg,
|
|
1532
|
+
imports,
|
|
1533
|
+
decls,
|
|
1534
|
+
lines,
|
|
1535
|
+
layer: layerOf(profile, `/${rel}`),
|
|
1536
|
+
aliases,
|
|
1537
|
+
stops
|
|
1538
|
+
});
|
|
1539
|
+
}
|
|
1540
|
+
const aliasByFq = /* @__PURE__ */ new Map();
|
|
1541
|
+
for (const fi of infos) {
|
|
1542
|
+
for (const [name, rhs] of fi.aliases) aliasByFq.set(`${fi.pkg}.${name}`, { rhs, from: fi });
|
|
1543
|
+
}
|
|
1544
|
+
for (const fi of infos) {
|
|
1545
|
+
const reach = /* @__PURE__ */ new Map();
|
|
1546
|
+
for (const [name, rhs] of fi.aliases) reach.set(name, { rhs, from: fi });
|
|
1547
|
+
for (const [simple, fq] of fi.imports) {
|
|
1548
|
+
const a = aliasByFq.get(fq);
|
|
1549
|
+
if (a) reach.set(simple, a);
|
|
1550
|
+
}
|
|
1551
|
+
for (const [fq, a] of aliasByFq) {
|
|
1552
|
+
const dot = fq.lastIndexOf(".");
|
|
1553
|
+
const name = fq.slice(dot + 1);
|
|
1554
|
+
if (fq.slice(0, dot) === fi.pkg && !reach.has(name)) reach.set(name, a);
|
|
1555
|
+
}
|
|
1556
|
+
if (!reach.size) continue;
|
|
1557
|
+
for (const { rhs, from } of reach.values()) {
|
|
1558
|
+
if (from === fi) continue;
|
|
1559
|
+
for (const [name] of rhs.matchAll(TYPENAME)) {
|
|
1560
|
+
const nm = name;
|
|
1561
|
+
if (!fi.imports.has(nm)) fi.imports.set(nm, from.imports.get(nm) ?? `${from.pkg}.${nm}`);
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1564
|
+
for (let pass = 0; pass < 2; pass++) {
|
|
1565
|
+
for (const [name, a] of reach) {
|
|
1566
|
+
const re = new RegExp(`\\b${name}\\b`, "g");
|
|
1567
|
+
fi.lines = fi.lines.map((l) => TYPEALIAS.test(l) ? l : l.replace(re, a.rhs));
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1374
1570
|
}
|
|
1375
1571
|
const base = profile.domain.base || inferBasePackage(rawPkgs);
|
|
1376
1572
|
const domainOf = (pkg) => {
|
|
@@ -1388,8 +1584,7 @@ function extractKotlin(srcRoot, profile, project, ref) {
|
|
|
1388
1584
|
const domain = domainOf(fi.pkg);
|
|
1389
1585
|
for (let di = 0; di < fi.decls.length; di++) {
|
|
1390
1586
|
const d = fi.decls[di];
|
|
1391
|
-
const
|
|
1392
|
-
const body = fi.lines.slice(d.line, end);
|
|
1587
|
+
const body = bodyOf(fi, di);
|
|
1393
1588
|
const struct = structOf(d.kind);
|
|
1394
1589
|
const sigs = collectSigs(body);
|
|
1395
1590
|
const api = [];
|
|
@@ -1398,13 +1593,18 @@ function extractKotlin(srcRoot, profile, project, ref) {
|
|
|
1398
1593
|
const braceAt = headerFull.indexOf("{");
|
|
1399
1594
|
const header2 = braceAt >= 0 ? headerFull.slice(0, braceAt) : headerFull;
|
|
1400
1595
|
const props = ctorParams(header2);
|
|
1596
|
+
const declared = /* @__PURE__ */ new Map();
|
|
1597
|
+
for (const p of ctorDeclared(header2)) declared.set(p.name, p.type);
|
|
1401
1598
|
if (braceAt >= 0) {
|
|
1402
1599
|
const rest = body.slice(header2.split("\n").length - 1);
|
|
1403
1600
|
const first = rest[0];
|
|
1404
1601
|
if (first !== void 0) rest[0] = first.slice(first.indexOf("{") + 1);
|
|
1405
1602
|
for (const ln of rest) {
|
|
1406
1603
|
const pm = PROP.exec(ln);
|
|
1407
|
-
if (pm)
|
|
1604
|
+
if (!pm) continue;
|
|
1605
|
+
const type = pm[2].trim().replace(/,$/, "");
|
|
1606
|
+
props.push(`${pm[1]}: ${type}`);
|
|
1607
|
+
declared.set(pm[1], type);
|
|
1408
1608
|
}
|
|
1409
1609
|
}
|
|
1410
1610
|
if (d.kind.includes("enum")) props.push(...enumEntries(body.join("\n")));
|
|
@@ -1423,7 +1623,8 @@ function extractKotlin(srcRoot, profile, project, ref) {
|
|
|
1423
1623
|
file: fi.rel,
|
|
1424
1624
|
line: d.line + 1,
|
|
1425
1625
|
struct,
|
|
1426
|
-
sigs
|
|
1626
|
+
sigs,
|
|
1627
|
+
declared
|
|
1427
1628
|
});
|
|
1428
1629
|
byPkg.set(fi.pkg, [...byPkg.get(fi.pkg) ?? [], id]);
|
|
1429
1630
|
}
|
|
@@ -1448,8 +1649,7 @@ function extractKotlin(srcRoot, profile, project, ref) {
|
|
|
1448
1649
|
for (let di = 0; di < fi.decls.length; di++) {
|
|
1449
1650
|
const d = fi.decls[di];
|
|
1450
1651
|
const id = `${fi.pkg}.${d.name}`;
|
|
1451
|
-
const
|
|
1452
|
-
const body = fi.lines.slice(d.line, end).join("\n");
|
|
1652
|
+
const body = bodyOf(fi, di).join("\n");
|
|
1453
1653
|
for (const sup of parseSupertypes(fi.lines, d.line)) {
|
|
1454
1654
|
const tgt = visible.get(sup);
|
|
1455
1655
|
if (tgt) supers.push([id, tgt]);
|
|
@@ -1493,8 +1693,7 @@ function extractKotlin(srcRoot, profile, project, ref) {
|
|
|
1493
1693
|
for (let di = 0; di < fi.decls.length; di++) {
|
|
1494
1694
|
const d = fi.decls[di];
|
|
1495
1695
|
const id = `${fi.pkg}.${d.name}`;
|
|
1496
|
-
const
|
|
1497
|
-
const body = fi.lines.slice(d.line, end).join("\n");
|
|
1696
|
+
const body = bodyOf(fi, di).join("\n");
|
|
1498
1697
|
const bind = /* @__PURE__ */ new Map();
|
|
1499
1698
|
for (const m of body.matchAll(FIELD)) {
|
|
1500
1699
|
const tgt = visible.get(m[2]);
|
|
@@ -1533,6 +1732,51 @@ function extractKotlin(srcRoot, profile, project, ref) {
|
|
|
1533
1732
|
}
|
|
1534
1733
|
}
|
|
1535
1734
|
const supSet = new Set(supers.map(([c, p]) => key(c, p)));
|
|
1735
|
+
const parentsOf = /* @__PURE__ */ new Map();
|
|
1736
|
+
for (const [c, p] of supers) parentsOf.set(c, [...parentsOf.get(c) ?? [], p]);
|
|
1737
|
+
const inherits = (child, ancestor) => {
|
|
1738
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1739
|
+
const walk2 = [child];
|
|
1740
|
+
while (walk2.length) {
|
|
1741
|
+
const cur = walk2.pop();
|
|
1742
|
+
if (cur === ancestor && cur !== child) return true;
|
|
1743
|
+
if (seen.has(cur)) continue;
|
|
1744
|
+
seen.add(cur);
|
|
1745
|
+
walk2.push(...parentsOf.get(cur) ?? []);
|
|
1746
|
+
}
|
|
1747
|
+
return false;
|
|
1748
|
+
};
|
|
1749
|
+
const aggregateOf = /* @__PURE__ */ new Map();
|
|
1750
|
+
const ambiguous = [];
|
|
1751
|
+
const identity = profile.identity;
|
|
1752
|
+
if (identity?.from === "property") {
|
|
1753
|
+
const want = identity.property ?? "id";
|
|
1754
|
+
const claims = /* @__PURE__ */ new Map();
|
|
1755
|
+
for (const [id, t] of types) {
|
|
1756
|
+
const written = t.declared.get(want);
|
|
1757
|
+
if (written === void 0) continue;
|
|
1758
|
+
const bare = written.replace(/[?\s]/g, "");
|
|
1759
|
+
const target = (visCache.get(t.file) ?? /* @__PURE__ */ new Map()).get(bare);
|
|
1760
|
+
if (target) claims.set(target, [...claims.get(target) ?? [], id]);
|
|
1761
|
+
}
|
|
1762
|
+
for (const [idType, holders] of claims) {
|
|
1763
|
+
const roots = holders.filter((h) => !holders.some((o) => o !== h && inherits(h, o)));
|
|
1764
|
+
if (roots.length === 1) aggregateOf.set(idType, roots[0]);
|
|
1765
|
+
else ambiguous.push(idType);
|
|
1766
|
+
}
|
|
1767
|
+
} else if (identity?.from === "suffix") {
|
|
1768
|
+
const suffix = identity.suffix ?? "Id";
|
|
1769
|
+
for (const [id, t] of types) {
|
|
1770
|
+
if (!t.name.endsWith(suffix) || t.name === suffix) continue;
|
|
1771
|
+
const stem = t.name.slice(0, -suffix.length);
|
|
1772
|
+
const pkg = id.slice(0, id.length - t.name.length - 1);
|
|
1773
|
+
const here = (byPkg.get(pkg) ?? []).filter((x) => types.get(x)?.name === stem);
|
|
1774
|
+
const anywhere = [...types.values()].filter((x) => x.name === stem).map((x) => x.id);
|
|
1775
|
+
const hit = here.length === 1 ? here : anywhere;
|
|
1776
|
+
if (hit.length === 1) aggregateOf.set(id, hit[0]);
|
|
1777
|
+
else if (hit.length > 1) ambiguous.push(id);
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1536
1780
|
const edges = [];
|
|
1537
1781
|
const push2 = (src, dst, rel, weight) => {
|
|
1538
1782
|
const s = types.get(src);
|
|
@@ -1549,20 +1793,47 @@ function extractKotlin(srcRoot, profile, project, ref) {
|
|
|
1549
1793
|
rel,
|
|
1550
1794
|
weight,
|
|
1551
1795
|
crossDomain: s.domain !== d.domain,
|
|
1796
|
+
// Not "this edge is an identifier reference" — those became REFERENCES and
|
|
1797
|
+
// point at the aggregate. This says the destination is a value type in the
|
|
1798
|
+
// domain model, which nearly everything touches, so the picture folds them
|
|
1799
|
+
// away by default. What lands here is value objects, enums, and identifiers
|
|
1800
|
+
// whose aggregate is outside the analysed source.
|
|
1552
1801
|
identifierOnly: d.component === "VO" && d.sublayer === "model",
|
|
1553
1802
|
viaSignature: viaSig.has(k),
|
|
1554
1803
|
contracts: rel === "DEPENDS_ON" ? contracts : [],
|
|
1555
|
-
|
|
1804
|
+
// Referencing another context's aggregate by id is how you avoid coupling to
|
|
1805
|
+
// it. Reporting that as a breach would penalise the design that got it right,
|
|
1806
|
+
// so REFERENCES carries no verdict — `crossDomain` still marks where it runs.
|
|
1807
|
+
violation: rel === "REFERENCES" ? "" : violationOf(profile, s, d, layerViol.has(k))
|
|
1556
1808
|
});
|
|
1557
1809
|
};
|
|
1558
1810
|
for (const [c, p] of supSet.size ? [...supSet].map((k) => k.split("\0")) : []) {
|
|
1559
1811
|
const parent = types.get(p);
|
|
1560
1812
|
push2(c, p, parent.struct === "Interface" ? "IMPLEMENTS" : "EXTENDS", 1);
|
|
1561
1813
|
}
|
|
1814
|
+
const refs = /* @__PURE__ */ new Map();
|
|
1562
1815
|
for (const [k, w] of dep) {
|
|
1563
1816
|
if (supSet.has(k)) continue;
|
|
1564
1817
|
const [s, d] = k.split("\0");
|
|
1565
|
-
|
|
1818
|
+
const g = aggregateOf.get(d);
|
|
1819
|
+
if (g === void 0) {
|
|
1820
|
+
push2(s, d, "DEPENDS_ON", w);
|
|
1821
|
+
continue;
|
|
1822
|
+
}
|
|
1823
|
+
if (g === s || inherits(s, g)) continue;
|
|
1824
|
+
if (dep.has(key(s, g))) continue;
|
|
1825
|
+
const rk = key(s, g);
|
|
1826
|
+
refs.set(rk, (refs.get(rk) ?? 0) + w);
|
|
1827
|
+
}
|
|
1828
|
+
for (const [k, w] of refs) {
|
|
1829
|
+
const [s, d] = k.split("\0");
|
|
1830
|
+
push2(s, d, "REFERENCES", w);
|
|
1831
|
+
}
|
|
1832
|
+
if (ambiguous.length) {
|
|
1833
|
+
process.stderr.write(
|
|
1834
|
+
`warning: cannot tell what these identifiers identify \u2014 ${ambiguous.map((x) => x.split(".").pop()).sort().join(", ")}
|
|
1835
|
+
`
|
|
1836
|
+
);
|
|
1566
1837
|
}
|
|
1567
1838
|
const nodes = [...types.values()].map(({ struct: _s, sigs: _g, ...n }) => n);
|
|
1568
1839
|
nodes.sort((a, b) => a.id.localeCompare(b.id));
|
|
@@ -1795,6 +2066,10 @@ var GraphSource = class {
|
|
|
1795
2066
|
this.graph();
|
|
1796
2067
|
return this.last?.delta;
|
|
1797
2068
|
}
|
|
2069
|
+
/**
|
|
2070
|
+
* The graph as it stands at the base ref. Extracted once and cached — the ref is
|
|
2071
|
+
* immutable, so a base-state render costs nothing a delta has not already paid.
|
|
2072
|
+
*/
|
|
1798
2073
|
base() {
|
|
1799
2074
|
if (this.baseGraph) return this.baseGraph;
|
|
1800
2075
|
const { repo, srcRel, profile, project, base } = this.cfg;
|
|
@@ -1900,7 +2175,7 @@ var shell = () => `<!doctype html>
|
|
|
1900
2175
|
Off = keep the fixed coordinates above.</div></div>
|
|
1901
2176
|
|
|
1902
2177
|
<h2>Edges</h2>
|
|
1903
|
-
<label><input type=checkbox id="showId">Show
|
|
2178
|
+
<label><input type=checkbox id="showId">Show value-type edges</label>
|
|
1904
2179
|
<label><input type=checkbox id="crossOnly">Cross-domain edges only</label>
|
|
1905
2180
|
<div class="sub" style="margin:6px 0 0"><b>Identifier edges</b><div class="d">references like
|
|
1906
2181
|
FamilyId\xB7UserId \u2014 a shared coordinate system, not coupling. Hidden by default.</div></div>
|
|
@@ -1908,6 +2183,8 @@ var shell = () => `<!doctype html>
|
|
|
1908
2183
|
<h2>Edge types</h2>
|
|
1909
2184
|
<label><input type=checkbox class=rf value="DEPENDS_ON" checked>
|
|
1910
2185
|
<i></i>DEPENDS_ON <span class="mut">straight \xB7 open V</span><span class="n" id="cDEPENDS_ON"></span></label>
|
|
2186
|
+
<label><input type=checkbox class=rf value="REFERENCES" checked>
|
|
2187
|
+
<i class="d"></i>REFERENCES <span class="mut">by id \xB7 fine dots</span><span class="n" id="cREFERENCES"></span></label>
|
|
1911
2188
|
<label><input type=checkbox class=rf value="IMPLEMENTS" checked>
|
|
1912
2189
|
<i class="d"></i>IMPLEMENTS <span class="mut">curved \xB7 long dash</span><span class="n" id="cIMPLEMENTS"></span></label>
|
|
1913
2190
|
<label><input type=checkbox class=rf value="EXTENDS" checked>
|
|
@@ -2006,11 +2283,27 @@ check only
|
|
|
2006
2283
|
has violations without fixing them all first.
|
|
2007
2284
|
|
|
2008
2285
|
render only
|
|
2009
|
-
--view <v> delta | impact | core | all | domain:<name>
|
|
2286
|
+
--view <v> delta | impact | core | all | violations | domain:<name>
|
|
2287
|
+
[delta]
|
|
2288
|
+
violations = only the breaches and the types they run
|
|
2289
|
+
through. A state view: it draws what is wrong now, not
|
|
2290
|
+
what this branch changed.
|
|
2291
|
+
--at <s> head | base [head]
|
|
2292
|
+
base draws the same types in their pre-branch state, for
|
|
2293
|
+
the "before" half of a before/after pair. Requires --base.
|
|
2294
|
+
Delta styling is dropped \u2014 nothing is added or modified in
|
|
2295
|
+
a picture of the past \u2014 and violations stay in red.
|
|
2010
2296
|
--layout <l> organic | grid | hex
|
|
2011
|
-
[organic for delta\xB7domain, hex for core\xB7all]
|
|
2297
|
+
[organic for delta\xB7domain\xB7violations, hex for core\xB7all]
|
|
2012
2298
|
--image <file> output path; .svg, or .png to rasterize [graph.svg]
|
|
2013
|
-
--identifiers include
|
|
2299
|
+
--identifiers include references to domain value types \u2014 value objects,
|
|
2300
|
+
enums, and identifiers whose aggregate is out of scope.
|
|
2301
|
+
A resolved identifier is drawn as REFERENCES at the
|
|
2302
|
+
aggregate instead and is not folded away. Flag name kept
|
|
2303
|
+
for compatibility.
|
|
2304
|
+
|
|
2305
|
+
Nothing to draw \u2014 no violations, or a branch that only adds types and so has
|
|
2306
|
+
no before state \u2014 is reported on stdout and exits 0.
|
|
2014
2307
|
`;
|
|
2015
2308
|
function main() {
|
|
2016
2309
|
const { values: v, positionals } = parseArgs({
|
|
@@ -2028,6 +2321,7 @@ function main() {
|
|
|
2028
2321
|
mcp: { type: "boolean", default: false },
|
|
2029
2322
|
scope: { type: "string", default: "all" },
|
|
2030
2323
|
view: { type: "string", default: "delta" },
|
|
2324
|
+
at: { type: "string", default: "head" },
|
|
2031
2325
|
layout: { type: "string" },
|
|
2032
2326
|
// no default — chosen to suit the view
|
|
2033
2327
|
image: { type: "string" },
|
|
@@ -2098,26 +2392,58 @@ function main() {
|
|
|
2098
2392
|
}
|
|
2099
2393
|
if (cmd === "render") {
|
|
2100
2394
|
const out = v.image ?? "graph.svg";
|
|
2395
|
+
if (v.at !== "head" && v.at !== "base") {
|
|
2396
|
+
process.stderr.write(`--at takes head or base, not '${v.at}'
|
|
2397
|
+
`);
|
|
2398
|
+
return 1;
|
|
2399
|
+
}
|
|
2400
|
+
const atBase = v.at === "base";
|
|
2401
|
+
if (atBase && !v.base) {
|
|
2402
|
+
process.stderr.write("--at base needs --base <ref> to know which state to draw\n");
|
|
2403
|
+
return 1;
|
|
2404
|
+
}
|
|
2405
|
+
const changed = d ? /* @__PURE__ */ new Set([...d.addedNodes, ...d.modifiedNodes, ...d.removedNodes]) : void 0;
|
|
2406
|
+
const target = atBase ? source.base() : graph;
|
|
2101
2407
|
let sel;
|
|
2102
2408
|
try {
|
|
2103
|
-
sel = select(
|
|
2409
|
+
sel = select(target, v.view, v.identifiers, atBase ? changed : void 0);
|
|
2104
2410
|
} catch (e) {
|
|
2411
|
+
if (e instanceof NothingToDraw) {
|
|
2412
|
+
process.stdout.write(`${project} @ ${target.ref}
|
|
2413
|
+
${e.message}
|
|
2414
|
+
`);
|
|
2415
|
+
return 0;
|
|
2416
|
+
}
|
|
2105
2417
|
process.stderr.write(`${e.message}
|
|
2106
2418
|
`);
|
|
2107
2419
|
return 1;
|
|
2108
2420
|
}
|
|
2421
|
+
let frame;
|
|
2422
|
+
if (v.base && changed) {
|
|
2423
|
+
const half = (gr, ch) => {
|
|
2424
|
+
try {
|
|
2425
|
+
return select(gr, v.view, v.identifiers, ch).graph;
|
|
2426
|
+
} catch {
|
|
2427
|
+
return void 0;
|
|
2428
|
+
}
|
|
2429
|
+
};
|
|
2430
|
+
const head = half(graph);
|
|
2431
|
+
const base = half(source.base(), changed);
|
|
2432
|
+
if (head && base) frame = union(head, base);
|
|
2433
|
+
}
|
|
2109
2434
|
const layout = v.layout === "hex" || v.layout === "grid" || v.layout === "organic" ? v.layout : v.view === "core" || v.view === "all" ? "hex" : "organic";
|
|
2110
2435
|
const svg = renderSvg(sel.graph, {
|
|
2111
2436
|
layout,
|
|
2112
2437
|
viewLabel: sel.label,
|
|
2113
|
-
showIdentifiers: v.identifiers
|
|
2438
|
+
showIdentifiers: v.identifiers,
|
|
2439
|
+
...frame ? { frame } : {}
|
|
2114
2440
|
});
|
|
2115
2441
|
const dir = dirname2(resolve(out));
|
|
2116
2442
|
mkdirSync(dir, { recursive: true });
|
|
2117
2443
|
const svgPath = out.endsWith(".png") ? `${out.slice(0, -4)}.svg` : out;
|
|
2118
2444
|
writeFileSync(svgPath, svg);
|
|
2119
2445
|
process.stdout.write(
|
|
2120
|
-
`${project} @ ${
|
|
2446
|
+
`${project} @ ${target.ref}
|
|
2121
2447
|
view ${sel.label}
|
|
2122
2448
|
drew ${sel.graph.nodes.length} types \xB7 ${sel.graph.edges.length} relations \xB7 ${sel.graph.edges.filter((e) => e.violation).length} violations
|
|
2123
2449
|
wrote ${svgPath} (${Math.round(svg.length / 1024)} KB)
|
|
@@ -2127,8 +2453,7 @@ function main() {
|
|
|
2127
2453
|
const px = toPng(svg, out);
|
|
2128
2454
|
process.stdout.write(
|
|
2129
2455
|
px ? ` wrote ${out} (${px})
|
|
2130
|
-
` :
|
|
2131
|
-
`
|
|
2456
|
+
` : " note PNG skipped \u2014 install @resvg/resvg-js for rasterizing\n"
|
|
2132
2457
|
);
|
|
2133
2458
|
}
|
|
2134
2459
|
return 0;
|
|
@@ -2205,6 +2530,19 @@ wrote ${join6(v.out, "graph.json")} \xB7 graph.tsv
|
|
|
2205
2530
|
}
|
|
2206
2531
|
return cmd === "check" && gated.length ? 1 : 0;
|
|
2207
2532
|
}
|
|
2533
|
+
function union(a, b) {
|
|
2534
|
+
const nodes = new Map(a.nodes.map((n) => [n.id, n]));
|
|
2535
|
+
for (const n of b.nodes) if (!nodes.has(n.id)) nodes.set(n.id, n);
|
|
2536
|
+
const edges = new Map(a.edges.map((e) => [edgeKey(e), e]));
|
|
2537
|
+
for (const e of b.edges) if (!edges.has(edgeKey(e))) edges.set(edgeKey(e), e);
|
|
2538
|
+
return {
|
|
2539
|
+
...a,
|
|
2540
|
+
nodes: [...nodes.values()].sort((x, y) => x.id.localeCompare(y.id)),
|
|
2541
|
+
edges: [...edges.values()].sort(
|
|
2542
|
+
(x, y) => x.src.localeCompare(y.src) || x.dst.localeCompare(y.dst) || x.rel.localeCompare(y.rel)
|
|
2543
|
+
)
|
|
2544
|
+
};
|
|
2545
|
+
}
|
|
2208
2546
|
function toPng(svg, out) {
|
|
2209
2547
|
try {
|
|
2210
2548
|
const req = createRequire(import.meta.url);
|
package/dist/client.js
CHANGED
|
@@ -318,7 +318,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
|
|
|
318
318
|
`).concat(r.picking?`if(outColor.a == 0.0) discard;
|
|
319
319
|
else outColor = vIndex;`:"",`
|
|
320
320
|
}
|
|
321
|
-
`),s=Jm(a,n,o);s.aPosition=a.getAttribLocation(s,"aPosition"),s.aIndex=a.getAttribLocation(s,"aIndex"),s.aVertType=a.getAttribLocation(s,"aVertType"),s.aTransform=a.getAttribLocation(s,"aTransform"),s.aAtlasId=a.getAttribLocation(s,"aAtlasId"),s.aTex=a.getAttribLocation(s,"aTex"),s.aPointAPointB=a.getAttribLocation(s,"aPointAPointB"),s.aPointCPointD=a.getAttribLocation(s,"aPointCPointD"),s.aLineWidth=a.getAttribLocation(s,"aLineWidth"),s.aColor=a.getAttribLocation(s,"aColor"),s.aCornerRadius=a.getAttribLocation(s,"aCornerRadius"),s.aBorderColor=a.getAttribLocation(s,"aBorderColor"),s.uPanZoomMatrix=a.getUniformLocation(s,"uPanZoomMatrix"),s.uAtlasSize=a.getUniformLocation(s,"uAtlasSize"),s.uBGColor=a.getUniformLocation(s,"uBGColor"),s.uZoom=a.getUniformLocation(s,"uZoom"),s.uTextures=[];for(var u=0;u<this.batchManager.getMaxAtlasesPerBatch();u++)s.uTextures.push(a.getUniformLocation(s,"uTexture".concat(u)));return s}},{key:"_createVAO",value:function(){var r=[0,0,1,0,1,1,0,0,1,1,0,1];this.vertexCount=r.length/2;var a=this.maxInstances,n=this.gl,i=this.program,o=n.createVertexArray();return n.bindVertexArray(o),s0(n,"vec2",i.aPosition,r),this.transformBuffer=l0(n,a,i.aTransform),this.indexBuffer=Zt(n,a,"vec4",i.aIndex),this.vertTypeBuffer=Zt(n,a,"int",i.aVertType),this.atlasIdBuffer=Zt(n,a,"int",i.aAtlasId),this.texBuffer=Zt(n,a,"vec4",i.aTex),this.pointAPointBBuffer=Zt(n,a,"vec4",i.aPointAPointB),this.pointCPointDBuffer=Zt(n,a,"vec4",i.aPointCPointD),this.lineWidthBuffer=Zt(n,a,"vec2",i.aLineWidth),this.colorBuffer=Zt(n,a,"vec4",i.aColor),this.cornerRadiusBuffer=Zt(n,a,"vec4",i.aCornerRadius),this.borderColorBuffer=Zt(n,a,"vec4",i.aBorderColor),n.bindVertexArray(null),o}},{key:"buffers",get:function(){var r=this;return this._buffers||(this._buffers=Object.keys(this).filter(function(a){return yr(a,"Buffer")}).map(function(a){return r[a]})),this._buffers}},{key:"startFrame",value:function(r){var a=arguments.length>1&&arguments[1]!==void 0?arguments[1]:Xa.SCREEN;this.panZoomMatrix=r,this.renderTarget=a,this.batchDebugInfo=[],this.wrappedCount=0,this.simpleCount=0,this.startBatch()}},{key:"startBatch",value:function(){this.instanceCount=0,this.batchManager.startBatch()}},{key:"endFrame",value:function(){this.endBatch()}},{key:"_isVisible",value:function(r,a){return r.visible()?a&&a.isVisible?a.isVisible(r):!0:!1}},{key:"drawTexture",value:function(r,a,n){var i=this.atlasManager,o=this.batchManager,s=i.getRenderTypeOpts(n);if(this._isVisible(r,s)&&!(r.isEdge()&&!this._isValidEdge(r))){if(this.renderTarget.picking&&s.getTexPickingMode){var u=s.getTexPickingMode(r);if(u===oi.IGNORE)return;if(u==oi.USE_BB){this.drawPickingRectangle(r,a,n);return}}var l=i.getAtlasInfo(r,n),f=zt(l),v;try{for(f.s();!(v=f.n()).done;){var c=v.value,h=c.atlas,d=c.tex1,g=c.tex2;o.canAddToCurrentBatch(h)||this.endBatch();for(var m=o.getAtlasIndexForBatch(h),p=0,y=[[d,!0],[g,!1]];p<y.length;p++){var b=dt(y[p],2),E=b[0],C=b[1];if(E.w!=0){var A=this.instanceCount;this.vertTypeBuffer.getView(A)[0]=is;var D=this.indexBuffer.getView(A);sa(a,D);var N=this.atlasIdBuffer.getView(A);N[0]=m;var O=this.texBuffer.getView(A);O[0]=E.x,O[1]=E.y,O[2]=E.w,O[3]=E.h;var R=this.transformBuffer.getMatrixView(A);this.setTransformMatrix(r,R,s,c,C),this.instanceCount++,C||this.wrappedCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}}}}catch(P){f.e(P)}finally{f.f()}}}},{key:"setTransformMatrix",value:function(r,a,n,i){var o=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,s=0;if(n.shapeProps&&n.shapeProps.padding&&(s=r.pstyle(n.shapeProps.padding).pfValue),i){var u=i.bb,l=i.tex1,f=i.tex2,v=l.w/(l.w+f.w);o||(v=1-v);var c=this._getAdjustedBB(u,s,o,v);this._applyTransformMatrix(a,c,n,r)}else{var h=n.getBoundingBox(r),d=this._getAdjustedBB(h,s,!0,1);this._applyTransformMatrix(a,d,n,r)}}},{key:"_applyTransformMatrix",value:function(r,a,n,i){var o,s;Uf(r);var u=n.getRotation?n.getRotation(i):0;if(u!==0){var l=n.getRotationPoint(i),f=l.x,v=l.y;$n(r,r,[f,v]),Hf(r,r,u);var c=n.getRotationOffset(i);o=c.x+(a.xOffset||0),s=c.y+(a.yOffset||0)}else o=a.x1,s=a.y1;$n(r,r,[o,s]),Ds(r,r,[a.w,a.h])}},{key:"_getAdjustedBB",value:function(r,a,n,i){var o=r.x1,s=r.y1,u=r.w,l=r.h,f=r.yOffset;a&&(o-=a,s-=a,u+=2*a,l+=2*a);var v=0,c=u*i;return n&&i<1?u=c:!n&&i<1&&(v=u-c,o+=v,u=c),{x1:o,y1:s,w:u,h:l,xOffset:v,yOffset:f}}},{key:"drawPickingRectangle",value:function(r,a,n){var i=this.atlasManager.getRenderTypeOpts(n),o=this.instanceCount;this.vertTypeBuffer.getView(o)[0]=la;var s=this.indexBuffer.getView(o);sa(a,s);var u=this.colorBuffer.getView(o);zr([0,0,0],1,u);var l=this.transformBuffer.getMatrixView(o);this.setTransformMatrix(r,l,i),this.simpleCount++,this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}},{key:"drawNode",value:function(r,a,n){var i=this.simpleShapeOptions.get(n);if(this._isVisible(r,i)){var o=i.shapeProps,s=this._getVertTypeForShape(r,o.shape);if(s===void 0||i.isSimple&&!i.isSimple(r,this.renderTarget)){this.drawTexture(r,a,n);return}var u=this.instanceCount;if(this.vertTypeBuffer.getView(u)[0]=s,s===kn||s===Va){var l=i.getBoundingBox(r),f=this._getCornerRadius(r,o.radius,l),v=this.cornerRadiusBuffer.getView(u);v[0]=f,v[1]=f,v[2]=f,v[3]=f,s===Va&&(v[0]=0,v[2]=0)}var c=this.indexBuffer.getView(u);sa(a,c);var h=this.renderTarget.picking?1:n==="node-body"?r.effectiveOpacity():1,d=this.renderTarget.picking?1:r.pstyle(o.opacity).value*h,g=r.pstyle(o.color).value,m=this.colorBuffer.getView(u);zr(g,d,m);var p=this.lineWidthBuffer.getView(u);if(p[0]=0,p[1]=0,o.border){var y=r.pstyle("border-width").value;if(y>0){var b=r.pstyle("border-color").value,E=h*r.pstyle("border-opacity").value,C=this.borderColorBuffer.getView(u);zr(b,E,C);var A=r.pstyle("border-position").value;if(A==="inside")p[0]=0,p[1]=-y;else if(A==="outside")p[0]=y,p[1]=0;else{var D=y/2;p[0]=D,p[1]=-D}}}var N=this.transformBuffer.getMatrixView(u);this.setTransformMatrix(r,N,i),this.simpleCount++,this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}}},{key:"_getVertTypeForShape",value:function(r,a){var n=r.pstyle(a).value;switch(n){case"rectangle":return la;case"ellipse":return Ga;case"roundrectangle":case"round-rectangle":return kn;case"bottom-round-rectangle":return Va;default:return}}},{key:"_getCornerRadius",value:function(r,a,n){var i=n.w,o=n.h;if(r.pstyle(a).value==="auto")return Cr(i,o);var s=r.pstyle(a).pfValue,u=i/2,l=o/2;return Math.min(s,l,u)}},{key:"drawEdgeArrow",value:function(r,a,n){if(r.visible()){var i=r._private.rscratch,o,s,u;if(n==="source"?(o=i.arrowStartX,s=i.arrowStartY,u=i.srcArrowAngle):(o=i.arrowEndX,s=i.arrowEndY,u=i.tgtArrowAngle),!(isNaN(o)||o==null||isNaN(s)||s==null||isNaN(u)||u==null)){var l=r.pstyle(n+"-arrow-shape").value;if(l!=="none"){var f=r.pstyle(n+"-arrow-color").value,v=r.pstyle("opacity").value,c=r.pstyle("line-opacity").value,h=v*c,d=r.pstyle("width").pfValue,g=r.pstyle("arrow-scale").value,m=this.r.getArrowWidth(d,g),p=this.instanceCount,y=this.transformBuffer.getMatrixView(p);Uf(y),$n(y,y,[o,s]),Ds(y,y,[m,m]),Hf(y,y,u),this.vertTypeBuffer.getView(p)[0]=os;var b=this.indexBuffer.getView(p);sa(a,b);var E=this.colorBuffer.getView(p);zr(f,h,E),this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}}}}},{key:"drawEdgeLine",value:function(r,a){if(r.visible()){var n=this._getEdgePoints(r);if(n){var i=r.pstyle("opacity").value,o=r.pstyle("line-opacity").value,s=r.pstyle("width").pfValue,u=r.pstyle("line-color").value,l=i*o;if(n.length/2+this.instanceCount>this.maxInstances&&this.endBatch(),n.length==4){var f=this.instanceCount;this.vertTypeBuffer.getView(f)[0]=qf;var v=this.indexBuffer.getView(f);sa(a,v);var c=this.colorBuffer.getView(f);zr(u,l,c);var h=this.lineWidthBuffer.getView(f);h[0]=s;var d=this.pointAPointBBuffer.getView(f);d[0]=n[0],d[1]=n[1],d[2]=n[2],d[3]=n[3],this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}else for(var g=0;g<n.length-2;g+=2){var m=this.instanceCount;this.vertTypeBuffer.getView(m)[0]=Yf;var p=this.indexBuffer.getView(m);sa(a,p);var y=this.colorBuffer.getView(m);zr(u,l,y);var b=this.lineWidthBuffer.getView(m);b[0]=s;var E=n[g-2],C=n[g-1],A=n[g],D=n[g+1],N=n[g+2],O=n[g+3],R=n[g+4],P=n[g+5];g==0&&(E=2*A-N+.001,C=2*D-O+.001),g==n.length-4&&(R=2*N-A+.001,P=2*O-D+.001);var w=this.pointAPointBBuffer.getView(m);w[0]=E,w[1]=C,w[2]=A,w[3]=D;var x=this.pointCPointDBuffer.getView(m);x[0]=N,x[1]=O,x[2]=R,x[3]=P,this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}}}}},{key:"_isValidEdge",value:function(r){var a=r._private.rscratch;return!(a.badLine||a.allpts==null||isNaN(a.allpts[0]))}},{key:"_getEdgePoints",value:function(r){var a=r._private.rscratch;if(this._isValidEdge(r)){var n=a.allpts;if(n.length==4)return n;var i=this._getNumSegments(r);return this._getCurveSegmentPoints(n,i)}}},{key:"_getNumSegments",value:function(r){var a=15;return Math.min(Math.max(a,5),this.maxInstances)}},{key:"_getCurveSegmentPoints",value:function(r,a){if(r.length==4)return r;for(var n=Array((a+1)*2),i=0;i<=a;i++)if(i==0)n[0]=r[0],n[1]=r[1];else if(i==a)n[i*2]=r[r.length-2],n[i*2+1]=r[r.length-1];else{var o=i/a;this._setCurvePoint(r,o,n,i*2)}return n}},{key:"_setCurvePoint",value:function(r,a,n,i){if(r.length<=2)n[i]=r[0],n[i+1]=r[1];else{for(var o=Array(r.length-2),s=0;s<o.length;s+=2){var u=(1-a)*r[s]+a*r[s+2],l=(1-a)*r[s+1]+a*r[s+3];o[s]=u,o[s+1]=l}return this._setCurvePoint(o,a,n,i)}}},{key:"endBatch",value:function(){var r=this.gl,a=this.vao,n=this.vertexCount,i=this.instanceCount;if(i!==0){var o=this.renderTarget.picking?this.pickingProgram:this.program;r.useProgram(o),r.bindVertexArray(a);var s=zt(this.buffers),u;try{for(s.s();!(u=s.n()).done;){var l=u.value;l.bufferSubData(i)}}catch(d){s.e(d)}finally{s.f()}for(var f=this.batchManager.getAtlases(),v=0;v<f.length;v++)f[v].bufferIfNeeded(r);for(var c=0;c<f.length;c++)r.activeTexture(r.TEXTURE0+c),r.bindTexture(r.TEXTURE_2D,f[c].texture),r.uniform1i(o.uTextures[c],c);r.uniform1f(o.uZoom,e0(this.r)),r.uniformMatrix3fv(o.uPanZoomMatrix,!1,this.panZoomMatrix),r.uniform1i(o.uAtlasSize,this.batchManager.getAtlasSize());var h=zr(this.bgColor,1);r.uniform4fv(o.uBGColor,h),r.drawArraysInstanced(r.TRIANGLES,0,n,i),r.bindVertexArray(null),r.bindTexture(r.TEXTURE_2D,null),this.debug&&this.batchDebugInfo.push({count:i,atlasCount:f.length}),this.startBatch()}}},{key:"getDebugInfo",value:function(){var r=this.atlasManager.getDebugInfo(),a=r.reduce(function(o,s){return o+s.atlasCount},0),n=this.batchDebugInfo,i=n.reduce(function(o,s){return o+s.count},0);return{atlasInfo:r,totalAtlases:a,wrappedCount:this.wrappedCount,simpleCount:this.simpleCount,batchCount:n.length,batchInfo:n,totalInstances:i}}}])})(),Mc={};Mc.initWebgl=function(t,e){var r=this,a=r.data.contexts[r.WEBGL];t.bgColor=x0(r),t.webglTexSize=Math.min(t.webglTexSize,a.getParameter(a.MAX_TEXTURE_SIZE)),t.webglTexRows=Math.min(t.webglTexRows,54),t.webglTexRowsNodes=Math.min(t.webglTexRowsNodes,54),t.webglBatchSize=Math.min(t.webglBatchSize,16384),t.webglTexPerBatch=Math.min(t.webglTexPerBatch,a.getParameter(a.MAX_TEXTURE_IMAGE_UNITS)),r.webglDebug=t.webglDebug,r.webglDebugShowAtlases=t.webglDebugShowAtlases,r.pickingFrameBuffer=u0(a),r.pickingFrameBuffer.needsDraw=!0,r.drawing=new E0(r,a,t);var n=function(v){return function(c){return r.getTextAngle(c,v)}},i=function(v){return function(c){var h=c.pstyle(v);return h&&h.value}},o=function(v){return function(c){return c.pstyle("".concat(v,"-opacity")).value>0}},s=function(v){var c=v.pstyle("text-events").strValue==="yes";return c?oi.USE_BB:oi.IGNORE},u=function(v){var c=v.position(),h=c.x,d=c.y,g=v.outerWidth(),m=v.outerHeight();return{w:g,h:m,x1:h-g/2,y1:d-m/2}};r.drawing.addAtlasCollection("node",{texRows:t.webglTexRowsNodes}),r.drawing.addAtlasCollection("label",{texRows:t.webglTexRows}),r.drawing.addTextureAtlasRenderType("node-body",{collection:"node",getKey:e.getStyleKey,getBoundingBox:e.getElementBox,drawElement:e.drawElement}),r.drawing.addSimpleShapeRenderType("node-body",{getBoundingBox:u,isSimple:r0,shapeProps:{shape:"shape",color:"background-color",opacity:"background-opacity",radius:"corner-radius",border:!0}}),r.drawing.addSimpleShapeRenderType("node-overlay",{getBoundingBox:u,isVisible:o("overlay"),shapeProps:{shape:"overlay-shape",color:"overlay-color",opacity:"overlay-opacity",padding:"overlay-padding",radius:"overlay-corner-radius"}}),r.drawing.addSimpleShapeRenderType("node-underlay",{getBoundingBox:u,isVisible:o("underlay"),shapeProps:{shape:"underlay-shape",color:"underlay-color",opacity:"underlay-opacity",padding:"underlay-padding",radius:"underlay-corner-radius"}}),r.drawing.addTextureAtlasRenderType("label",{collection:"label",getTexPickingMode:s,getKey:ss(e.getLabelKey,null),getBoundingBox:ls(e.getLabelBox,null),drawClipped:!0,drawElement:e.drawLabel,getRotation:n(null),getRotationPoint:e.getLabelRotationPoint,getRotationOffset:e.getLabelRotationOffset,isVisible:i("label")}),r.drawing.addTextureAtlasRenderType("edge-source-label",{collection:"label",getTexPickingMode:s,getKey:ss(e.getSourceLabelKey,"source"),getBoundingBox:ls(e.getSourceLabelBox,"source"),drawClipped:!0,drawElement:e.drawSourceLabel,getRotation:n("source"),getRotationPoint:e.getSourceLabelRotationPoint,getRotationOffset:e.getSourceLabelRotationOffset,isVisible:i("source-label")}),r.drawing.addTextureAtlasRenderType("edge-target-label",{collection:"label",getTexPickingMode:s,getKey:ss(e.getTargetLabelKey,"target"),getBoundingBox:ls(e.getTargetLabelBox,"target"),drawClipped:!0,drawElement:e.drawTargetLabel,getRotation:n("target"),getRotationPoint:e.getTargetLabelRotationPoint,getRotationOffset:e.getTargetLabelRotationOffset,isVisible:i("target-label")});var l=un(function(){console.log("garbage collect flag set"),r.data.gc=!0},1e4);r.onUpdateEleCalcs(function(f,v){var c=!1;v&&v.length>0&&(c|=r.drawing.invalidate(v)),c&&l()}),T0(r)};function x0(t){var e=t.cy.container(),r=e&&e.style&&e.style.backgroundColor||"white";return tv(r)}function Lc(t,e){var r=t._private.rscratch;return It(r,"labelWrapCachedLines",e)||[]}var ss=function(e,r){return function(a){var n=e(a),i=Lc(a,r);return i.length>1?i.map(function(o,s){return"".concat(n,"_").concat(s)}):n}},ls=function(e,r){return function(a,n){var i=e(a);if(typeof n=="string"){var o=n.indexOf("_");if(o>0){var s=Number(n.substring(o+1)),u=Lc(a,r),l=i.h/u.length,f=l*s,v=i.y1+f;return{x1:i.x1,w:i.w,y1:v,h:l,yOffset:f}}}return i}};function T0(t){{var e=t.render;t.render=function(i){i=i||{};var o=t.cy;t.webgl&&(o.zoom()>Ec?(C0(t),e.call(t,i)):(S0(t),Rc(t,i,Xa.SCREEN)))}}{var r=t.matchCanvasSize;t.matchCanvasSize=function(i){r.call(t,i),t.pickingFrameBuffer.setFramebufferAttachmentSizes(t.canvasWidth,t.canvasHeight),t.pickingFrameBuffer.needsDraw=!0}}t.findNearestElements=function(i,o,s,u){return R0(t,i,o)};{var a=t.invalidateCachedZSortedEles;t.invalidateCachedZSortedEles=function(){a.call(t),t.pickingFrameBuffer.needsDraw=!0}}{var n=t.notify;t.notify=function(i,o){n.call(t,i,o),i==="viewport"||i==="bounds"?t.pickingFrameBuffer.needsDraw=!0:i==="background"&&t.drawing.invalidate(o,{type:"node-body"})}}}function C0(t){var e=t.data.contexts[t.WEBGL];e.clear(e.COLOR_BUFFER_BIT|e.DEPTH_BUFFER_BIT)}function S0(t){var e=function(a){a.save(),a.setTransform(1,0,0,1,0,0),a.clearRect(0,0,t.canvasWidth,t.canvasHeight),a.restore()};e(t.data.contexts[t.NODE]),e(t.data.contexts[t.DRAG])}function D0(t){var e=t.canvasWidth,r=t.canvasHeight,a=el(t),n=a.pan,i=a.zoom,o=ns();$n(o,o,[n.x,n.y]),Ds(o,o,[i,i]);var s=ns();v0(s,e,r);var u=ns();return f0(u,s,o),u}function Nc(t,e){var r=t.canvasWidth,a=t.canvasHeight,n=el(t),i=n.pan,o=n.zoom;e.setTransform(1,0,0,1,0,0),e.clearRect(0,0,r,a),e.translate(i.x,i.y),e.scale(o,o)}function A0(t,e){t.drawSelectionRectangle(e,function(r){return Nc(t,r)})}function M0(t){var e=t.data.contexts[t.NODE];e.save(),Nc(t,e),e.strokeStyle="rgba(0, 0, 0, 0.3)",e.beginPath(),e.moveTo(-1e3,0),e.lineTo(1e3,0),e.stroke(),e.beginPath(),e.moveTo(0,-1e3),e.lineTo(0,1e3),e.stroke(),e.restore()}function L0(t){var e=function(n,i,o){for(var s=n.atlasManager.getAtlasCollection(i),u=t.data.contexts[t.NODE],l=s.atlases,f=0;f<l.length;f++){var v=l[f],c=v.canvas;if(c){var h=c.width,d=c.height,g=h*f,m=c.height*o,p=.4;u.save(),u.scale(p,p),u.drawImage(c,g,m),u.strokeStyle="black",u.rect(g,m,h,d),u.stroke(),u.restore()}}},r=0;e(t.drawing,"node",r++),e(t.drawing,"label",r++)}function N0(t,e,r,a,n){var i,o,s,u,l=el(t),f=l.pan,v=l.zoom;{var c=t0(t,f,v,e,r),h=dt(c,2),d=h[0],g=h[1],m=6;i=d-m/2,o=g-m/2,s=m,u=m}if(s===0||u===0)return[];var p=t.data.contexts[t.WEBGL];p.bindFramebuffer(p.FRAMEBUFFER,t.pickingFrameBuffer),t.pickingFrameBuffer.needsDraw&&(p.viewport(0,0,p.canvas.width,p.canvas.height),Rc(t,null,Xa.PICKING),t.pickingFrameBuffer.needsDraw=!1);var y=s*u,b=new Uint8Array(y*4);p.readPixels(i,o,s,u,p.RGBA,p.UNSIGNED_BYTE,b),p.bindFramebuffer(p.FRAMEBUFFER,null);for(var E=new Set,C=0;C<y;C++){var A=b.slice(C*4,C*4+4),D=n0(A)-1;D>=0&&E.add(D)}return E}function R0(t,e,r){var a=N0(t,e,r),n=t.getCachedZSortedEles(),i,o,s=zt(a),u;try{for(s.s();!(u=s.n()).done;){var l=u.value,f=n[l];if(!i&&f.isNode()&&(i=f),!o&&f.isEdge()&&(o=f),i&&o)break}}catch(v){s.e(v)}finally{s.f()}return[i,o].filter(Boolean)}function us(t,e,r){var a=t.drawing;e+=1,r.isNode()?(a.drawNode(r,e,"node-underlay"),a.drawNode(r,e,"node-body"),a.drawTexture(r,e,"label"),a.drawNode(r,e,"node-overlay")):(a.drawEdgeLine(r,e),a.drawEdgeArrow(r,e,"source"),a.drawEdgeArrow(r,e,"target"),a.drawTexture(r,e,"label"),a.drawTexture(r,e,"edge-source-label"),a.drawTexture(r,e,"edge-target-label"))}function Rc(t,e,r){var a;t.webglDebug&&(a=performance.now());var n=t.drawing,i=0;if(r.screen&&t.data.canvasNeedsRedraw[t.SELECT_BOX]&&A0(t,e),t.data.canvasNeedsRedraw[t.NODE]||r.picking){var o=t.data.contexts[t.WEBGL];r.screen?(o.clearColor(0,0,0,0),o.enable(o.BLEND),o.blendFunc(o.ONE,o.ONE_MINUS_SRC_ALPHA)):o.disable(o.BLEND),o.clear(o.COLOR_BUFFER_BIT|o.DEPTH_BUFFER_BIT),o.viewport(0,0,o.canvas.width,o.canvas.height);var s=D0(t),u=t.getCachedZSortedEles();if(i=u.length,n.startFrame(s,r),r.screen){for(var l=0;l<u.nondrag.length;l++)us(t,l,u.nondrag[l]);for(var f=0;f<u.drag.length;f++)us(t,f,u.drag[f])}else if(r.picking)for(var v=0;v<u.length;v++)us(t,v,u[v]);n.endFrame(),r.screen&&t.webglDebugShowAtlases&&(M0(t),L0(t)),t.data.canvasNeedsRedraw[t.NODE]=!1,t.data.canvasNeedsRedraw[t.DRAG]=!1}if(t.webglDebug){var c=performance.now(),h=!1,d=Math.ceil(c-a),g=n.getDebugInfo(),m=["".concat(i," elements"),"".concat(g.totalInstances," instances"),"".concat(g.batchCount," batches"),"".concat(g.totalAtlases," atlases"),"".concat(g.wrappedCount," wrapped textures"),"".concat(g.simpleCount," simple shapes")].join(", ");if(h)console.log("WebGL (".concat(r.name,") - time ").concat(d,"ms, ").concat(m));else{console.log("WebGL (".concat(r.name,") - frame time ").concat(d,"ms")),console.log("Totals:"),console.log(" ".concat(m)),console.log("Texture Atlases Used:");var p=g.atlasInfo,y=zt(p),b;try{for(y.s();!(b=y.n()).done;){var E=b.value;console.log(" ".concat(E.type,": ").concat(E.keyCount," keys, ").concat(E.atlasCount," atlases"))}}catch(C){y.e(C)}finally{y.f()}console.log("")}}t.data.gc&&(console.log("Garbage Collect!"),t.data.gc=!1,n.gc())}var Pr={};Pr.drawPolygonPath=function(t,e,r,a,n,i){var o=a/2,s=n/2;t.beginPath&&t.beginPath(),t.moveTo(e+o*i[0],r+s*i[1]);for(var u=1;u<i.length/2;u++)t.lineTo(e+o*i[u*2],r+s*i[u*2+1]);t.closePath()};Pr.drawRoundPolygonPath=function(t,e,r,a,n,i,o){o.forEach(function(s){return vc(t,s)}),t.closePath()};Pr.drawRoundRectanglePath=function(t,e,r,a,n,i){var o=a/2,s=n/2,u=i==="auto"?Cr(a,n):Math.min(i,s,o);t.beginPath&&t.beginPath(),t.moveTo(e,r-s),t.arcTo(e+o,r-s,e+o,r,u),t.arcTo(e+o,r+s,e,r+s,u),t.arcTo(e-o,r+s,e-o,r,u),t.arcTo(e-o,r-s,e,r-s,u),t.lineTo(e,r-s),t.closePath()};Pr.drawBottomRoundRectanglePath=function(t,e,r,a,n,i){var o=a/2,s=n/2,u=i==="auto"?Cr(a,n):i;t.beginPath&&t.beginPath(),t.moveTo(e,r-s),t.lineTo(e+o,r-s),t.lineTo(e+o,r),t.arcTo(e+o,r+s,e,r+s,u),t.arcTo(e-o,r+s,e-o,r,u),t.lineTo(e-o,r-s),t.lineTo(e,r-s),t.closePath()};Pr.drawCutRectanglePath=function(t,e,r,a,n,i,o){var s=a/2,u=n/2,l=o==="auto"?Gs():o;t.beginPath&&t.beginPath(),t.moveTo(e-s+l,r-u),t.lineTo(e+s-l,r-u),t.lineTo(e+s,r-u+l),t.lineTo(e+s,r+u-l),t.lineTo(e+s-l,r+u),t.lineTo(e-s+l,r+u),t.lineTo(e-s,r+u-l),t.lineTo(e-s,r-u+l),t.closePath()};Pr.drawBarrelPath=function(t,e,r,a,n){var i=a/2,o=n/2,s=e-i,u=e+i,l=r-o,f=r+o,v=cs(a,n),c=v.widthOffset,h=v.heightOffset,d=v.ctrlPtOffsetPct*c;t.beginPath&&t.beginPath(),t.moveTo(s,l+h),t.lineTo(s,f-h),t.quadraticCurveTo(s+d,f,s+c,f),t.lineTo(u-c,f),t.quadraticCurveTo(u-d,f,u,f-h),t.lineTo(u,l+h),t.quadraticCurveTo(u-d,l,u-c,l),t.lineTo(s+c,l),t.quadraticCurveTo(s+d,l,s,l+h),t.closePath()};var Wf=Math.sin(0),Xf=Math.cos(0),As={},Ms={},Pc=Math.PI/40;for(Vr=0*Math.PI;Vr<2*Math.PI;Vr+=Pc)As[Vr]=Math.sin(Vr),Ms[Vr]=Math.cos(Vr);var Vr;Pr.drawEllipsePath=function(t,e,r,a,n){if(t.beginPath&&t.beginPath(),t.ellipse)t.ellipse(e,r,a/2,n/2,0,0,2*Math.PI);else for(var i,o,s=a/2,u=n/2,l=0*Math.PI;l<2*Math.PI;l+=Pc)i=e-s*As[l]*Wf+s*Ms[l]*Xf,o=r+u*Ms[l]*Wf+u*As[l]*Xf,l===0?t.moveTo(i,o):t.lineTo(i,o);t.closePath()};var gn={};gn.createBuffer=function(t,e){var r=document.createElement("canvas");return r.width=t,r.height=e,[r,r.getContext("2d")]};gn.bufferCanvasImage=function(t){var e=this.cy,r=e.mutableElements(),a=r.boundingBox(),n=this.findContainerClientCoords(),i=t.full?Math.ceil(a.w):n[2],o=t.full?Math.ceil(a.h):n[3],s=we(t.maxWidth)||we(t.maxHeight),u=this.getPixelRatio(),l=1;if(t.scale!==void 0)i*=t.scale,o*=t.scale,l=t.scale;else if(s){var f=1/0,v=1/0;we(t.maxWidth)&&(f=l*t.maxWidth/i),we(t.maxHeight)&&(v=l*t.maxHeight/o),l=Math.min(f,v),i*=l,o*=l}s||(i*=u,o*=u,l*=u);var c=document.createElement("canvas");c.width=i,c.height=o,c.style.width=i+"px",c.style.height=o+"px";var h=c.getContext("2d");if(i>0&&o>0){h.clearRect(0,0,i,o),h.globalCompositeOperation="source-over";var d=this.getCachedZSortedEles();if(t.full)h.translate(-a.x1*l,-a.y1*l),h.scale(l,l),this.drawElements(h,d),h.scale(1/l,1/l),h.translate(a.x1*l,a.y1*l);else{var g=e.pan(),m={x:g.x*l,y:g.y*l};l*=e.zoom(),h.translate(m.x,m.y),h.scale(l,l),this.drawElements(h,d),h.scale(1/l,1/l),h.translate(-m.x,-m.y)}t.bg&&(h.globalCompositeOperation="destination-over",h.fillStyle=t.bg,h.rect(0,0,i,o),h.fill())}return c};function P0(t,e){for(var r=atob(t),a=new ArrayBuffer(r.length),n=new Uint8Array(a),i=0;i<r.length;i++)n[i]=r.charCodeAt(i);return new Blob([a],{type:e})}function $f(t){var e=t.indexOf(",");return t.substr(e+1)}function Oc(t,e,r){var a=function(){return e.toDataURL(r,t.quality)};switch(t.output){case"blob-promise":return new Ta(function(n,i){try{e.toBlob(function(o){o!=null?n(o):i(new Error("`canvas.toBlob()` sent a null value in its callback"))},r,t.quality)}catch(o){i(o)}});case"blob":return P0($f(a()),r);case"base64":return $f(a());default:return a()}}gn.png=function(t){return Oc(t,this.bufferCanvasImage(t),"image/png")};gn.jpg=function(t){return Oc(t,this.bufferCanvasImage(t),"image/jpeg")};var Ic={};Ic.nodeShapeImpl=function(t,e,r,a,n,i,o,s){switch(t){case"ellipse":return this.drawEllipsePath(e,r,a,n,i);case"polygon":return this.drawPolygonPath(e,r,a,n,i,o);case"round-polygon":return this.drawRoundPolygonPath(e,r,a,n,i,o,s);case"roundrectangle":case"round-rectangle":return this.drawRoundRectanglePath(e,r,a,n,i,s);case"cutrectangle":case"cut-rectangle":return this.drawCutRectanglePath(e,r,a,n,i,o,s);case"bottomroundrectangle":case"bottom-round-rectangle":return this.drawBottomRoundRectanglePath(e,r,a,n,i,s);case"barrel":return this.drawBarrelPath(e,r,a,n,i)}};var O0=Bc,Ge=Bc.prototype;Ge.CANVAS_LAYERS=3;Ge.SELECT_BOX=0;Ge.DRAG=1;Ge.NODE=2;Ge.WEBGL=3;Ge.CANVAS_TYPES=["2d","2d","2d","webgl2"];Ge.BUFFER_COUNT=3;Ge.TEXTURE_BUFFER=0;Ge.MOTIONBLUR_BUFFER_NODE=1;Ge.MOTIONBLUR_BUFFER_DRAG=2;function Bc(t){var e=this,r=e.cy.window(),a=r.document;t.webgl&&(Ge.CANVAS_LAYERS=e.CANVAS_LAYERS=4,console.log("webgl rendering enabled")),e.data={canvases:new Array(Ge.CANVAS_LAYERS),contexts:new Array(Ge.CANVAS_LAYERS),canvasNeedsRedraw:new Array(Ge.CANVAS_LAYERS),bufferCanvases:new Array(Ge.BUFFER_COUNT),bufferContexts:new Array(Ge.CANVAS_LAYERS)};var n="-webkit-tap-highlight-color",i="rgba(0,0,0,0)";e.data.canvasContainer=a.createElement("div");var o=e.data.canvasContainer.style;e.data.canvasContainer.style[n]=i,o.position="relative",o.zIndex="0",o.overflow="hidden";var s=t.cy.container();s.appendChild(e.data.canvasContainer),s.style[n]=i;var u={"-webkit-user-select":"none","-moz-user-select":"-moz-none","user-select":"none","-webkit-tap-highlight-color":"rgba(0,0,0,0)","outline-style":"none"};Ch()&&(u["-ms-touch-action"]="none",u["touch-action"]="none");for(var l=0;l<Ge.CANVAS_LAYERS;l++){var f=e.data.canvases[l]=a.createElement("canvas"),v=Ge.CANVAS_TYPES[l];e.data.contexts[l]=f.getContext(v),e.data.contexts[l]||nt("Could not create canvas of type "+v),Object.keys(u).forEach(function($){f.style[$]=u[$]}),f.style.position="absolute",f.setAttribute("data-id","layer"+l),f.style.zIndex=String(Ge.CANVAS_LAYERS-l),e.data.canvasContainer.appendChild(f),e.data.canvasNeedsRedraw[l]=!1}e.data.topCanvas=e.data.canvases[0],e.data.canvases[Ge.NODE].setAttribute("data-id","layer"+Ge.NODE+"-node"),e.data.canvases[Ge.SELECT_BOX].setAttribute("data-id","layer"+Ge.SELECT_BOX+"-selectbox"),e.data.canvases[Ge.DRAG].setAttribute("data-id","layer"+Ge.DRAG+"-drag"),e.data.canvases[Ge.WEBGL]&&e.data.canvases[Ge.WEBGL].setAttribute("data-id","layer"+Ge.WEBGL+"-webgl");for(var l=0;l<Ge.BUFFER_COUNT;l++)e.data.bufferCanvases[l]=a.createElement("canvas"),e.data.bufferContexts[l]=e.data.bufferCanvases[l].getContext("2d"),e.data.bufferCanvases[l].style.position="absolute",e.data.bufferCanvases[l].setAttribute("data-id","buffer"+l),e.data.bufferCanvases[l].style.zIndex=String(-l-1),e.data.bufferCanvases[l].style.visibility="hidden";e.pathsEnabled=!0;var c=Bt(),h=function(q){return{x:(q.x1+q.x2)/2,y:(q.y1+q.y2)/2}},d=function(q){return{x:-q.w/2,y:-q.h/2}},g=function(q){var K=q[0]._private,ee=K.oldBackgroundTimestamp===K.backgroundTimestamp;return!ee},m=function(q){return q[0]._private.nodeKey},p=function(q){return q[0]._private.labelStyleKey},y=function(q){return q[0]._private.sourceLabelStyleKey},b=function(q){return q[0]._private.targetLabelStyleKey},E=function(q,K,ee,ne,te){return e.drawElement(q,K,ee,!1,!1,te)},C=function(q,K,ee,ne,te){return e.drawElementText(q,K,ee,ne,"main",te)},A=function(q,K,ee,ne,te){return e.drawElementText(q,K,ee,ne,"source",te)},D=function(q,K,ee,ne,te){return e.drawElementText(q,K,ee,ne,"target",te)},N=function(q){return q.boundingBox(),q[0]._private.bodyBounds},O=function(q){return q.boundingBox(),q[0]._private.labelBounds.main||c},R=function(q){return q.boundingBox(),q[0]._private.labelBounds.source||c},P=function(q){return q.boundingBox(),q[0]._private.labelBounds.target||c},w=function(q,K){return K},x=function(q){return h(N(q))},T=function(q,K,ee){var ne=q?q+"-":"";return{x:K.x+ee.pstyle(ne+"text-margin-x").pfValue,y:K.y+ee.pstyle(ne+"text-margin-y").pfValue}},M=function(q,K,ee){var ne=q[0]._private.rscratch;return{x:ne[K],y:ne[ee]}},S=function(q){return T("",M(q,"labelX","labelY"),q)},I=function(q){return T("source",M(q,"sourceLabelX","sourceLabelY"),q)},B=function(q){return T("target",M(q,"targetLabelX","targetLabelY"),q)},V=function(q){return d(N(q))},F=function(q){return d(R(q))},k=function(q){return d(P(q))},U=function(q){var K=O(q),ee=d(O(q));if(q.isNode()){switch(wa(q.pstyle("text-halign").value)){case"left":ee.x=-K.w-(K.leftPad||0);break;case"right":ee.x=-(K.rightPad||0);break}switch(Ea(q.pstyle("text-valign").value)){case"top":ee.y=-K.h-(K.topPad||0);break;case"bottom":ee.y=-(K.botPad||0);break}}return ee},J=e.data.eleTxrCache=new qa(e,{getKey:m,doesEleInvalidateKey:g,drawElement:E,getBoundingBox:N,getRotationPoint:x,getRotationOffset:V,allowEdgeTxrCaching:!1,allowParentTxrCaching:!1}),W=e.data.lblTxrCache=new qa(e,{getKey:p,drawElement:C,getBoundingBox:O,getRotationPoint:S,getRotationOffset:U,isVisible:w}),Q=e.data.slbTxrCache=new qa(e,{getKey:y,drawElement:A,getBoundingBox:R,getRotationPoint:I,getRotationOffset:F,isVisible:w}),Z=e.data.tlbTxrCache=new qa(e,{getKey:b,drawElement:D,getBoundingBox:P,getRotationPoint:B,getRotationOffset:k,isVisible:w}),H=e.data.lyrTxrCache=new xc(e);e.onUpdateEleCalcs(function(q,K){J.invalidateElements(K),W.invalidateElements(K),Q.invalidateElements(K),Z.invalidateElements(K),H.invalidateElements(K);for(var ee=0;ee<K.length;ee++){var ne=K[ee]._private;ne.oldBackgroundTimestamp=ne.backgroundTimestamp}});var j=function(q){for(var K=0;K<q.length;K++)H.enqueueElementRefinement(q[K].ele)};J.onDequeue(j),W.onDequeue(j),Q.onDequeue(j),Z.onDequeue(j),t.webgl&&e.initWebgl(t,{getStyleKey:m,getLabelKey:p,getSourceLabelKey:y,getTargetLabelKey:b,drawElement:E,drawLabel:C,drawSourceLabel:A,drawTargetLabel:D,getElementBox:N,getLabelBox:O,getSourceLabelBox:R,getTargetLabelBox:P,getElementRotationPoint:x,getElementRotationOffset:V,getLabelRotationPoint:S,getSourceLabelRotationPoint:I,getTargetLabelRotationPoint:B,getLabelRotationOffset:U,getSourceLabelRotationOffset:F,getTargetLabelRotationOffset:k})}Ge.redrawHint=function(t,e){var r=this;switch(t){case"eles":r.data.canvasNeedsRedraw[Ge.NODE]=e;break;case"drag":r.data.canvasNeedsRedraw[Ge.DRAG]=e;break;case"select":r.data.canvasNeedsRedraw[Ge.SELECT_BOX]=e;break;case"gc":r.data.gc=!0;break}};var I0=typeof Path2D<"u";Ge.path2dEnabled=function(t){if(t===void 0)return this.pathsEnabled;this.pathsEnabled=!!t};Ge.usePaths=function(){return I0&&this.pathsEnabled};Ge.setImgSmoothing=function(t,e){t.imageSmoothingEnabled!=null?t.imageSmoothingEnabled=e:(t.webkitImageSmoothingEnabled=e,t.mozImageSmoothingEnabled=e,t.msImageSmoothingEnabled=e)};Ge.getImgSmoothing=function(t){return t.imageSmoothingEnabled!=null?t.imageSmoothingEnabled:t.webkitImageSmoothingEnabled||t.mozImageSmoothingEnabled||t.msImageSmoothingEnabled};Ge.makeOffscreenCanvas=function(t,e){var r;if((typeof OffscreenCanvas>"u"?"undefined":mt(OffscreenCanvas))!=="undefined")r=new OffscreenCanvas(t,e);else{var a=this.cy.window(),n=a.document;r=n.createElement("canvas"),r.width=t,r.height=e}return r};[Tc,rr,fr,js,Qr,Rr,kt,Mc,Pr,gn,Ic].forEach(function(t){Re(Ge,t)});var B0=[{name:"null",impl:lc},{name:"base",impl:bc},{name:"canvas",impl:O0}],k0=[{type:"layout",extensions:im},{type:"renderer",extensions:B0}],kc={},Fc={};function zc(t,e,r){var a=r,n=function(N){Qe("Can not register `"+e+"` for `"+t+"` since `"+N+"` already exists in the prototype and can not be overridden")};if(t==="core"){if(tn.prototype[e])return n(e);tn.prototype[e]=r}else if(t==="collection"){if(St.prototype[e])return n(e);St.prototype[e]=r}else if(t==="layout"){for(var i=function(N){this.options=N,r.call(this,N),$e(this._private)||(this._private={}),this._private.cy=N.cy,this._private.listeners=[],this.createEmitter()},o=i.prototype=Object.create(r.prototype),s=[],u=0;u<s.length;u++){var l=s[u];o[l]=o[l]||function(){return this}}o.start&&!o.run?o.run=function(){return this.start(),this}:!o.start&&o.run&&(o.start=function(){return this.run(),this});var f=r.prototype.stop;o.stop=function(){var D=this.options;if(D&&D.animate){var N=this.animations;if(N)for(var O=0;O<N.length;O++)N[O].stop()}return f?f.call(this):this.emit("layoutstop"),this},o.destroy||(o.destroy=function(){return this}),o.cy=function(){return this._private.cy};var v=function(N){return N._private.cy},c={addEventFields:function(N,O){O.layout=N,O.cy=v(N),O.target=N},bubble:function(){return!0},parent:function(N){return v(N)}};Re(o,{createEmitter:function(){return this._private.emitter=new mi(c,this),this},emitter:function(){return this._private.emitter},on:function(N,O){return this.emitter().on(N,O),this},one:function(N,O){return this.emitter().one(N,O),this},once:function(N,O){return this.emitter().one(N,O),this},removeListener:function(N,O){return this.emitter().removeListener(N,O),this},removeAllListeners:function(){return this.emitter().removeAllListeners(),this},emit:function(N,O){return this.emitter().emit(N,O),this}}),Ze.eventAliasesOn(o),a=i}else if(t==="renderer"&&e!=="null"&&e!=="base"){var h=Vc("renderer","base"),d=h.prototype,g=r,m=r.prototype,p=function(){h.apply(this,arguments),g.apply(this,arguments)},y=p.prototype;for(var b in d){var E=d[b],C=m[b]!=null;if(C)return n(b);y[b]=E}for(var A in m)y[A]=m[A];d.clientFunctions.forEach(function(D){y[D]=y[D]||function(){nt("Renderer does not implement `renderer."+D+"()` on its prototype")}}),a=p}else if(t==="__proto__"||t==="constructor"||t==="prototype")return nt(t+" is an illegal type to be registered, possibly lead to prototype pollutions");return rv({map:kc,keys:[t,e],value:a})}function Vc(t,e){return av({map:kc,keys:[t,e]})}function F0(t,e,r,a,n){return rv({map:Fc,keys:[t,e,r,a],value:n})}function z0(t,e,r,a){return av({map:Fc,keys:[t,e,r,a]})}var Ls=function(){if(arguments.length===2)return Vc.apply(null,arguments);if(arguments.length===3)return zc.apply(null,arguments);if(arguments.length===4)return z0.apply(null,arguments);if(arguments.length===5)return F0.apply(null,arguments);nt("Invalid extension access syntax")};tn.prototype.extension=Ls;k0.forEach(function(t){t.extensions.forEach(function(e){zc(t.type,e.name,e.impl)})});var si=function(){if(!(this instanceof si))return new si;this.length=0},_r=si.prototype;_r.instanceString=function(){return"stylesheet"};_r.selector=function(t){var e=this.length++;return this[e]={selector:t,properties:[]},this};_r.css=function(t,e){var r=this.length-1;if(Le(t))this[r].properties.push({name:t,value:e});else if($e(t))for(var a=t,n=Object.keys(a),i=0;i<n.length;i++){var o=n[i],s=a[o];if(s!=null){var u=xt.properties[o]||xt.properties[li(o)];if(u!=null){var l=u.name,f=s;this[r].properties.push({name:l,value:f})}}}return this};_r.style=_r.css;_r.generateStyle=function(t){var e=new xt(t);return this.appendToStyle(e)};_r.appendToStyle=function(t){for(var e=0;e<this.length;e++){var r=this[e],a=r.selector,n=r.properties;t.selector(a);for(var i=0;i<n.length;i++){var o=n[i];t.css(o.name,o.value)}}return t};var V0="3.34.0",lr=function(e){if(e===void 0&&(e={}),$e(e))return new tn(e);if(Le(e))return Ls.apply(Ls,arguments)};lr.use=function(t){var e=Array.prototype.slice.call(arguments,1);return e.unshift(lr),t.apply(null,e),this};lr.warnings=function(t){return fv(t)};lr.version=V0;lr.stylesheet=lr.Stylesheet=si;var _c=oh(Gc(),1);var Ma={Entity:0,Service:1,Event:1,UseCase:2,Port:3,DTO:4,VO:4,Error:4,Shared:4,Adapter:5},qc={Entity:95,Service:72,Event:60,UseCase:48,Port:30,DTO:0,VO:0,Error:0,Shared:22,Adapter:18},Yc={Entity:"barrel",Service:"rectangle",UseCase:"round-rectangle",Port:"cut-rectangle",Event:"rhomboid",DTO:"round-rectangle",VO:"round-rectangle",Error:"round-rectangle",Shared:"round-rectangle",Adapter:"round-rectangle"},ol=["Entity","Service","UseCase","Port","Event"],sl=["DTO","VO","Error"],bn=42,Wc=338,G0=15;function Uc(t){let e=0;for(let a=0;a<t.length;a++)e=e*31+t.charCodeAt(a)|0;let r=Math.abs(e*.6180339887%1);return Math.round(bn+r*(Wc-bn))}var U0=(t,e)=>{let r=Math.abs(t-e)%360;return Math.min(r,360-r)};function Xc(t){let e=[...new Set(t)].filter(i=>!La(i)).sort(),r=[],a=new Map,n=Wc-bn;for(let i of e){let o=Uc(i),s=o;for(let u=0;u<n;u++){let l=bn+(o-bn+u)%n;if(r.every(f=>U0(f,l)>=G0)){s=l;break}}r.push(s),a.set(i,s)}return i=>La(i)?0:a.get(i)??Uc(i)}var La=t=>t==="common"||t==="shared",Di=190,H0=40,q0=230,Y0=268,W0=130,Hc=34,X0=30;function $0(t){let e=new Map;for(let o of t){let s=Ma[o.component];e.set(s,[...e.get(s)??[],o])}let r=new Map,a=0;for(let o of[...e.keys()].sort((s,u)=>s-u)){let s=e.get(o),u=s.length*Y0/(2*Math.PI),l=o===0&&s.length===1?0:Math.max(a+q0,u,170);s.forEach((f,v)=>{if(l===0)r.set(f.id,[0,0]);else{let c=2*Math.PI*v/s.length-Math.PI/2;r.set(f.id,[l*Math.cos(c),l*Math.sin(c)])}}),a=l}let n=0,i=0;for(let[o,s]of r.values())n=Math.max(n,Math.abs(o)),i=Math.max(i,Math.abs(s));return{pos:r,hw:n+Di/2+Hc,hh:i+H0/2+Hc+X0/2}}function K0(t,e,r=W0){let a=new Map(t.nodes.map(c=>[c.id,c])),n=new Map;for(let c of t.edges){let h=a.get(c.src)?.domain,d=a.get(c.dst)?.domain;if(!h||!d||h===d)continue;let g=h<d?`${h}|${d}`:`${d}|${h}`;n.set(g,(n.get(g)??0)+1)}let i=c=>e.get(c)??{hw:0,hh:0},o=c=>i(c).hw*i(c).hh,s=[...e.keys()].sort((c,h)=>o(h)-o(c)),u=new Map,l=0,f=0;s.forEach((c,h)=>{if(h===0){u.set(c,[0,0]);return}l+=Math.hypot(i(c).hw,i(c).hh)*.95,f+=2.399963,u.set(c,[l*Math.cos(f),l*Math.sin(f)])});let v=c=>{let h=0;for(let d=0;d<s.length;d++){let g=s[d];for(let m=d+1;m<s.length;m++){let p=s[m],y=u.get(g),b=u.get(p),E=b[0]-y[0],C=b[1]-y[1],A=i(g).hw+i(p).hw+r-Math.abs(E),D=i(g).hh+i(p).hh+r-Math.abs(C);if(A<=0||D<=0)continue;h=Math.max(h,Math.min(A,D));let N=Math.min(A,D)*c;if(A<D){let O=E>=0?1:-1;y[0]-=O*N,b[0]+=O*N}else{let O=C>=0?1:-1;y[1]-=O*N,b[1]+=O*N}}}return h};for(let c=0;c<400;c++){for(let h=0;h<s.length;h++){let d=s[h];for(let g=h+1;g<s.length;g++){let m=s[g],p=n.get(d<m?`${d}|${m}`:`${m}|${d}`)??0,y=u.get(d),b=u.get(m),E=b[0]-y[0],C=b[1]-y[1],A=Math.hypot(E,C)||1,D=i(d).hw+i(m).hw+r-Math.abs(E),N=i(d).hh+i(m).hh+r-Math.abs(C);if(D>0&&N>0)continue;let O=-Math.min(D,N),R=Math.min(O*(p?.06*Math.log1p(p):.006),90);u.set(d,[y[0]+E/A*R,y[1]+C/A*R]),u.set(m,[b[0]-E/A*R,b[1]-C/A*R])}}v(.5);for(let h of s){let d=u.get(h);d[0]-=d[0]*.004,d[1]-=d[1]*.004}}for(let c=0;c<600&&v(.5)>.5;c++);return u}function ll(t){let e=new Map;for(let o of t.nodes)e.set(o.domain,[...e.get(o.domain)??[],o]);let r=new Map,a=new Map;for(let[o,s]of e){let u=$0(s);r.set(o,u.pos),a.set(o,{hw:u.hw,hh:u.hh})}let n=K0(t,a),i=[];for(let[o,s]of r){let[u,l]=n.get(o)??[0,0];for(let[f,[v,c]]of s)i.push({id:f,x:Math.round(u+v),y:Math.round(l+c)})}return i}var _0=Di+54,Z0=74;function Q0(t,e){let r=[...e].sort((i,o)=>Ma[i.component]-Ma[o.component]||i.name.localeCompare(o.name)),a=Math.max(1,Math.min(5,Math.ceil(Math.sqrt(r.length/2.2)))),n=Math.ceil(r.length/a);return{d:t,items:r,cols:a,w:a*_0+80,h:n*Z0+92}}function $c(t,e=3e3){let r=new Map;for(let l of t.nodes)r.set(l.domain,[...r.get(l.domain)??[],l]);let a=[...r.entries()].map(([l,f])=>Q0(l,f)).sort((l,f)=>f.items.length-l.items.length),n=e,i=[],o=0,s=0,u=0;for(let l of a)s+l.w>n&&s>0&&(o+=u+90,s=0,u=0),l.items.forEach((f,v)=>{i.push({id:f.id,x:Math.round(s+40+v%l.cols*(Di+54)+Di/2),y:Math.round(o+52+Math.floor(v/l.cols)*74)})}),s+=l.w+70,u=Math.max(u,l.h);return i}lr.use(_c.default);var vr=(t,e,r)=>`hsl(${t},${e}%,${r}%)`,He=t=>document.getElementById(t),ea=t=>Array.from(document.querySelectorAll(t)),Ue,wt,pl,Li="hex",Or=!1,jr=!1,Ai,ta=null,Jr="both",Kc,Ni,wn=()=>0;async function J0(){wt=await(await fetch("/api/graph")).json();let t=[...new Set(wt.nodes.map(a=>a.domain))];wn=Xc(t);let e=[...new Set(wt.nodes.map(a=>a.component))].sort((a,n)=>Ma[a]-Ma[n]);pl={hex:new Map(ll(wt).map(a=>[a.id,{x:a.x,y:a.y}])),grid:new Map($c(wt).map(a=>[a.id,{x:a.x,y:a.y}]))},document.title=`${wt.project} \u2014 hexwright`,He("title").textContent=wt.project,He("ref").textContent=wt.ref;let r={added:wt.nodes.filter(a=>a.status==="added").length,modified:wt.nodes.filter(a=>a.status==="modified").length,addedEdges:wt.edges.filter(a=>a.status==="added").length};(r.added||r.modified)&&(He("delta").innerHTML=`<span class="k"></span>added ${r.added} nodes \xB7 ${r.addedEdges} edges<br><span class="k2"></span>modified ${r.modified} nodes`,He("deltaBox").style.display="block"),j0(t,e),tb(),cl("bhex"),gl("core")}function j0(t,e){let r=new Map;for(let a of wt.nodes)r.set(`c:${a.component}`,(r.get(`c:${a.component}`)??0)+1),r.set(`d:${a.domain}`,(r.get(`d:${a.domain}`)??0)+1);He("comps").innerHTML=e.map(a=>`<label><span class="sw" style="${eb(a)}"></span><input type=checkbox class=cf value="${a}" ${ol.includes(a)?"checked":""}>${a}<span class="n">${r.get(`c:${a}`)??0}</span></label>`).join(""),He("doms").innerHTML=t.sort((a,n)=>(r.get(`d:${n}`)??0)-(r.get(`d:${a}`)??0)).map(a=>{let n=wn(a);return`<label><span class="sw" style="background:${vr(n,La(a)?0:60,50)}"></span><input type=checkbox class=df value="${a}" checked>${a}<span class="n">${r.get(`d:${a}`)??0}</span></label>`}).join("");for(let a of ea(".cf,.df,.rf"))a.onchange=()=>Ir();He("showId").onchange=()=>Ir(),He("crossOnly").onchange=()=>Ir(),He("deltaOnly").onchange=()=>Ir()}function eb(t){let e="#8b949e";return sl.includes(t)?`border:1.4px dashed ${e};border-radius:5px`:`background:${e};${{Entity:"border-radius:6px/50%",Service:"border-radius:0",Port:"clip-path:polygon(22% 0,100% 0,100% 78%,78% 100%,0 100%,0 22%)",Event:"transform:skewX(-16deg)"}[t]??"border-radius:5px"}`}function tb(){let t=[...new Set(wt.nodes.map(n=>n.domain))].map(n=>({data:{id:`dom::${n}`,label:n,kind:"domain",hue:wn(n),sat:La(n)?0:26}})),e=wt.nodes.map(n=>({data:{...n,parent:`dom::${n.domain}`,kind:"type",hue:wn(n.domain),sat:La(n.domain)?0:qc[n.component],shape:Yc[n.component],outline:sl.includes(n.component),label:n.name},position:{...pl.hex.get(n.id)??{x:0,y:0}}})),r=wt.edges.map((n,i)=>({data:{...n,id:`e${i}`,source:n.src,target:n.dst,hue:wn(vl(n.src)?.domain??"")}}));Ue=lr({container:He("cy"),elements:[...t,...e,...r],layout:{name:"preset"},minZoom:.05,maxZoom:3,wheelSensitivity:.25,style:[{selector:'node[kind="domain"]',style:{"background-color":n=>vr(n.data("hue"),n.data("sat"),13),"background-opacity":.5,"border-width":1.5,"border-color":n=>vr(n.data("hue"),n.data("sat")+19,42),shape:"round-rectangle",label:"data(label)","text-valign":"top","font-size":21,"font-weight":"bold",color:n=>vr(n.data("hue"),n.data("sat")+29,62),"text-margin-y":-7,padding:"16px"}},{selector:'node[kind="type"]',style:{shape:"data(shape)",width:"182px",height:"32px","background-color":n=>vr(n.data("hue"),n.data("sat"),46-n.data("sat")*.07),"background-opacity":n=>n.data("outline")?0:1,label:"data(label)","font-size":11,"text-valign":"center","text-wrap":"ellipsis","text-max-width":"160px",color:n=>n.data("outline")?vr(n.data("hue"),n.data("hue")?52:0,72):"#fff","border-width":n=>n.data("outline")?1.4:1,"border-color":n=>vr(n.data("hue"),n.data("outline")?48:n.data("sat"),n.data("outline")?52:70),"border-style":n=>n.data("outline")?"dashed":"solid"}},{selector:'node[component="Entity"]',style:{"border-width":2.6,width:"190px",height:"36px","font-weight":"bold","font-size":12}},{selector:'node[component="Service"]',style:{"border-width":1.8}},{selector:"edge",style:{width:1.9,"line-color":n=>vr(n.data("hue"),n.data("crossDomain")?62:22,n.data("crossDomain")?58:46),opacity:n=>n.data("crossDomain")?.8:.62,"target-arrow-color":n=>vr(n.data("hue"),n.data("crossDomain")?62:22,n.data("crossDomain")?58:46)}},{selector:'edge[rel="DEPENDS_ON"]',style:{"line-style":"solid","curve-style":"straight","target-arrow-shape":"vee","arrow-scale":.95}},{selector:'edge[rel="IMPLEMENTS"]',style:{"line-style":"dashed","line-dash-pattern":[9,5],width:2.2,"curve-style":"unbundled-bezier","control-point-distances":[42],"control-point-weights":[.5],"target-arrow-shape":"triangle","target-arrow-fill":"hollow","arrow-scale":1.35}},{selector:'edge[rel="EXTENDS"]',style:{"line-style":"dashed","line-dash-pattern":[3,3],width:3.4,"curve-style":"unbundled-bezier","control-point-distances":[58],"control-point-weights":[.5],"target-arrow-shape":"triangle","target-arrow-fill":"hollow","arrow-scale":1.6}},{selector:"edge[?identifierOnly]",style:{"line-style":"dotted",opacity:.4}},{selector:'edge[violation != ""]',style:{"line-color":"#f85149","target-arrow-color":"#f85149",width:3.4,opacity:1,"z-index":90,label:"data(violation)","font-size":10,color:"#f85149","text-background-color":"#0e1116","text-background-opacity":.85,"text-background-padding":"3px"}},{selector:'edge[status="added"]',style:{opacity:1,"line-color":"#f0883e","target-arrow-color":"#f0883e","z-index":80}},{selector:".dim",style:{opacity:.035,"text-opacity":0}},{selector:".nb",style:{"border-width":2.4,"border-color":"#58a6ff","z-index":50}},{selector:".hi",style:{"border-width":5,"border-color":"#58a6ff","z-index":100}},{selector:"edge.sel",style:{width:5,opacity:1,"line-color":"#58a6ff","target-arrow-color":"#58a6ff","z-index":99}}]}),window.cy=Ue,new ResizeObserver(()=>{Ue.resize();let n=Ue.nodes('[kind="type"]').filter(i=>i.style("display")==="element");n.length&&Ue.fit(n,40)}).observe(He("cy")),Ue.on("tap",'node[kind="type"]',n=>dl(n.target)),Ue.on("tap","edge",n=>sb(n.target)),Ue.on("tap",n=>{let i=n.target;(n.target===Ue||i.data?.("kind")==="domain")&&hl()}),document.addEventListener("keydown",n=>{n.key==="Escape"&&hl()})}var vl=t=>wt.nodes.find(e=>e.id===t);function Ir(){let t=new Set(ea(".cf:checked").map(u=>u.value)),e=new Set(ea(".df:checked").map(u=>u.value)),r=new Set(ea(".rf:checked").map(u=>u.value)),a=He("showId").checked,n=He("crossOnly").checked,i=He("deltaOnly").checked,o=new Set;if(jr)for(let u of Ue.edges())u.data("violation")&&(o.add(u.data("source")),o.add(u.data("target")));Ue.batch(()=>{for(let l of Ue.nodes('[kind="type"]')){let f=l.data(),v=t.has(f.component)&&e.has(f.domain);v&&i&&f.status==="existing"&&(v=!1),v&&jr&&!o.has(f.id)&&(v=!1),l.style("display",v?"element":"none")}let u=l=>l.style("display")==="element";for(let l of Ue.nodes('[kind="domain"]'))l.style("display",l.children().filter(f=>u(f)).length?"element":"none");for(let l of Ue.edges()){let f=u(l.source())&&u(l.target())&&r.has(l.data("rel"));f&&!a&&l.data("identifierOnly")&&(f=!1),f&&n&&!l.data("crossDomain")&&(f=!1),f&&jr&&!l.data("violation")&&(f=!1),l.style("display",f?"element":"none")}}),rb(),Ue.nodes('[kind="type"]').filter(u=>u.style("display")==="element").length&&ab()}function rb(){let t=n=>n.style("display")==="element",e=Ue.nodes('[kind="type"]').filter(n=>t(n)).length,r=Ue.edges().filter(n=>t(n)).length,a=Ue.edges().filter(n=>t(n)&&n.data("violation")).length;He("stat").innerHTML=`Nodes <b>${e}</b>/${Ue.nodes('[kind="type"]').length} \xB7 Edges <b>${r}</b>/${Ue.edges().length}`,He("cviol").textContent=String(a);for(let n of["DEPENDS_ON","IMPLEMENTS","EXTENDS"]){let i=document.getElementById(`c${n}`);i&&(i.textContent=String(Ue.edges(`[rel="${n}"]`).filter(o=>t(o)).length))}}function ab(){clearTimeout(Kc),Kc=setTimeout(Mi,110)}function Mi(){Ni?.stop(),Ni=void 0,Or?Li==="hex"?nb():ob():ib()}var ul=t=>t.style("display")==="element";function nb(){let t=new Set(Ue.nodes('[kind="type"]').filter(i=>ul(i)).map(i=>i.id())),e=new Set(Ue.edges().filter(i=>ul(i)).map(i=>i.id())),r={...wt,nodes:wt.nodes.filter(i=>t.has(i.id)),edges:wt.edges.filter((i,o)=>e.has(`e${o}`))},a=new Map(ll(r).map(i=>[i.id,i]));Ue.batch(()=>{for(let i of Ue.nodes('[kind="type"]')){let o=a.get(i.id());o&&i.position({x:o.x,y:o.y})}});let n=Ue.nodes('[kind="type"]').filter(i=>ul(i));n.length&&Ue.fit(n,40)}function ib(){let t=pl[Li];Ue.batch(()=>{for(let r of Ue.nodes('[kind="type"]')){let a=t.get(r.id());a&&r.position({x:a.x,y:a.y})}});let e=Ue.nodes('[kind="type"]').filter(r=>r.style("display")==="element");e.length&&Ue.fit(e,40)}function ob(){let t=Ue.elements().filter(r=>r.style("display")==="element"),e=t.nodes().length;e&&(Ni=t.layout({name:"fcose",quality:e<=150?"proof":e<=400?"default":"draft",numIter:e<=150?1600:e<=400?900:500,randomize:e<=150,animate:e<=250,animationDuration:400,nodeSeparation:210,idealEdgeLength:r=>r.data("crossDomain")?300:130,nodeRepulsion:34e3,gravity:.12,gravityCompound:.9,gravityRangeCompound:2.2,packComponents:!0,tile:!0,nodeDimensionsIncludeLabels:!0,stop:()=>Ue.fit(t.nodes(),60)}),Ni.run())}var cl=t=>{for(let e of["bhex","bgrid"])He(e).classList.toggle("on",e===t)};function hl(){Ue.elements().removeClass("hi dim sel nb"),He("info").style.display="none",ta=null,Jr="both"}var Vt=(t,e)=>`<tr><td>${t}</td><td>${e}</td></tr>`,fl=t=>t?'<span style="color:#f0883e">yes</span>':"no",Zc=t=>t==="added"?'<span style="color:#f0883e">added</span>':t==="modified"?'<span style="color:#a371f7">modified</span>':"existing";function dl(t){ta=t.id();let e=t.data(),r=c=>c.style("display")==="element",a=t.connectedEdges().filter(c=>r(c)),n=a.filter(c=>c.target().id()===ta),i=a.filter(c=>c.source().id()===ta),o=Jr==="in"?n:Jr==="out"?i:a,s=o.connectedNodes().difference(t);Ue.elements().removeClass("hi dim sel nb").addClass("dim"),t.removeClass("dim").addClass("hi"),s.removeClass("dim").addClass("nb"),o.removeClass("dim").addClass("sel"),s.parent().removeClass("dim"),t.parent().removeClass("dim");let u=(c,h,d)=>`<button class="dirb ${Jr===c?"on":""}" data-dir="${c}">${h} ${d}</button>`,l=(c,h,d)=>{let g=d.data();return`<div class="lk" data-goto="${g.id}"><span class="ar">${h}</span>${g.name}<span class="mut"> ${g.domain}\xB7${g.component}</span><span class="rel">${c.data("rel")==="DEPENDS_ON"?"":c.data("rel")}</span></div>`},f="";if(Jr!=="out")for(let c of n)f+=l(c,"\u2190",c.source());if(Jr!=="in")for(let c of i)f+=l(c,"\u2192",c.target());let v=e.api.length||e.props.length?`<div class="dirbar" style="display:block"><b>Public contract</b><span class="mut"> ${e.api.length} fn${e.props.length?` \xB7 ${e.props.length} prop`:""}</span></div><div class="lks">${e.api.map(c=>{let h=c.indexOf("(");return`<div class="lk"><span class="sig"><b>${c.slice(0,h)}</b>${c.slice(h)}</span></div>`}).join("")}${e.props.map(c=>`<div class="lk"><span class="sig" style="color:#6e7681">${c}</span></div>`).join("")}</div>`:"";He("info").style.display="block",He("info").innerHTML=`<div class="ih">${e.name}<span class="x">\xD7</span></div><table>${Vt("Domain",e.domain)}${Vt("Component",`${e.component} <span class="mut">${e.layer}${e.sublayer?`/${e.sublayer}`:""}</span>`)}${Vt("Kind",e.kind)}${Vt("Status",Zc(e.status))}${Vt("File",`<span class="mut">${e.file}:${e.line}</span>`)}${Vt("Id",`<span class="mut" style="word-break:break-all">${e.id}</span>`)}</table>${v}<div class="dirbar">${u("both","Both",a.length)}${u("in","\u2190 In",n.length)}${u("out","Out \u2192",i.length)}</div><div class="lks">${f||'<span class="mut">No visible connections</span>'}</div><div class="hint">Click an item to focus it \xB7 Esc to clear</div>`,Qc()}function sb(t){ta=null;let e=t.data(),r=vl(e.src),a=vl(e.dst);Ue.elements().removeClass("hi dim sel nb").addClass("dim"),t.removeClass("dim").addClass("sel"),t.connectedNodes().removeClass("dim").addClass("nb").parent().removeClass("dim");let n=e.contracts.length?`<div class="dirbar" style="display:block"><b>Contracts used</b><span class="mut"> ${e.contracts.length}/${a?.api.length??0}</span></div><div class="lks">${e.contracts.map(i=>{let o=i.indexOf("(");return`<div class="lk"><span class="sig"><b>${o>0?i.slice(0,o):i}</b>${o>0?i.slice(o):""}</span></div>`}).join("")}</div>`:'<div class="hint">No method calls \u2014 type reference only</div>';He("info").style.display="block",He("info").innerHTML=`<div class="ih">${e.rel}<span class="x">\xD7</span></div><table>${Vt("Source",`${r?.name} <span class="mut">${r?.domain}\xB7${r?.component}</span>`)}${Vt("Target",`${a?.name} <span class="mut">${a?.domain}\xB7${a?.component}</span>`)}${e.rel==="DEPENDS_ON"?Vt("Weight",`${e.weight} <span class="mut">occurrences</span>`):""}${Vt("Cross-domain",fl(e.crossDomain))}${Vt("Identifier only",fl(e.identifierOnly))}${Vt("Via signature",fl(e.viaSignature))}${e.violation?Vt("Violation",`<span style="color:#f85149">${e.violation}</span>`):""}${Vt("Status",Zc(e.status))}</table>${n}`,Qc()}function Qc(){let t=He("info").querySelector(".x");t&&(t.onclick=()=>hl());for(let e of Array.from(He("info").querySelectorAll(".dirb")))e.onclick=()=>{Jr=e.dataset.dir,ta&&dl(Ue.getElementById(ta))};for(let e of Array.from(He("info").querySelectorAll("[data-goto]")))e.onclick=()=>dl(Ue.getElementById(e.dataset.goto))}function gl(t){for(let e of ea(".cf"))e.checked=t==="core"?ol.includes(e.value):!0;for(let e of["pcore","pall"])He(e).classList.toggle("on",e===`p${t}`);Ir()}function lb(){He("pcore").onclick=()=>gl("core"),He("pall").onclick=()=>gl("all"),He("bhex").onclick=()=>{Li="hex",cl("bhex"),Mi()},He("bgrid").onclick=()=>{Li="grid",cl("bgrid"),Mi()},He("borg").onclick=()=>{Or=!Or,He("borg").classList.toggle("on",Or),Mi()},He("bviol").onclick=()=>{jr=!jr,He("bviol").classList.toggle("on",jr),jr?(Ai=Or,Or=!0):Ai!==void 0&&(Or=Ai,Ai=void 0),He("borg").classList.toggle("on",Or),Ir()},He("allDomOn").onclick=()=>{for(let t of ea(".df"))t.checked=!0;Ir()},He("allDomOff").onclick=()=>{for(let t of ea(".df"))t.checked=!1;Ir()},J0()}lb();})();
|
|
321
|
+
`),s=Jm(a,n,o);s.aPosition=a.getAttribLocation(s,"aPosition"),s.aIndex=a.getAttribLocation(s,"aIndex"),s.aVertType=a.getAttribLocation(s,"aVertType"),s.aTransform=a.getAttribLocation(s,"aTransform"),s.aAtlasId=a.getAttribLocation(s,"aAtlasId"),s.aTex=a.getAttribLocation(s,"aTex"),s.aPointAPointB=a.getAttribLocation(s,"aPointAPointB"),s.aPointCPointD=a.getAttribLocation(s,"aPointCPointD"),s.aLineWidth=a.getAttribLocation(s,"aLineWidth"),s.aColor=a.getAttribLocation(s,"aColor"),s.aCornerRadius=a.getAttribLocation(s,"aCornerRadius"),s.aBorderColor=a.getAttribLocation(s,"aBorderColor"),s.uPanZoomMatrix=a.getUniformLocation(s,"uPanZoomMatrix"),s.uAtlasSize=a.getUniformLocation(s,"uAtlasSize"),s.uBGColor=a.getUniformLocation(s,"uBGColor"),s.uZoom=a.getUniformLocation(s,"uZoom"),s.uTextures=[];for(var u=0;u<this.batchManager.getMaxAtlasesPerBatch();u++)s.uTextures.push(a.getUniformLocation(s,"uTexture".concat(u)));return s}},{key:"_createVAO",value:function(){var r=[0,0,1,0,1,1,0,0,1,1,0,1];this.vertexCount=r.length/2;var a=this.maxInstances,n=this.gl,i=this.program,o=n.createVertexArray();return n.bindVertexArray(o),s0(n,"vec2",i.aPosition,r),this.transformBuffer=l0(n,a,i.aTransform),this.indexBuffer=Zt(n,a,"vec4",i.aIndex),this.vertTypeBuffer=Zt(n,a,"int",i.aVertType),this.atlasIdBuffer=Zt(n,a,"int",i.aAtlasId),this.texBuffer=Zt(n,a,"vec4",i.aTex),this.pointAPointBBuffer=Zt(n,a,"vec4",i.aPointAPointB),this.pointCPointDBuffer=Zt(n,a,"vec4",i.aPointCPointD),this.lineWidthBuffer=Zt(n,a,"vec2",i.aLineWidth),this.colorBuffer=Zt(n,a,"vec4",i.aColor),this.cornerRadiusBuffer=Zt(n,a,"vec4",i.aCornerRadius),this.borderColorBuffer=Zt(n,a,"vec4",i.aBorderColor),n.bindVertexArray(null),o}},{key:"buffers",get:function(){var r=this;return this._buffers||(this._buffers=Object.keys(this).filter(function(a){return yr(a,"Buffer")}).map(function(a){return r[a]})),this._buffers}},{key:"startFrame",value:function(r){var a=arguments.length>1&&arguments[1]!==void 0?arguments[1]:Xa.SCREEN;this.panZoomMatrix=r,this.renderTarget=a,this.batchDebugInfo=[],this.wrappedCount=0,this.simpleCount=0,this.startBatch()}},{key:"startBatch",value:function(){this.instanceCount=0,this.batchManager.startBatch()}},{key:"endFrame",value:function(){this.endBatch()}},{key:"_isVisible",value:function(r,a){return r.visible()?a&&a.isVisible?a.isVisible(r):!0:!1}},{key:"drawTexture",value:function(r,a,n){var i=this.atlasManager,o=this.batchManager,s=i.getRenderTypeOpts(n);if(this._isVisible(r,s)&&!(r.isEdge()&&!this._isValidEdge(r))){if(this.renderTarget.picking&&s.getTexPickingMode){var u=s.getTexPickingMode(r);if(u===oi.IGNORE)return;if(u==oi.USE_BB){this.drawPickingRectangle(r,a,n);return}}var l=i.getAtlasInfo(r,n),f=zt(l),v;try{for(f.s();!(v=f.n()).done;){var c=v.value,h=c.atlas,d=c.tex1,g=c.tex2;o.canAddToCurrentBatch(h)||this.endBatch();for(var m=o.getAtlasIndexForBatch(h),p=0,y=[[d,!0],[g,!1]];p<y.length;p++){var b=dt(y[p],2),E=b[0],C=b[1];if(E.w!=0){var A=this.instanceCount;this.vertTypeBuffer.getView(A)[0]=is;var D=this.indexBuffer.getView(A);sa(a,D);var N=this.atlasIdBuffer.getView(A);N[0]=m;var O=this.texBuffer.getView(A);O[0]=E.x,O[1]=E.y,O[2]=E.w,O[3]=E.h;var R=this.transformBuffer.getMatrixView(A);this.setTransformMatrix(r,R,s,c,C),this.instanceCount++,C||this.wrappedCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}}}}catch(P){f.e(P)}finally{f.f()}}}},{key:"setTransformMatrix",value:function(r,a,n,i){var o=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,s=0;if(n.shapeProps&&n.shapeProps.padding&&(s=r.pstyle(n.shapeProps.padding).pfValue),i){var u=i.bb,l=i.tex1,f=i.tex2,v=l.w/(l.w+f.w);o||(v=1-v);var c=this._getAdjustedBB(u,s,o,v);this._applyTransformMatrix(a,c,n,r)}else{var h=n.getBoundingBox(r),d=this._getAdjustedBB(h,s,!0,1);this._applyTransformMatrix(a,d,n,r)}}},{key:"_applyTransformMatrix",value:function(r,a,n,i){var o,s;Uf(r);var u=n.getRotation?n.getRotation(i):0;if(u!==0){var l=n.getRotationPoint(i),f=l.x,v=l.y;$n(r,r,[f,v]),Hf(r,r,u);var c=n.getRotationOffset(i);o=c.x+(a.xOffset||0),s=c.y+(a.yOffset||0)}else o=a.x1,s=a.y1;$n(r,r,[o,s]),Ds(r,r,[a.w,a.h])}},{key:"_getAdjustedBB",value:function(r,a,n,i){var o=r.x1,s=r.y1,u=r.w,l=r.h,f=r.yOffset;a&&(o-=a,s-=a,u+=2*a,l+=2*a);var v=0,c=u*i;return n&&i<1?u=c:!n&&i<1&&(v=u-c,o+=v,u=c),{x1:o,y1:s,w:u,h:l,xOffset:v,yOffset:f}}},{key:"drawPickingRectangle",value:function(r,a,n){var i=this.atlasManager.getRenderTypeOpts(n),o=this.instanceCount;this.vertTypeBuffer.getView(o)[0]=la;var s=this.indexBuffer.getView(o);sa(a,s);var u=this.colorBuffer.getView(o);zr([0,0,0],1,u);var l=this.transformBuffer.getMatrixView(o);this.setTransformMatrix(r,l,i),this.simpleCount++,this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}},{key:"drawNode",value:function(r,a,n){var i=this.simpleShapeOptions.get(n);if(this._isVisible(r,i)){var o=i.shapeProps,s=this._getVertTypeForShape(r,o.shape);if(s===void 0||i.isSimple&&!i.isSimple(r,this.renderTarget)){this.drawTexture(r,a,n);return}var u=this.instanceCount;if(this.vertTypeBuffer.getView(u)[0]=s,s===kn||s===Va){var l=i.getBoundingBox(r),f=this._getCornerRadius(r,o.radius,l),v=this.cornerRadiusBuffer.getView(u);v[0]=f,v[1]=f,v[2]=f,v[3]=f,s===Va&&(v[0]=0,v[2]=0)}var c=this.indexBuffer.getView(u);sa(a,c);var h=this.renderTarget.picking?1:n==="node-body"?r.effectiveOpacity():1,d=this.renderTarget.picking?1:r.pstyle(o.opacity).value*h,g=r.pstyle(o.color).value,m=this.colorBuffer.getView(u);zr(g,d,m);var p=this.lineWidthBuffer.getView(u);if(p[0]=0,p[1]=0,o.border){var y=r.pstyle("border-width").value;if(y>0){var b=r.pstyle("border-color").value,E=h*r.pstyle("border-opacity").value,C=this.borderColorBuffer.getView(u);zr(b,E,C);var A=r.pstyle("border-position").value;if(A==="inside")p[0]=0,p[1]=-y;else if(A==="outside")p[0]=y,p[1]=0;else{var D=y/2;p[0]=D,p[1]=-D}}}var N=this.transformBuffer.getMatrixView(u);this.setTransformMatrix(r,N,i),this.simpleCount++,this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}}},{key:"_getVertTypeForShape",value:function(r,a){var n=r.pstyle(a).value;switch(n){case"rectangle":return la;case"ellipse":return Ga;case"roundrectangle":case"round-rectangle":return kn;case"bottom-round-rectangle":return Va;default:return}}},{key:"_getCornerRadius",value:function(r,a,n){var i=n.w,o=n.h;if(r.pstyle(a).value==="auto")return Cr(i,o);var s=r.pstyle(a).pfValue,u=i/2,l=o/2;return Math.min(s,l,u)}},{key:"drawEdgeArrow",value:function(r,a,n){if(r.visible()){var i=r._private.rscratch,o,s,u;if(n==="source"?(o=i.arrowStartX,s=i.arrowStartY,u=i.srcArrowAngle):(o=i.arrowEndX,s=i.arrowEndY,u=i.tgtArrowAngle),!(isNaN(o)||o==null||isNaN(s)||s==null||isNaN(u)||u==null)){var l=r.pstyle(n+"-arrow-shape").value;if(l!=="none"){var f=r.pstyle(n+"-arrow-color").value,v=r.pstyle("opacity").value,c=r.pstyle("line-opacity").value,h=v*c,d=r.pstyle("width").pfValue,g=r.pstyle("arrow-scale").value,m=this.r.getArrowWidth(d,g),p=this.instanceCount,y=this.transformBuffer.getMatrixView(p);Uf(y),$n(y,y,[o,s]),Ds(y,y,[m,m]),Hf(y,y,u),this.vertTypeBuffer.getView(p)[0]=os;var b=this.indexBuffer.getView(p);sa(a,b);var E=this.colorBuffer.getView(p);zr(f,h,E),this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}}}}},{key:"drawEdgeLine",value:function(r,a){if(r.visible()){var n=this._getEdgePoints(r);if(n){var i=r.pstyle("opacity").value,o=r.pstyle("line-opacity").value,s=r.pstyle("width").pfValue,u=r.pstyle("line-color").value,l=i*o;if(n.length/2+this.instanceCount>this.maxInstances&&this.endBatch(),n.length==4){var f=this.instanceCount;this.vertTypeBuffer.getView(f)[0]=qf;var v=this.indexBuffer.getView(f);sa(a,v);var c=this.colorBuffer.getView(f);zr(u,l,c);var h=this.lineWidthBuffer.getView(f);h[0]=s;var d=this.pointAPointBBuffer.getView(f);d[0]=n[0],d[1]=n[1],d[2]=n[2],d[3]=n[3],this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}else for(var g=0;g<n.length-2;g+=2){var m=this.instanceCount;this.vertTypeBuffer.getView(m)[0]=Yf;var p=this.indexBuffer.getView(m);sa(a,p);var y=this.colorBuffer.getView(m);zr(u,l,y);var b=this.lineWidthBuffer.getView(m);b[0]=s;var E=n[g-2],C=n[g-1],A=n[g],D=n[g+1],N=n[g+2],O=n[g+3],R=n[g+4],P=n[g+5];g==0&&(E=2*A-N+.001,C=2*D-O+.001),g==n.length-4&&(R=2*N-A+.001,P=2*O-D+.001);var w=this.pointAPointBBuffer.getView(m);w[0]=E,w[1]=C,w[2]=A,w[3]=D;var x=this.pointCPointDBuffer.getView(m);x[0]=N,x[1]=O,x[2]=R,x[3]=P,this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}}}}},{key:"_isValidEdge",value:function(r){var a=r._private.rscratch;return!(a.badLine||a.allpts==null||isNaN(a.allpts[0]))}},{key:"_getEdgePoints",value:function(r){var a=r._private.rscratch;if(this._isValidEdge(r)){var n=a.allpts;if(n.length==4)return n;var i=this._getNumSegments(r);return this._getCurveSegmentPoints(n,i)}}},{key:"_getNumSegments",value:function(r){var a=15;return Math.min(Math.max(a,5),this.maxInstances)}},{key:"_getCurveSegmentPoints",value:function(r,a){if(r.length==4)return r;for(var n=Array((a+1)*2),i=0;i<=a;i++)if(i==0)n[0]=r[0],n[1]=r[1];else if(i==a)n[i*2]=r[r.length-2],n[i*2+1]=r[r.length-1];else{var o=i/a;this._setCurvePoint(r,o,n,i*2)}return n}},{key:"_setCurvePoint",value:function(r,a,n,i){if(r.length<=2)n[i]=r[0],n[i+1]=r[1];else{for(var o=Array(r.length-2),s=0;s<o.length;s+=2){var u=(1-a)*r[s]+a*r[s+2],l=(1-a)*r[s+1]+a*r[s+3];o[s]=u,o[s+1]=l}return this._setCurvePoint(o,a,n,i)}}},{key:"endBatch",value:function(){var r=this.gl,a=this.vao,n=this.vertexCount,i=this.instanceCount;if(i!==0){var o=this.renderTarget.picking?this.pickingProgram:this.program;r.useProgram(o),r.bindVertexArray(a);var s=zt(this.buffers),u;try{for(s.s();!(u=s.n()).done;){var l=u.value;l.bufferSubData(i)}}catch(d){s.e(d)}finally{s.f()}for(var f=this.batchManager.getAtlases(),v=0;v<f.length;v++)f[v].bufferIfNeeded(r);for(var c=0;c<f.length;c++)r.activeTexture(r.TEXTURE0+c),r.bindTexture(r.TEXTURE_2D,f[c].texture),r.uniform1i(o.uTextures[c],c);r.uniform1f(o.uZoom,e0(this.r)),r.uniformMatrix3fv(o.uPanZoomMatrix,!1,this.panZoomMatrix),r.uniform1i(o.uAtlasSize,this.batchManager.getAtlasSize());var h=zr(this.bgColor,1);r.uniform4fv(o.uBGColor,h),r.drawArraysInstanced(r.TRIANGLES,0,n,i),r.bindVertexArray(null),r.bindTexture(r.TEXTURE_2D,null),this.debug&&this.batchDebugInfo.push({count:i,atlasCount:f.length}),this.startBatch()}}},{key:"getDebugInfo",value:function(){var r=this.atlasManager.getDebugInfo(),a=r.reduce(function(o,s){return o+s.atlasCount},0),n=this.batchDebugInfo,i=n.reduce(function(o,s){return o+s.count},0);return{atlasInfo:r,totalAtlases:a,wrappedCount:this.wrappedCount,simpleCount:this.simpleCount,batchCount:n.length,batchInfo:n,totalInstances:i}}}])})(),Mc={};Mc.initWebgl=function(t,e){var r=this,a=r.data.contexts[r.WEBGL];t.bgColor=x0(r),t.webglTexSize=Math.min(t.webglTexSize,a.getParameter(a.MAX_TEXTURE_SIZE)),t.webglTexRows=Math.min(t.webglTexRows,54),t.webglTexRowsNodes=Math.min(t.webglTexRowsNodes,54),t.webglBatchSize=Math.min(t.webglBatchSize,16384),t.webglTexPerBatch=Math.min(t.webglTexPerBatch,a.getParameter(a.MAX_TEXTURE_IMAGE_UNITS)),r.webglDebug=t.webglDebug,r.webglDebugShowAtlases=t.webglDebugShowAtlases,r.pickingFrameBuffer=u0(a),r.pickingFrameBuffer.needsDraw=!0,r.drawing=new E0(r,a,t);var n=function(v){return function(c){return r.getTextAngle(c,v)}},i=function(v){return function(c){var h=c.pstyle(v);return h&&h.value}},o=function(v){return function(c){return c.pstyle("".concat(v,"-opacity")).value>0}},s=function(v){var c=v.pstyle("text-events").strValue==="yes";return c?oi.USE_BB:oi.IGNORE},u=function(v){var c=v.position(),h=c.x,d=c.y,g=v.outerWidth(),m=v.outerHeight();return{w:g,h:m,x1:h-g/2,y1:d-m/2}};r.drawing.addAtlasCollection("node",{texRows:t.webglTexRowsNodes}),r.drawing.addAtlasCollection("label",{texRows:t.webglTexRows}),r.drawing.addTextureAtlasRenderType("node-body",{collection:"node",getKey:e.getStyleKey,getBoundingBox:e.getElementBox,drawElement:e.drawElement}),r.drawing.addSimpleShapeRenderType("node-body",{getBoundingBox:u,isSimple:r0,shapeProps:{shape:"shape",color:"background-color",opacity:"background-opacity",radius:"corner-radius",border:!0}}),r.drawing.addSimpleShapeRenderType("node-overlay",{getBoundingBox:u,isVisible:o("overlay"),shapeProps:{shape:"overlay-shape",color:"overlay-color",opacity:"overlay-opacity",padding:"overlay-padding",radius:"overlay-corner-radius"}}),r.drawing.addSimpleShapeRenderType("node-underlay",{getBoundingBox:u,isVisible:o("underlay"),shapeProps:{shape:"underlay-shape",color:"underlay-color",opacity:"underlay-opacity",padding:"underlay-padding",radius:"underlay-corner-radius"}}),r.drawing.addTextureAtlasRenderType("label",{collection:"label",getTexPickingMode:s,getKey:ss(e.getLabelKey,null),getBoundingBox:ls(e.getLabelBox,null),drawClipped:!0,drawElement:e.drawLabel,getRotation:n(null),getRotationPoint:e.getLabelRotationPoint,getRotationOffset:e.getLabelRotationOffset,isVisible:i("label")}),r.drawing.addTextureAtlasRenderType("edge-source-label",{collection:"label",getTexPickingMode:s,getKey:ss(e.getSourceLabelKey,"source"),getBoundingBox:ls(e.getSourceLabelBox,"source"),drawClipped:!0,drawElement:e.drawSourceLabel,getRotation:n("source"),getRotationPoint:e.getSourceLabelRotationPoint,getRotationOffset:e.getSourceLabelRotationOffset,isVisible:i("source-label")}),r.drawing.addTextureAtlasRenderType("edge-target-label",{collection:"label",getTexPickingMode:s,getKey:ss(e.getTargetLabelKey,"target"),getBoundingBox:ls(e.getTargetLabelBox,"target"),drawClipped:!0,drawElement:e.drawTargetLabel,getRotation:n("target"),getRotationPoint:e.getTargetLabelRotationPoint,getRotationOffset:e.getTargetLabelRotationOffset,isVisible:i("target-label")});var l=un(function(){console.log("garbage collect flag set"),r.data.gc=!0},1e4);r.onUpdateEleCalcs(function(f,v){var c=!1;v&&v.length>0&&(c|=r.drawing.invalidate(v)),c&&l()}),T0(r)};function x0(t){var e=t.cy.container(),r=e&&e.style&&e.style.backgroundColor||"white";return tv(r)}function Lc(t,e){var r=t._private.rscratch;return It(r,"labelWrapCachedLines",e)||[]}var ss=function(e,r){return function(a){var n=e(a),i=Lc(a,r);return i.length>1?i.map(function(o,s){return"".concat(n,"_").concat(s)}):n}},ls=function(e,r){return function(a,n){var i=e(a);if(typeof n=="string"){var o=n.indexOf("_");if(o>0){var s=Number(n.substring(o+1)),u=Lc(a,r),l=i.h/u.length,f=l*s,v=i.y1+f;return{x1:i.x1,w:i.w,y1:v,h:l,yOffset:f}}}return i}};function T0(t){{var e=t.render;t.render=function(i){i=i||{};var o=t.cy;t.webgl&&(o.zoom()>Ec?(C0(t),e.call(t,i)):(S0(t),Rc(t,i,Xa.SCREEN)))}}{var r=t.matchCanvasSize;t.matchCanvasSize=function(i){r.call(t,i),t.pickingFrameBuffer.setFramebufferAttachmentSizes(t.canvasWidth,t.canvasHeight),t.pickingFrameBuffer.needsDraw=!0}}t.findNearestElements=function(i,o,s,u){return R0(t,i,o)};{var a=t.invalidateCachedZSortedEles;t.invalidateCachedZSortedEles=function(){a.call(t),t.pickingFrameBuffer.needsDraw=!0}}{var n=t.notify;t.notify=function(i,o){n.call(t,i,o),i==="viewport"||i==="bounds"?t.pickingFrameBuffer.needsDraw=!0:i==="background"&&t.drawing.invalidate(o,{type:"node-body"})}}}function C0(t){var e=t.data.contexts[t.WEBGL];e.clear(e.COLOR_BUFFER_BIT|e.DEPTH_BUFFER_BIT)}function S0(t){var e=function(a){a.save(),a.setTransform(1,0,0,1,0,0),a.clearRect(0,0,t.canvasWidth,t.canvasHeight),a.restore()};e(t.data.contexts[t.NODE]),e(t.data.contexts[t.DRAG])}function D0(t){var e=t.canvasWidth,r=t.canvasHeight,a=el(t),n=a.pan,i=a.zoom,o=ns();$n(o,o,[n.x,n.y]),Ds(o,o,[i,i]);var s=ns();v0(s,e,r);var u=ns();return f0(u,s,o),u}function Nc(t,e){var r=t.canvasWidth,a=t.canvasHeight,n=el(t),i=n.pan,o=n.zoom;e.setTransform(1,0,0,1,0,0),e.clearRect(0,0,r,a),e.translate(i.x,i.y),e.scale(o,o)}function A0(t,e){t.drawSelectionRectangle(e,function(r){return Nc(t,r)})}function M0(t){var e=t.data.contexts[t.NODE];e.save(),Nc(t,e),e.strokeStyle="rgba(0, 0, 0, 0.3)",e.beginPath(),e.moveTo(-1e3,0),e.lineTo(1e3,0),e.stroke(),e.beginPath(),e.moveTo(0,-1e3),e.lineTo(0,1e3),e.stroke(),e.restore()}function L0(t){var e=function(n,i,o){for(var s=n.atlasManager.getAtlasCollection(i),u=t.data.contexts[t.NODE],l=s.atlases,f=0;f<l.length;f++){var v=l[f],c=v.canvas;if(c){var h=c.width,d=c.height,g=h*f,m=c.height*o,p=.4;u.save(),u.scale(p,p),u.drawImage(c,g,m),u.strokeStyle="black",u.rect(g,m,h,d),u.stroke(),u.restore()}}},r=0;e(t.drawing,"node",r++),e(t.drawing,"label",r++)}function N0(t,e,r,a,n){var i,o,s,u,l=el(t),f=l.pan,v=l.zoom;{var c=t0(t,f,v,e,r),h=dt(c,2),d=h[0],g=h[1],m=6;i=d-m/2,o=g-m/2,s=m,u=m}if(s===0||u===0)return[];var p=t.data.contexts[t.WEBGL];p.bindFramebuffer(p.FRAMEBUFFER,t.pickingFrameBuffer),t.pickingFrameBuffer.needsDraw&&(p.viewport(0,0,p.canvas.width,p.canvas.height),Rc(t,null,Xa.PICKING),t.pickingFrameBuffer.needsDraw=!1);var y=s*u,b=new Uint8Array(y*4);p.readPixels(i,o,s,u,p.RGBA,p.UNSIGNED_BYTE,b),p.bindFramebuffer(p.FRAMEBUFFER,null);for(var E=new Set,C=0;C<y;C++){var A=b.slice(C*4,C*4+4),D=n0(A)-1;D>=0&&E.add(D)}return E}function R0(t,e,r){var a=N0(t,e,r),n=t.getCachedZSortedEles(),i,o,s=zt(a),u;try{for(s.s();!(u=s.n()).done;){var l=u.value,f=n[l];if(!i&&f.isNode()&&(i=f),!o&&f.isEdge()&&(o=f),i&&o)break}}catch(v){s.e(v)}finally{s.f()}return[i,o].filter(Boolean)}function us(t,e,r){var a=t.drawing;e+=1,r.isNode()?(a.drawNode(r,e,"node-underlay"),a.drawNode(r,e,"node-body"),a.drawTexture(r,e,"label"),a.drawNode(r,e,"node-overlay")):(a.drawEdgeLine(r,e),a.drawEdgeArrow(r,e,"source"),a.drawEdgeArrow(r,e,"target"),a.drawTexture(r,e,"label"),a.drawTexture(r,e,"edge-source-label"),a.drawTexture(r,e,"edge-target-label"))}function Rc(t,e,r){var a;t.webglDebug&&(a=performance.now());var n=t.drawing,i=0;if(r.screen&&t.data.canvasNeedsRedraw[t.SELECT_BOX]&&A0(t,e),t.data.canvasNeedsRedraw[t.NODE]||r.picking){var o=t.data.contexts[t.WEBGL];r.screen?(o.clearColor(0,0,0,0),o.enable(o.BLEND),o.blendFunc(o.ONE,o.ONE_MINUS_SRC_ALPHA)):o.disable(o.BLEND),o.clear(o.COLOR_BUFFER_BIT|o.DEPTH_BUFFER_BIT),o.viewport(0,0,o.canvas.width,o.canvas.height);var s=D0(t),u=t.getCachedZSortedEles();if(i=u.length,n.startFrame(s,r),r.screen){for(var l=0;l<u.nondrag.length;l++)us(t,l,u.nondrag[l]);for(var f=0;f<u.drag.length;f++)us(t,f,u.drag[f])}else if(r.picking)for(var v=0;v<u.length;v++)us(t,v,u[v]);n.endFrame(),r.screen&&t.webglDebugShowAtlases&&(M0(t),L0(t)),t.data.canvasNeedsRedraw[t.NODE]=!1,t.data.canvasNeedsRedraw[t.DRAG]=!1}if(t.webglDebug){var c=performance.now(),h=!1,d=Math.ceil(c-a),g=n.getDebugInfo(),m=["".concat(i," elements"),"".concat(g.totalInstances," instances"),"".concat(g.batchCount," batches"),"".concat(g.totalAtlases," atlases"),"".concat(g.wrappedCount," wrapped textures"),"".concat(g.simpleCount," simple shapes")].join(", ");if(h)console.log("WebGL (".concat(r.name,") - time ").concat(d,"ms, ").concat(m));else{console.log("WebGL (".concat(r.name,") - frame time ").concat(d,"ms")),console.log("Totals:"),console.log(" ".concat(m)),console.log("Texture Atlases Used:");var p=g.atlasInfo,y=zt(p),b;try{for(y.s();!(b=y.n()).done;){var E=b.value;console.log(" ".concat(E.type,": ").concat(E.keyCount," keys, ").concat(E.atlasCount," atlases"))}}catch(C){y.e(C)}finally{y.f()}console.log("")}}t.data.gc&&(console.log("Garbage Collect!"),t.data.gc=!1,n.gc())}var Pr={};Pr.drawPolygonPath=function(t,e,r,a,n,i){var o=a/2,s=n/2;t.beginPath&&t.beginPath(),t.moveTo(e+o*i[0],r+s*i[1]);for(var u=1;u<i.length/2;u++)t.lineTo(e+o*i[u*2],r+s*i[u*2+1]);t.closePath()};Pr.drawRoundPolygonPath=function(t,e,r,a,n,i,o){o.forEach(function(s){return vc(t,s)}),t.closePath()};Pr.drawRoundRectanglePath=function(t,e,r,a,n,i){var o=a/2,s=n/2,u=i==="auto"?Cr(a,n):Math.min(i,s,o);t.beginPath&&t.beginPath(),t.moveTo(e,r-s),t.arcTo(e+o,r-s,e+o,r,u),t.arcTo(e+o,r+s,e,r+s,u),t.arcTo(e-o,r+s,e-o,r,u),t.arcTo(e-o,r-s,e,r-s,u),t.lineTo(e,r-s),t.closePath()};Pr.drawBottomRoundRectanglePath=function(t,e,r,a,n,i){var o=a/2,s=n/2,u=i==="auto"?Cr(a,n):i;t.beginPath&&t.beginPath(),t.moveTo(e,r-s),t.lineTo(e+o,r-s),t.lineTo(e+o,r),t.arcTo(e+o,r+s,e,r+s,u),t.arcTo(e-o,r+s,e-o,r,u),t.lineTo(e-o,r-s),t.lineTo(e,r-s),t.closePath()};Pr.drawCutRectanglePath=function(t,e,r,a,n,i,o){var s=a/2,u=n/2,l=o==="auto"?Gs():o;t.beginPath&&t.beginPath(),t.moveTo(e-s+l,r-u),t.lineTo(e+s-l,r-u),t.lineTo(e+s,r-u+l),t.lineTo(e+s,r+u-l),t.lineTo(e+s-l,r+u),t.lineTo(e-s+l,r+u),t.lineTo(e-s,r+u-l),t.lineTo(e-s,r-u+l),t.closePath()};Pr.drawBarrelPath=function(t,e,r,a,n){var i=a/2,o=n/2,s=e-i,u=e+i,l=r-o,f=r+o,v=cs(a,n),c=v.widthOffset,h=v.heightOffset,d=v.ctrlPtOffsetPct*c;t.beginPath&&t.beginPath(),t.moveTo(s,l+h),t.lineTo(s,f-h),t.quadraticCurveTo(s+d,f,s+c,f),t.lineTo(u-c,f),t.quadraticCurveTo(u-d,f,u,f-h),t.lineTo(u,l+h),t.quadraticCurveTo(u-d,l,u-c,l),t.lineTo(s+c,l),t.quadraticCurveTo(s+d,l,s,l+h),t.closePath()};var Wf=Math.sin(0),Xf=Math.cos(0),As={},Ms={},Pc=Math.PI/40;for(Vr=0*Math.PI;Vr<2*Math.PI;Vr+=Pc)As[Vr]=Math.sin(Vr),Ms[Vr]=Math.cos(Vr);var Vr;Pr.drawEllipsePath=function(t,e,r,a,n){if(t.beginPath&&t.beginPath(),t.ellipse)t.ellipse(e,r,a/2,n/2,0,0,2*Math.PI);else for(var i,o,s=a/2,u=n/2,l=0*Math.PI;l<2*Math.PI;l+=Pc)i=e-s*As[l]*Wf+s*Ms[l]*Xf,o=r+u*Ms[l]*Wf+u*As[l]*Xf,l===0?t.moveTo(i,o):t.lineTo(i,o);t.closePath()};var gn={};gn.createBuffer=function(t,e){var r=document.createElement("canvas");return r.width=t,r.height=e,[r,r.getContext("2d")]};gn.bufferCanvasImage=function(t){var e=this.cy,r=e.mutableElements(),a=r.boundingBox(),n=this.findContainerClientCoords(),i=t.full?Math.ceil(a.w):n[2],o=t.full?Math.ceil(a.h):n[3],s=we(t.maxWidth)||we(t.maxHeight),u=this.getPixelRatio(),l=1;if(t.scale!==void 0)i*=t.scale,o*=t.scale,l=t.scale;else if(s){var f=1/0,v=1/0;we(t.maxWidth)&&(f=l*t.maxWidth/i),we(t.maxHeight)&&(v=l*t.maxHeight/o),l=Math.min(f,v),i*=l,o*=l}s||(i*=u,o*=u,l*=u);var c=document.createElement("canvas");c.width=i,c.height=o,c.style.width=i+"px",c.style.height=o+"px";var h=c.getContext("2d");if(i>0&&o>0){h.clearRect(0,0,i,o),h.globalCompositeOperation="source-over";var d=this.getCachedZSortedEles();if(t.full)h.translate(-a.x1*l,-a.y1*l),h.scale(l,l),this.drawElements(h,d),h.scale(1/l,1/l),h.translate(a.x1*l,a.y1*l);else{var g=e.pan(),m={x:g.x*l,y:g.y*l};l*=e.zoom(),h.translate(m.x,m.y),h.scale(l,l),this.drawElements(h,d),h.scale(1/l,1/l),h.translate(-m.x,-m.y)}t.bg&&(h.globalCompositeOperation="destination-over",h.fillStyle=t.bg,h.rect(0,0,i,o),h.fill())}return c};function P0(t,e){for(var r=atob(t),a=new ArrayBuffer(r.length),n=new Uint8Array(a),i=0;i<r.length;i++)n[i]=r.charCodeAt(i);return new Blob([a],{type:e})}function $f(t){var e=t.indexOf(",");return t.substr(e+1)}function Oc(t,e,r){var a=function(){return e.toDataURL(r,t.quality)};switch(t.output){case"blob-promise":return new Ta(function(n,i){try{e.toBlob(function(o){o!=null?n(o):i(new Error("`canvas.toBlob()` sent a null value in its callback"))},r,t.quality)}catch(o){i(o)}});case"blob":return P0($f(a()),r);case"base64":return $f(a());default:return a()}}gn.png=function(t){return Oc(t,this.bufferCanvasImage(t),"image/png")};gn.jpg=function(t){return Oc(t,this.bufferCanvasImage(t),"image/jpeg")};var Ic={};Ic.nodeShapeImpl=function(t,e,r,a,n,i,o,s){switch(t){case"ellipse":return this.drawEllipsePath(e,r,a,n,i);case"polygon":return this.drawPolygonPath(e,r,a,n,i,o);case"round-polygon":return this.drawRoundPolygonPath(e,r,a,n,i,o,s);case"roundrectangle":case"round-rectangle":return this.drawRoundRectanglePath(e,r,a,n,i,s);case"cutrectangle":case"cut-rectangle":return this.drawCutRectanglePath(e,r,a,n,i,o,s);case"bottomroundrectangle":case"bottom-round-rectangle":return this.drawBottomRoundRectanglePath(e,r,a,n,i,s);case"barrel":return this.drawBarrelPath(e,r,a,n,i)}};var O0=Bc,Ge=Bc.prototype;Ge.CANVAS_LAYERS=3;Ge.SELECT_BOX=0;Ge.DRAG=1;Ge.NODE=2;Ge.WEBGL=3;Ge.CANVAS_TYPES=["2d","2d","2d","webgl2"];Ge.BUFFER_COUNT=3;Ge.TEXTURE_BUFFER=0;Ge.MOTIONBLUR_BUFFER_NODE=1;Ge.MOTIONBLUR_BUFFER_DRAG=2;function Bc(t){var e=this,r=e.cy.window(),a=r.document;t.webgl&&(Ge.CANVAS_LAYERS=e.CANVAS_LAYERS=4,console.log("webgl rendering enabled")),e.data={canvases:new Array(Ge.CANVAS_LAYERS),contexts:new Array(Ge.CANVAS_LAYERS),canvasNeedsRedraw:new Array(Ge.CANVAS_LAYERS),bufferCanvases:new Array(Ge.BUFFER_COUNT),bufferContexts:new Array(Ge.CANVAS_LAYERS)};var n="-webkit-tap-highlight-color",i="rgba(0,0,0,0)";e.data.canvasContainer=a.createElement("div");var o=e.data.canvasContainer.style;e.data.canvasContainer.style[n]=i,o.position="relative",o.zIndex="0",o.overflow="hidden";var s=t.cy.container();s.appendChild(e.data.canvasContainer),s.style[n]=i;var u={"-webkit-user-select":"none","-moz-user-select":"-moz-none","user-select":"none","-webkit-tap-highlight-color":"rgba(0,0,0,0)","outline-style":"none"};Ch()&&(u["-ms-touch-action"]="none",u["touch-action"]="none");for(var l=0;l<Ge.CANVAS_LAYERS;l++){var f=e.data.canvases[l]=a.createElement("canvas"),v=Ge.CANVAS_TYPES[l];e.data.contexts[l]=f.getContext(v),e.data.contexts[l]||nt("Could not create canvas of type "+v),Object.keys(u).forEach(function($){f.style[$]=u[$]}),f.style.position="absolute",f.setAttribute("data-id","layer"+l),f.style.zIndex=String(Ge.CANVAS_LAYERS-l),e.data.canvasContainer.appendChild(f),e.data.canvasNeedsRedraw[l]=!1}e.data.topCanvas=e.data.canvases[0],e.data.canvases[Ge.NODE].setAttribute("data-id","layer"+Ge.NODE+"-node"),e.data.canvases[Ge.SELECT_BOX].setAttribute("data-id","layer"+Ge.SELECT_BOX+"-selectbox"),e.data.canvases[Ge.DRAG].setAttribute("data-id","layer"+Ge.DRAG+"-drag"),e.data.canvases[Ge.WEBGL]&&e.data.canvases[Ge.WEBGL].setAttribute("data-id","layer"+Ge.WEBGL+"-webgl");for(var l=0;l<Ge.BUFFER_COUNT;l++)e.data.bufferCanvases[l]=a.createElement("canvas"),e.data.bufferContexts[l]=e.data.bufferCanvases[l].getContext("2d"),e.data.bufferCanvases[l].style.position="absolute",e.data.bufferCanvases[l].setAttribute("data-id","buffer"+l),e.data.bufferCanvases[l].style.zIndex=String(-l-1),e.data.bufferCanvases[l].style.visibility="hidden";e.pathsEnabled=!0;var c=Bt(),h=function(q){return{x:(q.x1+q.x2)/2,y:(q.y1+q.y2)/2}},d=function(q){return{x:-q.w/2,y:-q.h/2}},g=function(q){var K=q[0]._private,ee=K.oldBackgroundTimestamp===K.backgroundTimestamp;return!ee},m=function(q){return q[0]._private.nodeKey},p=function(q){return q[0]._private.labelStyleKey},y=function(q){return q[0]._private.sourceLabelStyleKey},b=function(q){return q[0]._private.targetLabelStyleKey},E=function(q,K,ee,ne,te){return e.drawElement(q,K,ee,!1,!1,te)},C=function(q,K,ee,ne,te){return e.drawElementText(q,K,ee,ne,"main",te)},A=function(q,K,ee,ne,te){return e.drawElementText(q,K,ee,ne,"source",te)},D=function(q,K,ee,ne,te){return e.drawElementText(q,K,ee,ne,"target",te)},N=function(q){return q.boundingBox(),q[0]._private.bodyBounds},O=function(q){return q.boundingBox(),q[0]._private.labelBounds.main||c},R=function(q){return q.boundingBox(),q[0]._private.labelBounds.source||c},P=function(q){return q.boundingBox(),q[0]._private.labelBounds.target||c},w=function(q,K){return K},x=function(q){return h(N(q))},T=function(q,K,ee){var ne=q?q+"-":"";return{x:K.x+ee.pstyle(ne+"text-margin-x").pfValue,y:K.y+ee.pstyle(ne+"text-margin-y").pfValue}},M=function(q,K,ee){var ne=q[0]._private.rscratch;return{x:ne[K],y:ne[ee]}},S=function(q){return T("",M(q,"labelX","labelY"),q)},I=function(q){return T("source",M(q,"sourceLabelX","sourceLabelY"),q)},B=function(q){return T("target",M(q,"targetLabelX","targetLabelY"),q)},V=function(q){return d(N(q))},F=function(q){return d(R(q))},k=function(q){return d(P(q))},U=function(q){var K=O(q),ee=d(O(q));if(q.isNode()){switch(wa(q.pstyle("text-halign").value)){case"left":ee.x=-K.w-(K.leftPad||0);break;case"right":ee.x=-(K.rightPad||0);break}switch(Ea(q.pstyle("text-valign").value)){case"top":ee.y=-K.h-(K.topPad||0);break;case"bottom":ee.y=-(K.botPad||0);break}}return ee},J=e.data.eleTxrCache=new qa(e,{getKey:m,doesEleInvalidateKey:g,drawElement:E,getBoundingBox:N,getRotationPoint:x,getRotationOffset:V,allowEdgeTxrCaching:!1,allowParentTxrCaching:!1}),W=e.data.lblTxrCache=new qa(e,{getKey:p,drawElement:C,getBoundingBox:O,getRotationPoint:S,getRotationOffset:U,isVisible:w}),Q=e.data.slbTxrCache=new qa(e,{getKey:y,drawElement:A,getBoundingBox:R,getRotationPoint:I,getRotationOffset:F,isVisible:w}),Z=e.data.tlbTxrCache=new qa(e,{getKey:b,drawElement:D,getBoundingBox:P,getRotationPoint:B,getRotationOffset:k,isVisible:w}),H=e.data.lyrTxrCache=new xc(e);e.onUpdateEleCalcs(function(q,K){J.invalidateElements(K),W.invalidateElements(K),Q.invalidateElements(K),Z.invalidateElements(K),H.invalidateElements(K);for(var ee=0;ee<K.length;ee++){var ne=K[ee]._private;ne.oldBackgroundTimestamp=ne.backgroundTimestamp}});var j=function(q){for(var K=0;K<q.length;K++)H.enqueueElementRefinement(q[K].ele)};J.onDequeue(j),W.onDequeue(j),Q.onDequeue(j),Z.onDequeue(j),t.webgl&&e.initWebgl(t,{getStyleKey:m,getLabelKey:p,getSourceLabelKey:y,getTargetLabelKey:b,drawElement:E,drawLabel:C,drawSourceLabel:A,drawTargetLabel:D,getElementBox:N,getLabelBox:O,getSourceLabelBox:R,getTargetLabelBox:P,getElementRotationPoint:x,getElementRotationOffset:V,getLabelRotationPoint:S,getSourceLabelRotationPoint:I,getTargetLabelRotationPoint:B,getLabelRotationOffset:U,getSourceLabelRotationOffset:F,getTargetLabelRotationOffset:k})}Ge.redrawHint=function(t,e){var r=this;switch(t){case"eles":r.data.canvasNeedsRedraw[Ge.NODE]=e;break;case"drag":r.data.canvasNeedsRedraw[Ge.DRAG]=e;break;case"select":r.data.canvasNeedsRedraw[Ge.SELECT_BOX]=e;break;case"gc":r.data.gc=!0;break}};var I0=typeof Path2D<"u";Ge.path2dEnabled=function(t){if(t===void 0)return this.pathsEnabled;this.pathsEnabled=!!t};Ge.usePaths=function(){return I0&&this.pathsEnabled};Ge.setImgSmoothing=function(t,e){t.imageSmoothingEnabled!=null?t.imageSmoothingEnabled=e:(t.webkitImageSmoothingEnabled=e,t.mozImageSmoothingEnabled=e,t.msImageSmoothingEnabled=e)};Ge.getImgSmoothing=function(t){return t.imageSmoothingEnabled!=null?t.imageSmoothingEnabled:t.webkitImageSmoothingEnabled||t.mozImageSmoothingEnabled||t.msImageSmoothingEnabled};Ge.makeOffscreenCanvas=function(t,e){var r;if((typeof OffscreenCanvas>"u"?"undefined":mt(OffscreenCanvas))!=="undefined")r=new OffscreenCanvas(t,e);else{var a=this.cy.window(),n=a.document;r=n.createElement("canvas"),r.width=t,r.height=e}return r};[Tc,rr,fr,js,Qr,Rr,kt,Mc,Pr,gn,Ic].forEach(function(t){Re(Ge,t)});var B0=[{name:"null",impl:lc},{name:"base",impl:bc},{name:"canvas",impl:O0}],k0=[{type:"layout",extensions:im},{type:"renderer",extensions:B0}],kc={},Fc={};function zc(t,e,r){var a=r,n=function(N){Qe("Can not register `"+e+"` for `"+t+"` since `"+N+"` already exists in the prototype and can not be overridden")};if(t==="core"){if(tn.prototype[e])return n(e);tn.prototype[e]=r}else if(t==="collection"){if(St.prototype[e])return n(e);St.prototype[e]=r}else if(t==="layout"){for(var i=function(N){this.options=N,r.call(this,N),$e(this._private)||(this._private={}),this._private.cy=N.cy,this._private.listeners=[],this.createEmitter()},o=i.prototype=Object.create(r.prototype),s=[],u=0;u<s.length;u++){var l=s[u];o[l]=o[l]||function(){return this}}o.start&&!o.run?o.run=function(){return this.start(),this}:!o.start&&o.run&&(o.start=function(){return this.run(),this});var f=r.prototype.stop;o.stop=function(){var D=this.options;if(D&&D.animate){var N=this.animations;if(N)for(var O=0;O<N.length;O++)N[O].stop()}return f?f.call(this):this.emit("layoutstop"),this},o.destroy||(o.destroy=function(){return this}),o.cy=function(){return this._private.cy};var v=function(N){return N._private.cy},c={addEventFields:function(N,O){O.layout=N,O.cy=v(N),O.target=N},bubble:function(){return!0},parent:function(N){return v(N)}};Re(o,{createEmitter:function(){return this._private.emitter=new mi(c,this),this},emitter:function(){return this._private.emitter},on:function(N,O){return this.emitter().on(N,O),this},one:function(N,O){return this.emitter().one(N,O),this},once:function(N,O){return this.emitter().one(N,O),this},removeListener:function(N,O){return this.emitter().removeListener(N,O),this},removeAllListeners:function(){return this.emitter().removeAllListeners(),this},emit:function(N,O){return this.emitter().emit(N,O),this}}),Ze.eventAliasesOn(o),a=i}else if(t==="renderer"&&e!=="null"&&e!=="base"){var h=Vc("renderer","base"),d=h.prototype,g=r,m=r.prototype,p=function(){h.apply(this,arguments),g.apply(this,arguments)},y=p.prototype;for(var b in d){var E=d[b],C=m[b]!=null;if(C)return n(b);y[b]=E}for(var A in m)y[A]=m[A];d.clientFunctions.forEach(function(D){y[D]=y[D]||function(){nt("Renderer does not implement `renderer."+D+"()` on its prototype")}}),a=p}else if(t==="__proto__"||t==="constructor"||t==="prototype")return nt(t+" is an illegal type to be registered, possibly lead to prototype pollutions");return rv({map:kc,keys:[t,e],value:a})}function Vc(t,e){return av({map:kc,keys:[t,e]})}function F0(t,e,r,a,n){return rv({map:Fc,keys:[t,e,r,a],value:n})}function z0(t,e,r,a){return av({map:Fc,keys:[t,e,r,a]})}var Ls=function(){if(arguments.length===2)return Vc.apply(null,arguments);if(arguments.length===3)return zc.apply(null,arguments);if(arguments.length===4)return z0.apply(null,arguments);if(arguments.length===5)return F0.apply(null,arguments);nt("Invalid extension access syntax")};tn.prototype.extension=Ls;k0.forEach(function(t){t.extensions.forEach(function(e){zc(t.type,e.name,e.impl)})});var si=function(){if(!(this instanceof si))return new si;this.length=0},_r=si.prototype;_r.instanceString=function(){return"stylesheet"};_r.selector=function(t){var e=this.length++;return this[e]={selector:t,properties:[]},this};_r.css=function(t,e){var r=this.length-1;if(Le(t))this[r].properties.push({name:t,value:e});else if($e(t))for(var a=t,n=Object.keys(a),i=0;i<n.length;i++){var o=n[i],s=a[o];if(s!=null){var u=xt.properties[o]||xt.properties[li(o)];if(u!=null){var l=u.name,f=s;this[r].properties.push({name:l,value:f})}}}return this};_r.style=_r.css;_r.generateStyle=function(t){var e=new xt(t);return this.appendToStyle(e)};_r.appendToStyle=function(t){for(var e=0;e<this.length;e++){var r=this[e],a=r.selector,n=r.properties;t.selector(a);for(var i=0;i<n.length;i++){var o=n[i];t.css(o.name,o.value)}}return t};var V0="3.34.0",lr=function(e){if(e===void 0&&(e={}),$e(e))return new tn(e);if(Le(e))return Ls.apply(Ls,arguments)};lr.use=function(t){var e=Array.prototype.slice.call(arguments,1);return e.unshift(lr),t.apply(null,e),this};lr.warnings=function(t){return fv(t)};lr.version=V0;lr.stylesheet=lr.Stylesheet=si;var _c=oh(Gc(),1);var Ma={Entity:0,Service:1,Event:1,UseCase:2,Port:3,DTO:4,VO:4,Error:4,Shared:4,Adapter:5},qc={Entity:95,Service:72,Event:60,UseCase:48,Port:30,DTO:0,VO:0,Error:0,Shared:22,Adapter:18},Yc={Entity:"barrel",Service:"rectangle",UseCase:"round-rectangle",Port:"cut-rectangle",Event:"rhomboid",DTO:"round-rectangle",VO:"round-rectangle",Error:"round-rectangle",Shared:"round-rectangle",Adapter:"round-rectangle"},ol=["Entity","Service","UseCase","Port","Event"],sl=["DTO","VO","Error"],bn=42,Wc=338,G0=15;function Uc(t){let e=0;for(let a=0;a<t.length;a++)e=e*31+t.charCodeAt(a)|0;let r=Math.abs(e*.6180339887%1);return Math.round(bn+r*(Wc-bn))}var U0=(t,e)=>{let r=Math.abs(t-e)%360;return Math.min(r,360-r)};function Xc(t){let e=[...new Set(t)].filter(i=>!La(i)).sort(),r=[],a=new Map,n=Wc-bn;for(let i of e){let o=Uc(i),s=o;for(let u=0;u<n;u++){let l=bn+(o-bn+u)%n;if(r.every(f=>U0(f,l)>=G0)){s=l;break}}r.push(s),a.set(i,s)}return i=>La(i)?0:a.get(i)??Uc(i)}var La=t=>t==="common"||t==="shared",Di=190,H0=40,q0=230,Y0=268,W0=130,Hc=34,X0=30;function $0(t){let e=new Map;for(let o of t){let s=Ma[o.component];e.set(s,[...e.get(s)??[],o])}let r=new Map,a=0;for(let o of[...e.keys()].sort((s,u)=>s-u)){let s=e.get(o),u=s.length*Y0/(2*Math.PI),l=o===0&&s.length===1?0:Math.max(a+q0,u,170);s.forEach((f,v)=>{if(l===0)r.set(f.id,[0,0]);else{let c=2*Math.PI*v/s.length-Math.PI/2;r.set(f.id,[l*Math.cos(c),l*Math.sin(c)])}}),a=l}let n=0,i=0;for(let[o,s]of r.values())n=Math.max(n,Math.abs(o)),i=Math.max(i,Math.abs(s));return{pos:r,hw:n+Di/2+Hc,hh:i+H0/2+Hc+X0/2}}function K0(t,e,r=W0){let a=new Map(t.nodes.map(c=>[c.id,c])),n=new Map;for(let c of t.edges){let h=a.get(c.src)?.domain,d=a.get(c.dst)?.domain;if(!h||!d||h===d)continue;let g=h<d?`${h}|${d}`:`${d}|${h}`;n.set(g,(n.get(g)??0)+1)}let i=c=>e.get(c)??{hw:0,hh:0},o=c=>i(c).hw*i(c).hh,s=[...e.keys()].sort((c,h)=>o(h)-o(c)),u=new Map,l=0,f=0;s.forEach((c,h)=>{if(h===0){u.set(c,[0,0]);return}l+=Math.hypot(i(c).hw,i(c).hh)*.95,f+=2.399963,u.set(c,[l*Math.cos(f),l*Math.sin(f)])});let v=c=>{let h=0;for(let d=0;d<s.length;d++){let g=s[d];for(let m=d+1;m<s.length;m++){let p=s[m],y=u.get(g),b=u.get(p),E=b[0]-y[0],C=b[1]-y[1],A=i(g).hw+i(p).hw+r-Math.abs(E),D=i(g).hh+i(p).hh+r-Math.abs(C);if(A<=0||D<=0)continue;h=Math.max(h,Math.min(A,D));let N=Math.min(A,D)*c;if(A<D){let O=E>=0?1:-1;y[0]-=O*N,b[0]+=O*N}else{let O=C>=0?1:-1;y[1]-=O*N,b[1]+=O*N}}}return h};for(let c=0;c<400;c++){for(let h=0;h<s.length;h++){let d=s[h];for(let g=h+1;g<s.length;g++){let m=s[g],p=n.get(d<m?`${d}|${m}`:`${m}|${d}`)??0,y=u.get(d),b=u.get(m),E=b[0]-y[0],C=b[1]-y[1],A=Math.hypot(E,C)||1,D=i(d).hw+i(m).hw+r-Math.abs(E),N=i(d).hh+i(m).hh+r-Math.abs(C);if(D>0&&N>0)continue;let O=-Math.min(D,N),R=Math.min(O*(p?.06*Math.log1p(p):.006),90);u.set(d,[y[0]+E/A*R,y[1]+C/A*R]),u.set(m,[b[0]-E/A*R,b[1]-C/A*R])}}v(.5);for(let h of s){let d=u.get(h);d[0]-=d[0]*.004,d[1]-=d[1]*.004}}for(let c=0;c<600&&v(.5)>.5;c++);return u}function ll(t){let e=new Map;for(let o of t.nodes)e.set(o.domain,[...e.get(o.domain)??[],o]);let r=new Map,a=new Map;for(let[o,s]of e){let u=$0(s);r.set(o,u.pos),a.set(o,{hw:u.hw,hh:u.hh})}let n=K0(t,a),i=[];for(let[o,s]of r){let[u,l]=n.get(o)??[0,0];for(let[f,[v,c]]of s)i.push({id:f,x:Math.round(u+v),y:Math.round(l+c)})}return i}var _0=Di+54,Z0=74;function Q0(t,e){let r=[...e].sort((i,o)=>Ma[i.component]-Ma[o.component]||i.name.localeCompare(o.name)),a=Math.max(1,Math.min(5,Math.ceil(Math.sqrt(r.length/2.2)))),n=Math.ceil(r.length/a);return{d:t,items:r,cols:a,w:a*_0+80,h:n*Z0+92}}function $c(t,e=3e3){let r=new Map;for(let l of t.nodes)r.set(l.domain,[...r.get(l.domain)??[],l]);let a=[...r.entries()].map(([l,f])=>Q0(l,f)).sort((l,f)=>f.items.length-l.items.length),n=e,i=[],o=0,s=0,u=0;for(let l of a)s+l.w>n&&s>0&&(o+=u+90,s=0,u=0),l.items.forEach((f,v)=>{i.push({id:f.id,x:Math.round(s+40+v%l.cols*(Di+54)+Di/2),y:Math.round(o+52+Math.floor(v/l.cols)*74)})}),s+=l.w+70,u=Math.max(u,l.h);return i}lr.use(_c.default);var vr=(t,e,r)=>`hsl(${t},${e}%,${r}%)`,He=t=>document.getElementById(t),ea=t=>Array.from(document.querySelectorAll(t)),Ue,wt,pl,Li="hex",Or=!1,jr=!1,Ai,ta=null,Jr="both",Kc,Ni,wn=()=>0;async function J0(){wt=await(await fetch("/api/graph")).json();let t=[...new Set(wt.nodes.map(a=>a.domain))];wn=Xc(t);let e=[...new Set(wt.nodes.map(a=>a.component))].sort((a,n)=>Ma[a]-Ma[n]);pl={hex:new Map(ll(wt).map(a=>[a.id,{x:a.x,y:a.y}])),grid:new Map($c(wt).map(a=>[a.id,{x:a.x,y:a.y}]))},document.title=`${wt.project} \u2014 hexwright`,He("title").textContent=wt.project,He("ref").textContent=wt.ref;let r={added:wt.nodes.filter(a=>a.status==="added").length,modified:wt.nodes.filter(a=>a.status==="modified").length,addedEdges:wt.edges.filter(a=>a.status==="added").length};(r.added||r.modified)&&(He("delta").innerHTML=`<span class="k"></span>added ${r.added} nodes \xB7 ${r.addedEdges} edges<br><span class="k2"></span>modified ${r.modified} nodes`,He("deltaBox").style.display="block"),j0(t,e),tb(),cl("bhex"),gl("core")}function j0(t,e){let r=new Map;for(let a of wt.nodes)r.set(`c:${a.component}`,(r.get(`c:${a.component}`)??0)+1),r.set(`d:${a.domain}`,(r.get(`d:${a.domain}`)??0)+1);He("comps").innerHTML=e.map(a=>`<label><span class="sw" style="${eb(a)}"></span><input type=checkbox class=cf value="${a}" ${ol.includes(a)?"checked":""}>${a}<span class="n">${r.get(`c:${a}`)??0}</span></label>`).join(""),He("doms").innerHTML=t.sort((a,n)=>(r.get(`d:${n}`)??0)-(r.get(`d:${a}`)??0)).map(a=>{let n=wn(a);return`<label><span class="sw" style="background:${vr(n,La(a)?0:60,50)}"></span><input type=checkbox class=df value="${a}" checked>${a}<span class="n">${r.get(`d:${a}`)??0}</span></label>`}).join("");for(let a of ea(".cf,.df,.rf"))a.onchange=()=>Ir();He("showId").onchange=()=>Ir(),He("crossOnly").onchange=()=>Ir(),He("deltaOnly").onchange=()=>Ir()}function eb(t){let e="#8b949e";return sl.includes(t)?`border:1.4px dashed ${e};border-radius:5px`:`background:${e};${{Entity:"border-radius:6px/50%",Service:"border-radius:0",Port:"clip-path:polygon(22% 0,100% 0,100% 78%,78% 100%,0 100%,0 22%)",Event:"transform:skewX(-16deg)"}[t]??"border-radius:5px"}`}function tb(){let t=[...new Set(wt.nodes.map(n=>n.domain))].map(n=>({data:{id:`dom::${n}`,label:n,kind:"domain",hue:wn(n),sat:La(n)?0:26}})),e=wt.nodes.map(n=>({data:{...n,parent:`dom::${n.domain}`,kind:"type",hue:wn(n.domain),sat:La(n.domain)?0:qc[n.component],shape:Yc[n.component],outline:sl.includes(n.component),label:n.name},position:{...pl.hex.get(n.id)??{x:0,y:0}}})),r=wt.edges.map((n,i)=>({data:{...n,id:`e${i}`,source:n.src,target:n.dst,hue:wn(vl(n.src)?.domain??"")}}));Ue=lr({container:He("cy"),elements:[...t,...e,...r],layout:{name:"preset"},minZoom:.05,maxZoom:3,wheelSensitivity:.25,style:[{selector:'node[kind="domain"]',style:{"background-color":n=>vr(n.data("hue"),n.data("sat"),13),"background-opacity":.5,"border-width":1.5,"border-color":n=>vr(n.data("hue"),n.data("sat")+19,42),shape:"round-rectangle",label:"data(label)","text-valign":"top","font-size":21,"font-weight":"bold",color:n=>vr(n.data("hue"),n.data("sat")+29,62),"text-margin-y":-7,padding:"16px"}},{selector:'node[kind="type"]',style:{shape:"data(shape)",width:"182px",height:"32px","background-color":n=>vr(n.data("hue"),n.data("sat"),46-n.data("sat")*.07),"background-opacity":n=>n.data("outline")?0:1,label:"data(label)","font-size":11,"text-valign":"center","text-wrap":"ellipsis","text-max-width":"160px",color:n=>n.data("outline")?vr(n.data("hue"),n.data("hue")?52:0,72):"#fff","border-width":n=>n.data("outline")?1.4:1,"border-color":n=>vr(n.data("hue"),n.data("outline")?48:n.data("sat"),n.data("outline")?52:70),"border-style":n=>n.data("outline")?"dashed":"solid"}},{selector:'node[component="Entity"]',style:{"border-width":2.6,width:"190px",height:"36px","font-weight":"bold","font-size":12}},{selector:'node[component="Service"]',style:{"border-width":1.8}},{selector:"edge",style:{width:1.9,"line-color":n=>vr(n.data("hue"),n.data("crossDomain")?62:22,n.data("crossDomain")?58:46),opacity:n=>n.data("crossDomain")?.8:.62,"target-arrow-color":n=>vr(n.data("hue"),n.data("crossDomain")?62:22,n.data("crossDomain")?58:46)}},{selector:'edge[rel="DEPENDS_ON"]',style:{"line-style":"solid","curve-style":"straight","target-arrow-shape":"vee","arrow-scale":.95}},{selector:'edge[rel="REFERENCES"]',style:{"line-style":"dashed","line-dash-pattern":[2,4],width:1.4,"curve-style":"unbundled-bezier","control-point-distances":[24],"control-point-weights":[.5],"target-arrow-shape":"vee","arrow-scale":.9}},{selector:'edge[rel="IMPLEMENTS"]',style:{"line-style":"dashed","line-dash-pattern":[9,5],width:2.2,"curve-style":"unbundled-bezier","control-point-distances":[42],"control-point-weights":[.5],"target-arrow-shape":"triangle","target-arrow-fill":"hollow","arrow-scale":1.35}},{selector:'edge[rel="EXTENDS"]',style:{"line-style":"dashed","line-dash-pattern":[3,3],width:3.4,"curve-style":"unbundled-bezier","control-point-distances":[58],"control-point-weights":[.5],"target-arrow-shape":"triangle","target-arrow-fill":"hollow","arrow-scale":1.6}},{selector:"edge[?identifierOnly]",style:{"line-style":"dotted",opacity:.4}},{selector:'edge[violation != ""]',style:{"line-color":"#f85149","target-arrow-color":"#f85149",width:3.4,opacity:1,"z-index":90,label:"data(violation)","font-size":10,color:"#f85149","text-background-color":"#0e1116","text-background-opacity":.85,"text-background-padding":"3px"}},{selector:'edge[status="added"]',style:{opacity:1,"line-color":"#f0883e","target-arrow-color":"#f0883e","z-index":80}},{selector:".dim",style:{opacity:.035,"text-opacity":0}},{selector:".nb",style:{"border-width":2.4,"border-color":"#58a6ff","z-index":50}},{selector:".hi",style:{"border-width":5,"border-color":"#58a6ff","z-index":100}},{selector:"edge.sel",style:{width:5,opacity:1,"line-color":"#58a6ff","target-arrow-color":"#58a6ff","z-index":99}}]}),window.cy=Ue,new ResizeObserver(()=>{Ue.resize();let n=Ue.nodes('[kind="type"]').filter(i=>i.style("display")==="element");n.length&&Ue.fit(n,40)}).observe(He("cy")),Ue.on("tap",'node[kind="type"]',n=>dl(n.target)),Ue.on("tap","edge",n=>sb(n.target)),Ue.on("tap",n=>{let i=n.target;(n.target===Ue||i.data?.("kind")==="domain")&&hl()}),document.addEventListener("keydown",n=>{n.key==="Escape"&&hl()})}var vl=t=>wt.nodes.find(e=>e.id===t);function Ir(){let t=new Set(ea(".cf:checked").map(u=>u.value)),e=new Set(ea(".df:checked").map(u=>u.value)),r=new Set(ea(".rf:checked").map(u=>u.value)),a=He("showId").checked,n=He("crossOnly").checked,i=He("deltaOnly").checked,o=new Set;if(jr)for(let u of Ue.edges())u.data("violation")&&(o.add(u.data("source")),o.add(u.data("target")));Ue.batch(()=>{for(let l of Ue.nodes('[kind="type"]')){let f=l.data(),v=t.has(f.component)&&e.has(f.domain);v&&i&&f.status==="existing"&&(v=!1),v&&jr&&!o.has(f.id)&&(v=!1),l.style("display",v?"element":"none")}let u=l=>l.style("display")==="element";for(let l of Ue.nodes('[kind="domain"]'))l.style("display",l.children().filter(f=>u(f)).length?"element":"none");for(let l of Ue.edges()){let f=u(l.source())&&u(l.target())&&r.has(l.data("rel"));f&&!a&&l.data("identifierOnly")&&(f=!1),f&&n&&!l.data("crossDomain")&&(f=!1),f&&jr&&!l.data("violation")&&(f=!1),l.style("display",f?"element":"none")}}),rb(),Ue.nodes('[kind="type"]').filter(u=>u.style("display")==="element").length&&ab()}function rb(){let t=n=>n.style("display")==="element",e=Ue.nodes('[kind="type"]').filter(n=>t(n)).length,r=Ue.edges().filter(n=>t(n)).length,a=Ue.edges().filter(n=>t(n)&&n.data("violation")).length;He("stat").innerHTML=`Nodes <b>${e}</b>/${Ue.nodes('[kind="type"]').length} \xB7 Edges <b>${r}</b>/${Ue.edges().length}`,He("cviol").textContent=String(a);for(let n of["DEPENDS_ON","REFERENCES","IMPLEMENTS","EXTENDS"]){let i=document.getElementById(`c${n}`);i&&(i.textContent=String(Ue.edges(`[rel="${n}"]`).filter(o=>t(o)).length))}}function ab(){clearTimeout(Kc),Kc=setTimeout(Mi,110)}function Mi(){Ni?.stop(),Ni=void 0,Or?Li==="hex"?nb():ob():ib()}var ul=t=>t.style("display")==="element";function nb(){let t=new Set(Ue.nodes('[kind="type"]').filter(i=>ul(i)).map(i=>i.id())),e=new Set(Ue.edges().filter(i=>ul(i)).map(i=>i.id())),r={...wt,nodes:wt.nodes.filter(i=>t.has(i.id)),edges:wt.edges.filter((i,o)=>e.has(`e${o}`))},a=new Map(ll(r).map(i=>[i.id,i]));Ue.batch(()=>{for(let i of Ue.nodes('[kind="type"]')){let o=a.get(i.id());o&&i.position({x:o.x,y:o.y})}});let n=Ue.nodes('[kind="type"]').filter(i=>ul(i));n.length&&Ue.fit(n,40)}function ib(){let t=pl[Li];Ue.batch(()=>{for(let r of Ue.nodes('[kind="type"]')){let a=t.get(r.id());a&&r.position({x:a.x,y:a.y})}});let e=Ue.nodes('[kind="type"]').filter(r=>r.style("display")==="element");e.length&&Ue.fit(e,40)}function ob(){let t=Ue.elements().filter(r=>r.style("display")==="element"),e=t.nodes().length;e&&(Ni=t.layout({name:"fcose",quality:e<=150?"proof":e<=400?"default":"draft",numIter:e<=150?1600:e<=400?900:500,randomize:e<=150,animate:e<=250,animationDuration:400,nodeSeparation:210,idealEdgeLength:r=>r.data("crossDomain")?300:130,nodeRepulsion:34e3,gravity:.12,gravityCompound:.9,gravityRangeCompound:2.2,packComponents:!0,tile:!0,nodeDimensionsIncludeLabels:!0,stop:()=>Ue.fit(t.nodes(),60)}),Ni.run())}var cl=t=>{for(let e of["bhex","bgrid"])He(e).classList.toggle("on",e===t)};function hl(){Ue.elements().removeClass("hi dim sel nb"),He("info").style.display="none",ta=null,Jr="both"}var Vt=(t,e)=>`<tr><td>${t}</td><td>${e}</td></tr>`,fl=t=>t?'<span style="color:#f0883e">yes</span>':"no",Zc=t=>t==="added"?'<span style="color:#f0883e">added</span>':t==="modified"?'<span style="color:#a371f7">modified</span>':"existing";function dl(t){ta=t.id();let e=t.data(),r=c=>c.style("display")==="element",a=t.connectedEdges().filter(c=>r(c)),n=a.filter(c=>c.target().id()===ta),i=a.filter(c=>c.source().id()===ta),o=Jr==="in"?n:Jr==="out"?i:a,s=o.connectedNodes().difference(t);Ue.elements().removeClass("hi dim sel nb").addClass("dim"),t.removeClass("dim").addClass("hi"),s.removeClass("dim").addClass("nb"),o.removeClass("dim").addClass("sel"),s.parent().removeClass("dim"),t.parent().removeClass("dim");let u=(c,h,d)=>`<button class="dirb ${Jr===c?"on":""}" data-dir="${c}">${h} ${d}</button>`,l=(c,h,d)=>{let g=d.data();return`<div class="lk" data-goto="${g.id}"><span class="ar">${h}</span>${g.name}<span class="mut"> ${g.domain}\xB7${g.component}</span><span class="rel">${c.data("rel")==="DEPENDS_ON"?"":c.data("rel")}</span></div>`},f="";if(Jr!=="out")for(let c of n)f+=l(c,"\u2190",c.source());if(Jr!=="in")for(let c of i)f+=l(c,"\u2192",c.target());let v=e.api.length||e.props.length?`<div class="dirbar" style="display:block"><b>Public contract</b><span class="mut"> ${e.api.length} fn${e.props.length?` \xB7 ${e.props.length} prop`:""}</span></div><div class="lks">${e.api.map(c=>{let h=c.indexOf("(");return`<div class="lk"><span class="sig"><b>${c.slice(0,h)}</b>${c.slice(h)}</span></div>`}).join("")}${e.props.map(c=>`<div class="lk"><span class="sig" style="color:#6e7681">${c}</span></div>`).join("")}</div>`:"";He("info").style.display="block",He("info").innerHTML=`<div class="ih">${e.name}<span class="x">\xD7</span></div><table>${Vt("Domain",e.domain)}${Vt("Component",`${e.component} <span class="mut">${e.layer}${e.sublayer?`/${e.sublayer}`:""}</span>`)}${Vt("Kind",e.kind)}${Vt("Status",Zc(e.status))}${Vt("File",`<span class="mut">${e.file}:${e.line}</span>`)}${Vt("Id",`<span class="mut" style="word-break:break-all">${e.id}</span>`)}</table>${v}<div class="dirbar">${u("both","Both",a.length)}${u("in","\u2190 In",n.length)}${u("out","Out \u2192",i.length)}</div><div class="lks">${f||'<span class="mut">No visible connections</span>'}</div><div class="hint">Click an item to focus it \xB7 Esc to clear</div>`,Qc()}function sb(t){ta=null;let e=t.data(),r=vl(e.src),a=vl(e.dst);Ue.elements().removeClass("hi dim sel nb").addClass("dim"),t.removeClass("dim").addClass("sel"),t.connectedNodes().removeClass("dim").addClass("nb").parent().removeClass("dim");let n=e.contracts.length?`<div class="dirbar" style="display:block"><b>Contracts used</b><span class="mut"> ${e.contracts.length}/${a?.api.length??0}</span></div><div class="lks">${e.contracts.map(i=>{let o=i.indexOf("(");return`<div class="lk"><span class="sig"><b>${o>0?i.slice(0,o):i}</b>${o>0?i.slice(o):""}</span></div>`}).join("")}</div>`:'<div class="hint">No method calls \u2014 type reference only</div>';He("info").style.display="block",He("info").innerHTML=`<div class="ih">${e.rel}<span class="x">\xD7</span></div><table>${Vt("Source",`${r?.name} <span class="mut">${r?.domain}\xB7${r?.component}</span>`)}${Vt("Target",`${a?.name} <span class="mut">${a?.domain}\xB7${a?.component}</span>`)}${e.rel==="DEPENDS_ON"?Vt("Weight",`${e.weight} <span class="mut">occurrences</span>`):""}${Vt("Cross-domain",fl(e.crossDomain))}${Vt("Identifier only",fl(e.identifierOnly))}${Vt("Via signature",fl(e.viaSignature))}${e.violation?Vt("Violation",`<span style="color:#f85149">${e.violation}</span>`):""}${Vt("Status",Zc(e.status))}</table>${n}`,Qc()}function Qc(){let t=He("info").querySelector(".x");t&&(t.onclick=()=>hl());for(let e of Array.from(He("info").querySelectorAll(".dirb")))e.onclick=()=>{Jr=e.dataset.dir,ta&&dl(Ue.getElementById(ta))};for(let e of Array.from(He("info").querySelectorAll("[data-goto]")))e.onclick=()=>dl(Ue.getElementById(e.dataset.goto))}function gl(t){for(let e of ea(".cf"))e.checked=t==="core"?ol.includes(e.value):!0;for(let e of["pcore","pall"])He(e).classList.toggle("on",e===`p${t}`);Ir()}function lb(){He("pcore").onclick=()=>gl("core"),He("pall").onclick=()=>gl("all"),He("bhex").onclick=()=>{Li="hex",cl("bhex"),Mi()},He("bgrid").onclick=()=>{Li="grid",cl("bgrid"),Mi()},He("borg").onclick=()=>{Or=!Or,He("borg").classList.toggle("on",Or),Mi()},He("bviol").onclick=()=>{jr=!jr,He("bviol").classList.toggle("on",jr),jr?(Ai=Or,Or=!0):Ai!==void 0&&(Or=Ai,Ai=void 0),He("borg").classList.toggle("on",Or),Ir()},He("allDomOn").onclick=()=>{for(let t of ea(".df"))t.checked=!0;Ir()},He("allDomOff").onclick=()=>{for(let t of ea(".df"))t.checked=!1;Ir()},J0()}lb();})();
|
|
322
322
|
/*! Bundled license information:
|
|
323
323
|
|
|
324
324
|
cytoscape/dist/cytoscape.esm.mjs:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hexwright",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Design graph for hexagonal-architecture codebases. Renders what a branch changed as one picture a human can confirm at a glance, and gives a coding agent boundary verdicts it can run on itself before asking for review.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"hexagonal-architecture",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"esbuild": "^0.28.1",
|
|
62
62
|
"tsup": "^8.3.5",
|
|
63
63
|
"typescript": "^5.7.2",
|
|
64
|
-
"vitest": "^
|
|
64
|
+
"vitest": "^4.1.10"
|
|
65
65
|
},
|
|
66
66
|
"optionalDependencies": {
|
|
67
67
|
"@resvg/resvg-js": "^2.6.2"
|
|
@@ -14,6 +14,18 @@ domain:
|
|
|
14
14
|
# which segment is the domain (0-based, after the prefix is stripped)
|
|
15
15
|
at: 0
|
|
16
16
|
|
|
17
|
+
# How an identifier is tied to the aggregate it identifies, so that a type holding
|
|
18
|
+
# another aggregate's id is drawn as REFERENCES rather than as a dependency on the
|
|
19
|
+
# id. Remove this block and no identifier is resolved.
|
|
20
|
+
identity:
|
|
21
|
+
# property = the type declaring this property owns the identifier. Structural, and
|
|
22
|
+
# it survives an aggregate whose name is not the identifier's stem — MediaId
|
|
23
|
+
# identifies MediaItem, not Media.
|
|
24
|
+
# suffix = strip the suffix from the identifier's name and look for that type.
|
|
25
|
+
# Simpler, but resolves nothing the moment the two names diverge.
|
|
26
|
+
from: property
|
|
27
|
+
property: id
|
|
28
|
+
|
|
17
29
|
# Path fragments to exclude from analysis
|
|
18
30
|
exclude:
|
|
19
31
|
- /config/
|