@r0kshan/cairn 1.0.0-RC13 → 1.0.0-RC15
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 +87 -21
- package/THIRD-PARTY-NOTICES.md +311 -7
- package/bin/cairn.mjs +1855 -677
- package/dist/cairn.mjs +1539 -611
- package/licenses/Apache-2.0.txt +73 -0
- package/licenses/BSD-3-Clause.txt +11 -0
- package/licenses/CC-BY-4.0.txt +396 -0
- package/licenses/LGPL-2.1.txt +501 -0
- package/licenses/MIT-javascript-logo.js.txt +21 -0
- package/licenses/README.md +50 -0
- package/licenses/bun-LICENSE.md +84 -0
- package/licenses/simple-icons-CC0-1.0.md +30 -0
- package/package.json +3 -3
package/dist/cairn.mjs
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* cairn — Apache-2.0 — https://github.com/R0kshan/cairn
|
|
3
|
+
* Copyright 2026 Røkshan.
|
|
4
|
+
*
|
|
5
|
+
* This artifact contains third-party code and artwork:
|
|
6
|
+
*
|
|
7
|
+
* elkjs 0.12.0 — (c) 2017 Kiel University and others.
|
|
8
|
+
* Dual-licensed EPL-2.0 OR GPL-3.0-or-later; cairn elects EPL-2.0.
|
|
9
|
+
* Full text: licenses/elkjs-EPL-2.0.md — https://www.eclipse.org/legal/epl-2.0
|
|
10
|
+
*
|
|
11
|
+
* Simple Icons 16.29.0 artwork — CC0-1.0 project-wide.
|
|
12
|
+
* Six of the vendored icons carry their own terms instead — MIT,
|
|
13
|
+
* BSD-3-Clause, CC-BY-4.0 or Apache-2.0 — and are attributed individually.
|
|
14
|
+
* Full texts: licenses/
|
|
15
|
+
*
|
|
16
|
+
* Per-icon attribution and the full licence texts ship with this artifact:
|
|
17
|
+
* the package root (npm), the app directory (Scoop), or
|
|
18
|
+
* share/doc/cairn (Homebrew, install.sh). Also at
|
|
19
|
+
* https://github.com/R0kshan/cairn/blob/main/THIRD-PARTY-NOTICES.md
|
|
20
|
+
*/
|
|
1
21
|
var __create = Object.create;
|
|
2
22
|
var __defProp = Object.defineProperty;
|
|
3
23
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -92303,6 +92323,7 @@ function lex(src, diagnostics) {
|
|
|
92303
92323
|
|
|
92304
92324
|
// src/models/ast.ts
|
|
92305
92325
|
var ATTACH_SIDES = ["left", "right", "top", "bottom"];
|
|
92326
|
+
var ATTACH_ROLES = ["producer", "consumer"];
|
|
92306
92327
|
var defaultDiagramStyle = () => ({
|
|
92307
92328
|
crossingHops: true,
|
|
92308
92329
|
compact: false,
|
|
@@ -92369,10 +92390,6 @@ var darkPalette = {
|
|
|
92369
92390
|
chipStroke: "#b08d2a",
|
|
92370
92391
|
chipText: "#e0c068"
|
|
92371
92392
|
};
|
|
92372
|
-
var palettes = {
|
|
92373
|
-
light: lightPalette,
|
|
92374
|
-
dark: darkPalette
|
|
92375
|
-
};
|
|
92376
92393
|
var flowPalette = {
|
|
92377
92394
|
light: [
|
|
92378
92395
|
"#1f77b4",
|
|
@@ -92419,16 +92436,15 @@ var KIND_ROLE_MAP = {
|
|
|
92419
92436
|
datastore: "datastore",
|
|
92420
92437
|
queue: "datastore",
|
|
92421
92438
|
gateway: "authGateway",
|
|
92439
|
+
firewall: "firewall",
|
|
92422
92440
|
auth: "auth",
|
|
92423
92441
|
idp: "identityProvider",
|
|
92424
92442
|
site: "site",
|
|
92425
92443
|
"network-zone": "networkZone",
|
|
92426
92444
|
server: "server",
|
|
92427
|
-
"app-instance": "appInstance"
|
|
92428
|
-
"security-node": "securityNode",
|
|
92429
|
-
asset: "leaf"
|
|
92445
|
+
"app-instance": "appInstance"
|
|
92430
92446
|
};
|
|
92431
|
-
var roleForKind = (kind
|
|
92447
|
+
var roleForKind = (kind) => KIND_ROLE_MAP[kind] ?? "leaf";
|
|
92432
92448
|
var buildTheme = (spec) => {
|
|
92433
92449
|
const paletteSpec = spec.pal, accentColors = spec.accentColors;
|
|
92434
92450
|
const palette = {
|
|
@@ -92464,28 +92480,25 @@ var buildTheme = (spec) => {
|
|
|
92464
92480
|
application: containerStyle(accentColors.appF, accentColors.app),
|
|
92465
92481
|
layer: containerStyle(accentColors.goldF, accentColors.gold, false, 1),
|
|
92466
92482
|
external: containerStyle(accentColors.violetF, accentColors.violet, true),
|
|
92467
|
-
untrusted: containerStyle(accentColors.redF, accentColors.red, true, 1.3),
|
|
92468
92483
|
leaf: leafStyle(accentColors.leafF, accentColors.leafS),
|
|
92469
92484
|
datastore: leafStyle(accentColors.purpleF, accentColors.purple),
|
|
92470
92485
|
site: containerStyle(accentColors.siteF, accentColors.siteS, false, 1.4),
|
|
92471
92486
|
networkZone: containerStyle(accentColors.greenF, accentColors.green, true),
|
|
92472
92487
|
server: containerStyle(accentColors.serverF, accentColors.serverS, false, 1.5),
|
|
92473
92488
|
appInstance: leafStyle(accentColors.aiF, accentColors.aiS, 1.2),
|
|
92474
|
-
|
|
92489
|
+
// Accent keys predate the roles that read them: `auth`/`authF` is the
|
|
92490
|
+
// gateway's orange, `authn`/`authnF` the auth middleware's blue. The two
|
|
92491
|
+
// used to share the `node` orange, which is what made a gateway and an
|
|
92492
|
+
// auth middleware indistinguishable in a dense infrastructure view.
|
|
92475
92493
|
authGateway: leafStyle(accentColors.authF, accentColors.auth, 1.4),
|
|
92476
|
-
|
|
92494
|
+
firewall: leafStyle(accentColors.fwF, accentColors.fw, 1.6),
|
|
92495
|
+
auth: leafStyle(accentColors.authnF, accentColors.authn, 1.5),
|
|
92477
92496
|
identityProvider: leafStyle(accentColors.idpF, accentColors.idp)
|
|
92478
|
-
},
|
|
92479
|
-
levels: {
|
|
92480
|
-
public: containerStyle(spec.lv.public[0], spec.lv.public[1], false, 1.4),
|
|
92481
|
-
internal: containerStyle(spec.lv.internal[0], spec.lv.internal[1], false, 1.4),
|
|
92482
|
-
restricted: containerStyle(spec.lv.restricted[0], spec.lv.restricted[1], false, 1.4),
|
|
92483
|
-
secret: containerStyle(spec.lv.secret[0], spec.lv.secret[1], false, 1.4)
|
|
92484
92497
|
}
|
|
92485
92498
|
};
|
|
92486
92499
|
};
|
|
92487
|
-
var
|
|
92488
|
-
light:
|
|
92500
|
+
var THEME_SPECS = {
|
|
92501
|
+
light: {
|
|
92489
92502
|
pal: {
|
|
92490
92503
|
bg: "#ffffff",
|
|
92491
92504
|
text: "#17202c",
|
|
@@ -92533,16 +92546,15 @@ var themes = {
|
|
|
92533
92546
|
auth: "#b85a30",
|
|
92534
92547
|
authF: "#f5e6dd",
|
|
92535
92548
|
idp: "#3a8f8f",
|
|
92536
|
-
idpF: "#e0f0f0"
|
|
92537
|
-
|
|
92538
|
-
|
|
92539
|
-
|
|
92540
|
-
|
|
92541
|
-
restricted: ["#e9f2fb", "#2f7cc4"],
|
|
92542
|
-
secret: ["#efe9f7", "#7a55a8"]
|
|
92549
|
+
idpF: "#e0f0f0",
|
|
92550
|
+
fw: "#c0392b",
|
|
92551
|
+
fwF: "#fdecea",
|
|
92552
|
+
authn: "#2f6fb5",
|
|
92553
|
+
authnF: "#e8f1fb"
|
|
92543
92554
|
}
|
|
92544
|
-
}
|
|
92545
|
-
dark:
|
|
92555
|
+
},
|
|
92556
|
+
dark: {
|
|
92557
|
+
dark: true,
|
|
92546
92558
|
pal: {
|
|
92547
92559
|
bg: "#1e2530",
|
|
92548
92560
|
text: "#e6edf3",
|
|
@@ -92590,16 +92602,14 @@ var themes = {
|
|
|
92590
92602
|
auth: "#c96a4a",
|
|
92591
92603
|
authF: "#332218",
|
|
92592
92604
|
idp: "#4fafaf",
|
|
92593
|
-
idpF: "#1a2e2e"
|
|
92594
|
-
|
|
92595
|
-
|
|
92596
|
-
|
|
92597
|
-
|
|
92598
|
-
restricted: ["#1f2a37", "#4a86b8"],
|
|
92599
|
-
secret: ["#291f33", "#8a6cb0"]
|
|
92605
|
+
idpF: "#1a2e2e",
|
|
92606
|
+
fw: "#e5675a",
|
|
92607
|
+
fwF: "#33211f",
|
|
92608
|
+
authn: "#6fa8e0",
|
|
92609
|
+
authnF: "#1d2735"
|
|
92600
92610
|
}
|
|
92601
|
-
}
|
|
92602
|
-
slate:
|
|
92611
|
+
},
|
|
92612
|
+
slate: {
|
|
92603
92613
|
pal: {
|
|
92604
92614
|
bg: "#f7f9fb",
|
|
92605
92615
|
text: "#26303c",
|
|
@@ -92647,16 +92657,14 @@ var themes = {
|
|
|
92647
92657
|
auth: "#a85a30",
|
|
92648
92658
|
authF: "#f0e4dd",
|
|
92649
92659
|
idp: "#3a8f8f",
|
|
92650
|
-
idpF: "#e4f0f0"
|
|
92651
|
-
|
|
92652
|
-
|
|
92653
|
-
|
|
92654
|
-
|
|
92655
|
-
restricted: ["#e8eff6", "#3b6ea5"],
|
|
92656
|
-
secret: ["#efecf5", "#7d6ba8"]
|
|
92660
|
+
idpF: "#e4f0f0",
|
|
92661
|
+
fw: "#bd4b3c",
|
|
92662
|
+
fwF: "#f9e9e6",
|
|
92663
|
+
authn: "#3a6ea5",
|
|
92664
|
+
authnF: "#e9f0f8"
|
|
92657
92665
|
}
|
|
92658
|
-
}
|
|
92659
|
-
sand:
|
|
92666
|
+
},
|
|
92667
|
+
sand: {
|
|
92660
92668
|
pal: {
|
|
92661
92669
|
bg: "#faf6ee",
|
|
92662
92670
|
text: "#3a2f22",
|
|
@@ -92704,16 +92712,14 @@ var themes = {
|
|
|
92704
92712
|
auth: "#a85a30",
|
|
92705
92713
|
authF: "#f0e5dd",
|
|
92706
92714
|
idp: "#3a7a6f",
|
|
92707
|
-
idpF: "#e5f0ed"
|
|
92708
|
-
|
|
92709
|
-
|
|
92710
|
-
|
|
92711
|
-
|
|
92712
|
-
restricted: ["#e6f0f1", "#3f7a8c"],
|
|
92713
|
-
secret: ["#f0e8ef", "#8a5f7a"]
|
|
92715
|
+
idpF: "#e5f0ed",
|
|
92716
|
+
fw: "#b8492f",
|
|
92717
|
+
fwF: "#f8e8e0",
|
|
92718
|
+
authn: "#3a6b9a",
|
|
92719
|
+
authnF: "#e9eff7"
|
|
92714
92720
|
}
|
|
92715
|
-
}
|
|
92716
|
-
contrast:
|
|
92721
|
+
},
|
|
92722
|
+
contrast: {
|
|
92717
92723
|
pal: {
|
|
92718
92724
|
bg: "#ffffff",
|
|
92719
92725
|
text: "#000000",
|
|
@@ -92761,16 +92767,15 @@ var themes = {
|
|
|
92761
92767
|
auth: "#993a1a",
|
|
92762
92768
|
authF: "#f6e3dd",
|
|
92763
92769
|
idp: "#005a5a",
|
|
92764
|
-
idpF: "#daf0f0"
|
|
92765
|
-
|
|
92766
|
-
|
|
92767
|
-
|
|
92768
|
-
|
|
92769
|
-
restricted: ["#e0edf7", "#005a9c"],
|
|
92770
|
-
secret: ["#eee0f7", "#6a2fa0"]
|
|
92770
|
+
idpF: "#daf0f0",
|
|
92771
|
+
fw: "#a3140a",
|
|
92772
|
+
fwF: "#fbe3df",
|
|
92773
|
+
authn: "#00408f",
|
|
92774
|
+
authnF: "#dfe8fb"
|
|
92771
92775
|
}
|
|
92772
|
-
}
|
|
92773
|
-
nord:
|
|
92776
|
+
},
|
|
92777
|
+
nord: {
|
|
92778
|
+
dark: true,
|
|
92774
92779
|
pal: {
|
|
92775
92780
|
bg: "#2e3440",
|
|
92776
92781
|
text: "#eceff4",
|
|
@@ -92818,16 +92823,14 @@ var themes = {
|
|
|
92818
92823
|
auth: "#c96a4a",
|
|
92819
92824
|
authF: "#332218",
|
|
92820
92825
|
idp: "#6fafaf",
|
|
92821
|
-
idpF: "#203432"
|
|
92822
|
-
|
|
92823
|
-
|
|
92824
|
-
|
|
92825
|
-
|
|
92826
|
-
restricted: ["#2f3a44", "#81a1c1"],
|
|
92827
|
-
secret: ["#312a3a", "#a38bbd"]
|
|
92826
|
+
idpF: "#203432",
|
|
92827
|
+
fw: "#bf616a",
|
|
92828
|
+
fwF: "#3b2f34",
|
|
92829
|
+
authn: "#81a1c1",
|
|
92830
|
+
authnF: "#333c4a"
|
|
92828
92831
|
}
|
|
92829
|
-
}
|
|
92830
|
-
solarized:
|
|
92832
|
+
},
|
|
92833
|
+
solarized: {
|
|
92831
92834
|
pal: {
|
|
92832
92835
|
bg: "#fdf6e3",
|
|
92833
92836
|
text: "#586e75",
|
|
@@ -92875,34 +92878,41 @@ var themes = {
|
|
|
92875
92878
|
auth: "#b85a30",
|
|
92876
92879
|
authF: "#f5e6dd",
|
|
92877
92880
|
idp: "#2aa198",
|
|
92878
|
-
idpF: "#dff0ec"
|
|
92879
|
-
|
|
92880
|
-
|
|
92881
|
-
|
|
92882
|
-
|
|
92883
|
-
restricted: ["#e3edf3", "#268bd2"],
|
|
92884
|
-
secret: ["#e8e6f2", "#6c71c4"]
|
|
92881
|
+
idpF: "#dff0ec",
|
|
92882
|
+
fw: "#dc322f",
|
|
92883
|
+
fwF: "#f7e3dd",
|
|
92884
|
+
authn: "#268bd2",
|
|
92885
|
+
authnF: "#e3edf5"
|
|
92885
92886
|
}
|
|
92886
|
-
}
|
|
92887
|
+
}
|
|
92887
92888
|
};
|
|
92889
|
+
var themes = Object.fromEntries(
|
|
92890
|
+
Object.entries(THEME_SPECS).map(([name, spec]) => [name, buildTheme(spec)])
|
|
92891
|
+
);
|
|
92888
92892
|
var themeNames = [...Object.keys(themes), "classic", "classic-dark"];
|
|
92893
|
+
function isDarkTheme(name) {
|
|
92894
|
+
return name === "classic-dark" || THEME_SPECS[name]?.dark === true;
|
|
92895
|
+
}
|
|
92889
92896
|
function themeFor(name, view) {
|
|
92890
|
-
if (name === "classic")
|
|
92891
|
-
|
|
92892
|
-
|
|
92893
|
-
|
|
92894
|
-
|
|
92895
|
-
|
|
92896
|
-
|
|
92897
|
-
|
|
92898
|
-
|
|
92899
|
-
|
|
92900
|
-
|
|
92901
|
-
|
|
92902
|
-
|
|
92897
|
+
if (name === "classic") return { palette: lightPalette, kinds: view.defaults };
|
|
92898
|
+
if (name === "classic-dark") return { palette: darkPalette, kinds: view.defaultsDark };
|
|
92899
|
+
return applyTheme(themes[name] ?? themes.light, view);
|
|
92900
|
+
}
|
|
92901
|
+
function themeFromSpec(spec, view) {
|
|
92902
|
+
return applyTheme(buildTheme(spec), view);
|
|
92903
|
+
}
|
|
92904
|
+
function paletteFor(name) {
|
|
92905
|
+
if (name === "classic") return lightPalette;
|
|
92906
|
+
if (name === "classic-dark") return darkPalette;
|
|
92907
|
+
return themes[name]?.palette ?? lightPalette;
|
|
92908
|
+
}
|
|
92909
|
+
function paletteFromSpec(spec) {
|
|
92910
|
+
return buildTheme(spec).palette;
|
|
92911
|
+
}
|
|
92912
|
+
function applyTheme(theme, view) {
|
|
92903
92913
|
const kinds = {};
|
|
92904
|
-
for (const kind of view.kinds) kinds[kind] = theme.roles[roleForKind(kind
|
|
92905
|
-
return { palette: theme.palette, kinds
|
|
92914
|
+
for (const kind of view.kinds) kinds[kind] = theme.roles[roleForKind(kind)] ?? {};
|
|
92915
|
+
return { palette: theme.palette, kinds };
|
|
92906
92916
|
}
|
|
92907
92917
|
|
|
92908
92918
|
// src/element-tree.ts
|
|
@@ -93020,7 +93030,7 @@ function parseFlow(p, sourceToken) {
|
|
|
93020
93030
|
model.flows.push(flow);
|
|
93021
93031
|
}
|
|
93022
93032
|
function parseElement(p, sourceToken, parent) {
|
|
93023
|
-
const { matchToken, advance, reportError,
|
|
93033
|
+
const { matchToken, advance, reportError, syncToNextLine, model } = p;
|
|
93024
93034
|
if (!matchToken("id")) {
|
|
93025
93035
|
reportError(
|
|
93026
93036
|
`invalid declaration: \`${sourceToken.text}\` alone on this line`,
|
|
@@ -93040,84 +93050,66 @@ function parseElement(p, sourceToken, parent) {
|
|
|
93040
93050
|
parent: parent ?? void 0
|
|
93041
93051
|
};
|
|
93042
93052
|
if (matchToken("str")) element.label = advance().text;
|
|
93043
|
-
if (matchToken("lparen")) {
|
|
93044
|
-
advance();
|
|
93045
|
-
if (matchToken("id")) {
|
|
93046
|
-
const token = advance();
|
|
93047
|
-
element.attr = {
|
|
93048
|
-
value: token.text,
|
|
93049
|
-
span: token.span
|
|
93050
|
-
};
|
|
93051
|
-
} else
|
|
93052
|
-
reportError(
|
|
93053
|
-
"attribute value expected after `(`",
|
|
93054
|
-
lookAhead().span,
|
|
93055
|
-
'e.g. `trust-zone DMZ "DMZ" (public)`'
|
|
93056
|
-
);
|
|
93057
|
-
if (matchToken("rparen")) advance();
|
|
93058
|
-
else
|
|
93059
|
-
reportError(
|
|
93060
|
-
"`)` expected to close the attribute",
|
|
93061
|
-
lookAhead().span,
|
|
93062
|
-
'e.g. `trust-zone DMZ "DMZ" (public)`'
|
|
93063
|
-
);
|
|
93064
|
-
}
|
|
93065
93053
|
if (matchToken("lbrace")) {
|
|
93066
93054
|
advance();
|
|
93067
93055
|
p.parseElementBody(element);
|
|
93068
93056
|
}
|
|
93069
93057
|
(parent ? parent.children : model.elements).push(element);
|
|
93070
93058
|
}
|
|
93071
|
-
function splitEndpoint(token, flow,
|
|
93059
|
+
function splitEndpoint(token, flow, end) {
|
|
93072
93060
|
const dot = token.text.lastIndexOf(".");
|
|
93073
93061
|
if (dot <= 0 || dot === token.text.length - 1) return null;
|
|
93074
93062
|
const base = token.text.slice(0, dot);
|
|
93075
|
-
const
|
|
93063
|
+
const suffix = token.text.slice(dot + 1);
|
|
93076
93064
|
return {
|
|
93077
93065
|
flow,
|
|
93078
|
-
|
|
93066
|
+
end,
|
|
93079
93067
|
raw: token.text,
|
|
93080
93068
|
rawSpan: token.span,
|
|
93081
93069
|
base,
|
|
93082
93070
|
baseSpan: { line: token.span.line, col: token.span.col, len: base.length },
|
|
93083
|
-
|
|
93084
|
-
|
|
93071
|
+
suffix,
|
|
93072
|
+
suffixSpan: { line: token.span.line, col: token.span.col + dot + 1, len: suffix.length }
|
|
93085
93073
|
};
|
|
93086
93074
|
}
|
|
93087
|
-
function
|
|
93075
|
+
function resolveEndpointSuffixes(splits, model, diagnostics) {
|
|
93088
93076
|
for (const split of splits) {
|
|
93077
|
+
const isSide = ATTACH_SIDES.includes(split.suffix);
|
|
93078
|
+
const isRole = ATTACH_ROLES.includes(split.suffix);
|
|
93089
93079
|
if (model.index.has(split.raw)) {
|
|
93090
|
-
if (
|
|
93080
|
+
if (isSide || isRole)
|
|
93091
93081
|
diagnostics.push({
|
|
93092
93082
|
code: "W0571",
|
|
93093
93083
|
severity: "warning",
|
|
93094
|
-
message: `\`${split.raw}\` is a declared element, so \`.${split.
|
|
93084
|
+
message: `\`${split.raw}\` is a declared element, so \`.${split.suffix}\` is not read as ${isSide ? "an attachment side" : "a role"}`,
|
|
93095
93085
|
span: split.rawSpan,
|
|
93096
93086
|
note: "a declared id always wins over the `ID.side` reading",
|
|
93097
|
-
help: `rename the element if you meant to attach the flow to the ${split.
|
|
93087
|
+
help: isSide ? `rename the element if you meant to attach the flow to the ${split.suffix} side of \`${split.base}\`` : `rename the element if you meant \`${split.base}\` to be the ${split.suffix} of the queue at the other end`
|
|
93098
93088
|
});
|
|
93099
93089
|
continue;
|
|
93100
93090
|
}
|
|
93101
93091
|
if (!model.index.has(split.base)) continue;
|
|
93102
|
-
|
|
93103
|
-
if (!known)
|
|
93092
|
+
if (!isSide && !isRole)
|
|
93104
93093
|
diagnostics.push({
|
|
93105
93094
|
code: "E0223",
|
|
93106
93095
|
severity: "error",
|
|
93107
|
-
message: `unknown
|
|
93108
|
-
span: split.
|
|
93109
|
-
note: "
|
|
93110
|
-
help: "use `left`, `right`, `top` or `bottom
|
|
93096
|
+
message: `unknown endpoint suffix \`${split.suffix}\``,
|
|
93097
|
+
span: split.suffixSpan,
|
|
93098
|
+
note: "an endpoint names either the side it attaches to, as the diagram is read, or its role towards a queue",
|
|
93099
|
+
help: "use `left`, `right`, `top` or `bottom` \u2014 `APP.right -> DB.left` \u2014 or `producer` / `consumer`, e.g. `CAPTURE.producer -> EVENTS`"
|
|
93111
93100
|
});
|
|
93112
|
-
const side =
|
|
93113
|
-
|
|
93101
|
+
const side = isSide ? { value: split.suffix, span: split.suffixSpan } : void 0;
|
|
93102
|
+
const role = isRole ? { value: split.suffix, span: split.suffixSpan } : void 0;
|
|
93103
|
+
if (split.end === "from") {
|
|
93114
93104
|
split.flow.from = split.base;
|
|
93115
93105
|
split.flow.fromSpan = split.baseSpan;
|
|
93116
93106
|
split.flow.fromSide = side;
|
|
93107
|
+
split.flow.fromRole = role;
|
|
93117
93108
|
} else {
|
|
93118
93109
|
split.flow.to = split.base;
|
|
93119
93110
|
split.flow.toSpan = split.baseSpan;
|
|
93120
93111
|
split.flow.toSide = side;
|
|
93112
|
+
split.flow.toRole = role;
|
|
93121
93113
|
}
|
|
93122
93114
|
}
|
|
93123
93115
|
}
|
|
@@ -93146,6 +93138,34 @@ function tryOrderEntry(p, parent) {
|
|
|
93146
93138
|
parent.order = { value, span: valueToken.span };
|
|
93147
93139
|
return true;
|
|
93148
93140
|
}
|
|
93141
|
+
function tryLogoEntry(p, parent) {
|
|
93142
|
+
const { matchToken, advance, reportCoded, save, restore, syncToNextLine } = p;
|
|
93143
|
+
if (!parent || !matchToken("id", "logo")) return false;
|
|
93144
|
+
const mark = save();
|
|
93145
|
+
const keyToken = advance();
|
|
93146
|
+
if (!matchToken("colon")) {
|
|
93147
|
+
restore(mark);
|
|
93148
|
+
return false;
|
|
93149
|
+
}
|
|
93150
|
+
advance();
|
|
93151
|
+
const valueToken = matchToken("id") || matchToken("str") ? advance() : null;
|
|
93152
|
+
if (!valueToken || valueToken.text.length === 0) {
|
|
93153
|
+
reportCoded(
|
|
93154
|
+
"E0105",
|
|
93155
|
+
"`logo` expects a built-in name or a quoted file path",
|
|
93156
|
+
(valueToken ?? keyToken).span,
|
|
93157
|
+
'e.g. `logo: react`, or `logo: "./logos/acme.svg"` for your own'
|
|
93158
|
+
);
|
|
93159
|
+
syncToNextLine();
|
|
93160
|
+
return true;
|
|
93161
|
+
}
|
|
93162
|
+
parent.logo = {
|
|
93163
|
+
value: valueToken.text,
|
|
93164
|
+
source: valueToken.kind === "str" ? "file" : "builtin",
|
|
93165
|
+
span: valueToken.span
|
|
93166
|
+
};
|
|
93167
|
+
return true;
|
|
93168
|
+
}
|
|
93149
93169
|
function tryLegendBlock(p) {
|
|
93150
93170
|
const { matchToken, advance, reportError, lookAhead, skipNewlines, syncToNextLine, model } = p;
|
|
93151
93171
|
if (!matchToken("id", "legend")) return false;
|
|
@@ -93353,6 +93373,7 @@ function parse(src) {
|
|
|
93353
93373
|
}
|
|
93354
93374
|
if (tryStyleBlock(parent)) return;
|
|
93355
93375
|
if (tryOrderEntry(parser, parent)) return;
|
|
93376
|
+
if (tryLogoEntry(parser, parent)) return;
|
|
93356
93377
|
if (!parent && tryLegendBlock(parser)) return;
|
|
93357
93378
|
if (!parent && tryBusinessObject(parser)) return;
|
|
93358
93379
|
parseFlowOrElement(parser, parent);
|
|
@@ -93365,7 +93386,7 @@ function parse(src) {
|
|
|
93365
93386
|
for (const [id, element] of indexElementsById(model.elements)) {
|
|
93366
93387
|
if (!model.index.has(id)) model.index.set(id, element);
|
|
93367
93388
|
}
|
|
93368
|
-
|
|
93389
|
+
resolveEndpointSuffixes(endpointSplits, model, diagnostics);
|
|
93369
93390
|
return { model, diags: diagnostics };
|
|
93370
93391
|
}
|
|
93371
93392
|
var LINE_STYLES = /* @__PURE__ */ new Set(["solid", "dashed", "dotted"]);
|
|
@@ -93587,8 +93608,10 @@ function applyStyleEntry(entry) {
|
|
|
93587
93608
|
}
|
|
93588
93609
|
|
|
93589
93610
|
// src/views.ts
|
|
93611
|
+
var LINE_STYLES2 = ["solid", "dashed", "dotted"];
|
|
93590
93612
|
var logicalView = {
|
|
93591
93613
|
name: "logical",
|
|
93614
|
+
laneKinds: ["external"],
|
|
93592
93615
|
kinds: ["actor-group", "actor", "system", "layer", "block", "external"],
|
|
93593
93616
|
containerKinds: ["actor-group", "system", "layer", "external"],
|
|
93594
93617
|
// Logical flows carry no technical detail (flowTech* are null below), so the
|
|
@@ -93617,6 +93640,16 @@ var logicalView = {
|
|
|
93617
93640
|
},
|
|
93618
93641
|
legendFlowLabel: "Functional flow (label = exchanged data)",
|
|
93619
93642
|
legendFlowLabelFr: "Flux fonctionnel (libell\xE9 = donn\xE9es \xE9chang\xE9es)",
|
|
93643
|
+
legendLineStyles: {
|
|
93644
|
+
solid: "Direct exchange",
|
|
93645
|
+
dashed: "Asynchronous or event-driven exchange",
|
|
93646
|
+
dotted: "Dependency \u2014 no data exchanged"
|
|
93647
|
+
},
|
|
93648
|
+
legendLineStylesFr: {
|
|
93649
|
+
solid: "\xC9change direct",
|
|
93650
|
+
dashed: "\xC9change asynchrone ou \xE9v\xE9nementiel",
|
|
93651
|
+
dotted: "D\xE9pendance \u2014 aucune donn\xE9e \xE9chang\xE9e"
|
|
93652
|
+
},
|
|
93620
93653
|
flowTechRequired: null,
|
|
93621
93654
|
flowTechRecommended: null,
|
|
93622
93655
|
businessObjects: true,
|
|
@@ -93711,17 +93744,33 @@ var logicalView = {
|
|
|
93711
93744
|
};
|
|
93712
93745
|
var applicationView = {
|
|
93713
93746
|
name: "application",
|
|
93747
|
+
laneKinds: ["external"],
|
|
93748
|
+
hubKinds: ["queue"],
|
|
93714
93749
|
kinds: [
|
|
93715
93750
|
"actor-group",
|
|
93716
93751
|
"actor",
|
|
93717
93752
|
"system",
|
|
93718
93753
|
"application",
|
|
93719
93754
|
"module",
|
|
93755
|
+
"gateway",
|
|
93756
|
+
"auth",
|
|
93757
|
+
"idp",
|
|
93720
93758
|
"queue",
|
|
93721
93759
|
"datastore",
|
|
93722
93760
|
"external"
|
|
93723
93761
|
],
|
|
93724
93762
|
containerKinds: ["actor-group", "system", "application", "external"],
|
|
93763
|
+
// A logo says what a thing is built with, so it belongs to the kinds that run
|
|
93764
|
+
// code. `actor` and `actor-group` are people; `system` is a grouping whose
|
|
93765
|
+
// children carry their own stacks. `gateway`, `auth` and `idp` are left out
|
|
93766
|
+
// on purpose: they are drawn with a corner glyph, and the glyph renderer has
|
|
93767
|
+
// no logo slot — a logo on them would reserve width and draw nothing.
|
|
93768
|
+
logoKinds: ["application", "module", "queue", "datastore", "external"],
|
|
93769
|
+
// The same three kinds as the infrastructure view, drawn the same way: an API
|
|
93770
|
+
// gateway, an auth middleware and an identity provider are containers in
|
|
93771
|
+
// their own right at the application level, and the glyph is what tells them
|
|
93772
|
+
// apart from a plain `application` at a glance.
|
|
93773
|
+
glyphKinds: ["gateway", "auth", "idp"],
|
|
93725
93774
|
// C4-style `(API_REST, JSON)`: the protocol half is worth tabulating, the port is not.
|
|
93726
93775
|
// `zoneOf` walks ancestors nearest-first, so an endpoint inside an application
|
|
93727
93776
|
// still reads `Name (App)`; the system only annotates what sits directly in it.
|
|
@@ -93733,6 +93782,9 @@ var applicationView = {
|
|
|
93733
93782
|
"actor-group": 0,
|
|
93734
93783
|
system: 1,
|
|
93735
93784
|
application: 1,
|
|
93785
|
+
gateway: 1,
|
|
93786
|
+
auth: 1,
|
|
93787
|
+
idp: 1,
|
|
93736
93788
|
queue: 1,
|
|
93737
93789
|
datastore: 1,
|
|
93738
93790
|
external: 2
|
|
@@ -93743,6 +93795,9 @@ var applicationView = {
|
|
|
93743
93795
|
system: "System",
|
|
93744
93796
|
application: "Application",
|
|
93745
93797
|
module: "Application module",
|
|
93798
|
+
gateway: "Gateway / reverse proxy",
|
|
93799
|
+
auth: "Auth middleware",
|
|
93800
|
+
idp: "Identity provider (IdP)",
|
|
93746
93801
|
queue: "Message queue / broker",
|
|
93747
93802
|
datastore: "Datastore / registry",
|
|
93748
93803
|
external: "External system"
|
|
@@ -93753,6 +93808,9 @@ var applicationView = {
|
|
|
93753
93808
|
system: "Syst\xE8me",
|
|
93754
93809
|
application: "Application",
|
|
93755
93810
|
module: "Module applicatif",
|
|
93811
|
+
gateway: "Passerelle / proxy",
|
|
93812
|
+
auth: "Middleware d'authentification",
|
|
93813
|
+
idp: "Fournisseur d'identit\xE9 (IdP)",
|
|
93756
93814
|
queue: "File de messages / broker",
|
|
93757
93815
|
datastore: "Entrep\xF4t / r\xE9f\xE9rentiel",
|
|
93758
93816
|
external: "Syst\xE8me externe"
|
|
@@ -93764,6 +93822,16 @@ var applicationView = {
|
|
|
93764
93822
|
},
|
|
93765
93823
|
legendFlowLabel: "Application flow \u2014 (protocol, format) under the label",
|
|
93766
93824
|
legendFlowLabelFr: "Flux applicatif \u2014 (protocole, format) sous le libell\xE9",
|
|
93825
|
+
legendLineStyles: {
|
|
93826
|
+
solid: "Synchronous call (request / response)",
|
|
93827
|
+
dashed: "Asynchronous exchange (message, event)",
|
|
93828
|
+
dotted: "Dependency \u2014 no direct call"
|
|
93829
|
+
},
|
|
93830
|
+
legendLineStylesFr: {
|
|
93831
|
+
solid: "Appel synchrone (requ\xEAte / r\xE9ponse)",
|
|
93832
|
+
dashed: "\xC9change asynchrone (message, \xE9v\xE9nement)",
|
|
93833
|
+
dotted: "D\xE9pendance \u2014 sans appel direct"
|
|
93834
|
+
},
|
|
93767
93835
|
flowLabelRequired: null,
|
|
93768
93836
|
flowTechRequired: null,
|
|
93769
93837
|
flowTechRecommended: {
|
|
@@ -93790,7 +93858,7 @@ var applicationView = {
|
|
|
93790
93858
|
minCounts: [],
|
|
93791
93859
|
isolatedWarn: {
|
|
93792
93860
|
code: "W0510",
|
|
93793
|
-
kinds: ["module", "queue", "datastore"],
|
|
93861
|
+
kinds: ["module", "gateway", "auth", "idp", "queue", "datastore"],
|
|
93794
93862
|
message: "isolated element: no incoming or outgoing flow"
|
|
93795
93863
|
},
|
|
93796
93864
|
defaults: {
|
|
@@ -93812,6 +93880,20 @@ var applicationView = {
|
|
|
93812
93880
|
fill: "#ffffff",
|
|
93813
93881
|
stroke: { color: "#5b7a99", style: "solid", width: 1.3 }
|
|
93814
93882
|
},
|
|
93883
|
+
// Same colours as the infrastructure view's `gateway`, `auth` and `idp`: one
|
|
93884
|
+
// thing drawn one way, whichever view it appears in.
|
|
93885
|
+
gateway: {
|
|
93886
|
+
fill: "#f5e6dd",
|
|
93887
|
+
stroke: { color: "#bf5530", style: "solid", width: 1.6 }
|
|
93888
|
+
},
|
|
93889
|
+
auth: {
|
|
93890
|
+
fill: "#e8f1fb",
|
|
93891
|
+
stroke: { color: "#2f6fb5", style: "solid", width: 1.5 }
|
|
93892
|
+
},
|
|
93893
|
+
idp: {
|
|
93894
|
+
fill: "#e0f0f0",
|
|
93895
|
+
stroke: { color: "#3a8f8f", style: "solid", width: 1.3 }
|
|
93896
|
+
},
|
|
93815
93897
|
queue: {
|
|
93816
93898
|
fill: "#f3eef8",
|
|
93817
93899
|
stroke: { color: "#8a6fae", style: "solid", width: 1.3 }
|
|
@@ -93843,6 +93925,18 @@ var applicationView = {
|
|
|
93843
93925
|
fill: "#252a31",
|
|
93844
93926
|
stroke: { color: "#5f7f9e", style: "solid", width: 1.3 }
|
|
93845
93927
|
},
|
|
93928
|
+
gateway: {
|
|
93929
|
+
fill: "#332218",
|
|
93930
|
+
stroke: { color: "#c96a4a", style: "solid", width: 1.6 }
|
|
93931
|
+
},
|
|
93932
|
+
auth: {
|
|
93933
|
+
fill: "#1d2735",
|
|
93934
|
+
stroke: { color: "#6fa8e0", style: "solid", width: 1.5 }
|
|
93935
|
+
},
|
|
93936
|
+
idp: {
|
|
93937
|
+
fill: "#1a2e2e",
|
|
93938
|
+
stroke: { color: "#4fafaf", style: "solid", width: 1.3 }
|
|
93939
|
+
},
|
|
93846
93940
|
queue: {
|
|
93847
93941
|
fill: "#2a2433",
|
|
93848
93942
|
stroke: { color: "#7a5f9e", style: "solid", width: 1.3 }
|
|
@@ -93860,19 +93954,27 @@ var applicationView = {
|
|
|
93860
93954
|
};
|
|
93861
93955
|
var infrastructureView = {
|
|
93862
93956
|
name: "infrastructure",
|
|
93957
|
+
laneKinds: ["external"],
|
|
93958
|
+
hubKinds: ["queue"],
|
|
93863
93959
|
kinds: [
|
|
93864
93960
|
"actor",
|
|
93961
|
+
"device",
|
|
93865
93962
|
"site",
|
|
93866
93963
|
"network-zone",
|
|
93867
93964
|
"server",
|
|
93868
93965
|
"app-instance",
|
|
93869
93966
|
"queue",
|
|
93870
93967
|
"gateway",
|
|
93968
|
+
"firewall",
|
|
93871
93969
|
"auth",
|
|
93872
93970
|
"idp",
|
|
93873
93971
|
"external"
|
|
93874
93972
|
],
|
|
93875
93973
|
containerKinds: ["site", "network-zone", "server"],
|
|
93974
|
+
glyphKinds: ["gateway", "firewall", "auth", "idp", "device"],
|
|
93975
|
+
// A `device` is a flow origin, so it belongs on the entry side with the
|
|
93976
|
+
// actors rather than in a declaration-order band with the zones.
|
|
93977
|
+
ingressKinds: ["actor", "actor-group", "device"],
|
|
93876
93978
|
// The reference shape: the matrice des flux techniques as an EA dossier expects it.
|
|
93877
93979
|
matrix: {
|
|
93878
93980
|
zoneKinds: ["network-zone", "site"],
|
|
@@ -93883,24 +93985,28 @@ var infrastructureView = {
|
|
|
93883
93985
|
actorLegend: true,
|
|
93884
93986
|
legendNames: {
|
|
93885
93987
|
actor: "User / consumer",
|
|
93988
|
+
device: "Device / workstation",
|
|
93886
93989
|
site: "Site / data center",
|
|
93887
93990
|
"network-zone": "Network zone",
|
|
93888
93991
|
server: "Server / VM",
|
|
93889
93992
|
"app-instance": "Deployed application",
|
|
93890
93993
|
queue: "Message queue / broker",
|
|
93891
93994
|
gateway: "Gateway / reverse proxy",
|
|
93995
|
+
firewall: "Firewall",
|
|
93892
93996
|
auth: "Auth middleware",
|
|
93893
93997
|
idp: "Identity provider (IdP)",
|
|
93894
93998
|
external: "External system"
|
|
93895
93999
|
},
|
|
93896
94000
|
legendNamesFr: {
|
|
93897
94001
|
actor: "Utilisateur / consommateur",
|
|
94002
|
+
device: "Poste de travail",
|
|
93898
94003
|
site: "Site / centre de donn\xE9es",
|
|
93899
94004
|
"network-zone": "Zone r\xE9seau",
|
|
93900
94005
|
server: "Serveur / VM",
|
|
93901
94006
|
"app-instance": "Application d\xE9ploy\xE9e",
|
|
93902
94007
|
queue: "File de messages / broker",
|
|
93903
94008
|
gateway: "Passerelle / proxy",
|
|
94009
|
+
firewall: "Pare-feu",
|
|
93904
94010
|
auth: "Middleware d'authentification",
|
|
93905
94011
|
idp: "Fournisseur d'identit\xE9 (IdP)",
|
|
93906
94012
|
external: "Syst\xE8me externe"
|
|
@@ -93912,6 +94018,16 @@ var infrastructureView = {
|
|
|
93912
94018
|
},
|
|
93913
94019
|
legendFlowLabel: "Technical flow (protocol, port)",
|
|
93914
94020
|
legendFlowLabelFr: "Flux technique (protocole, port)",
|
|
94021
|
+
legendLineStyles: {
|
|
94022
|
+
solid: "Permanent link \u2014 nominal traffic",
|
|
94023
|
+
dashed: "Asynchronous or intermittent link",
|
|
94024
|
+
dotted: "Dependency \u2014 outside nominal traffic"
|
|
94025
|
+
},
|
|
94026
|
+
legendLineStylesFr: {
|
|
94027
|
+
solid: "Lien permanent \u2014 trafic nominal",
|
|
94028
|
+
dashed: "Lien asynchrone ou intermittent",
|
|
94029
|
+
dotted: "D\xE9pendance \u2014 hors trafic nominal"
|
|
94030
|
+
},
|
|
93915
94031
|
flowLabelRequired: null,
|
|
93916
94032
|
flowTechRecommended: null,
|
|
93917
94033
|
flowTechRequired: {
|
|
@@ -93945,7 +94061,7 @@ var infrastructureView = {
|
|
|
93945
94061
|
minCounts: [],
|
|
93946
94062
|
isolatedWarn: {
|
|
93947
94063
|
code: "W0510",
|
|
93948
|
-
kinds: ["app-instance", "queue", "gateway", "auth", "idp"],
|
|
94064
|
+
kinds: ["app-instance", "queue", "gateway", "firewall", "auth", "idp", "device"],
|
|
93949
94065
|
message: "isolated element: no incoming or outgoing flow"
|
|
93950
94066
|
},
|
|
93951
94067
|
defaults: {
|
|
@@ -93962,6 +94078,12 @@ var infrastructureView = {
|
|
|
93962
94078
|
fill: "#ffffff",
|
|
93963
94079
|
stroke: { color: "#55606b", style: "solid", width: 1.5 }
|
|
93964
94080
|
},
|
|
94081
|
+
// The server's grey: a workstation is hardware like a server is, and the
|
|
94082
|
+
// monitor glyph is what tells the two apart.
|
|
94083
|
+
device: {
|
|
94084
|
+
fill: "#eef0f2",
|
|
94085
|
+
stroke: { color: "#55606b", style: "solid", width: 1.3 }
|
|
94086
|
+
},
|
|
93965
94087
|
"app-instance": {
|
|
93966
94088
|
fill: "#fff7e6",
|
|
93967
94089
|
stroke: { color: "#b08d2a", style: "solid", width: 1.2 }
|
|
@@ -93974,9 +94096,13 @@ var infrastructureView = {
|
|
|
93974
94096
|
fill: "#f5e6dd",
|
|
93975
94097
|
stroke: { color: "#bf5530", style: "solid", width: 1.6 }
|
|
93976
94098
|
},
|
|
94099
|
+
firewall: {
|
|
94100
|
+
fill: "#fdecea",
|
|
94101
|
+
stroke: { color: "#c0392b", style: "solid", width: 1.6 }
|
|
94102
|
+
},
|
|
93977
94103
|
auth: {
|
|
93978
|
-
fill: "#
|
|
93979
|
-
stroke: { color: "#
|
|
94104
|
+
fill: "#e8f1fb",
|
|
94105
|
+
stroke: { color: "#2f6fb5", style: "solid", width: 1.5 }
|
|
93980
94106
|
},
|
|
93981
94107
|
idp: {
|
|
93982
94108
|
fill: "#e0f0f0",
|
|
@@ -94001,6 +94127,10 @@ var infrastructureView = {
|
|
|
94001
94127
|
fill: "#252a31",
|
|
94002
94128
|
stroke: { color: "#6b7885", style: "solid", width: 1.5 }
|
|
94003
94129
|
},
|
|
94130
|
+
device: {
|
|
94131
|
+
fill: "#242a30",
|
|
94132
|
+
stroke: { color: "#6b7885", style: "solid", width: 1.3 }
|
|
94133
|
+
},
|
|
94004
94134
|
"app-instance": {
|
|
94005
94135
|
fill: "#2e2717",
|
|
94006
94136
|
stroke: { color: "#b08d2a", style: "solid", width: 1.2 }
|
|
@@ -94013,9 +94143,13 @@ var infrastructureView = {
|
|
|
94013
94143
|
fill: "#332218",
|
|
94014
94144
|
stroke: { color: "#c96a4a", style: "solid", width: 1.6 }
|
|
94015
94145
|
},
|
|
94146
|
+
firewall: {
|
|
94147
|
+
fill: "#33211f",
|
|
94148
|
+
stroke: { color: "#e5675a", style: "solid", width: 1.6 }
|
|
94149
|
+
},
|
|
94016
94150
|
auth: {
|
|
94017
|
-
fill: "#
|
|
94018
|
-
stroke: { color: "#
|
|
94151
|
+
fill: "#1d2735",
|
|
94152
|
+
stroke: { color: "#6fa8e0", style: "solid", width: 1.5 }
|
|
94019
94153
|
},
|
|
94020
94154
|
idp: {
|
|
94021
94155
|
fill: "#1a2e2e",
|
|
@@ -94027,186 +94161,180 @@ var infrastructureView = {
|
|
|
94027
94161
|
}
|
|
94028
94162
|
}
|
|
94029
94163
|
};
|
|
94030
|
-
var
|
|
94031
|
-
|
|
94032
|
-
|
|
94033
|
-
|
|
94034
|
-
|
|
94035
|
-
|
|
94036
|
-
|
|
94037
|
-
|
|
94038
|
-
|
|
94039
|
-
|
|
94164
|
+
var views = {
|
|
94165
|
+
logical: logicalView,
|
|
94166
|
+
application: applicationView,
|
|
94167
|
+
infrastructure: infrastructureView
|
|
94168
|
+
};
|
|
94169
|
+
|
|
94170
|
+
// src/logos.ts
|
|
94171
|
+
var LOGOS = {
|
|
94172
|
+
angular: {
|
|
94173
|
+
title: "Angular",
|
|
94174
|
+
d: "M16.712 17.711H7.288l-1.204 2.916L12 24l5.916-3.373-1.204-2.916ZM14.692 0l7.832 16.855.814-12.856L14.692 0ZM9.308 0 .662 3.999l.814 12.856L9.308 0Zm-.405 13.93h6.198L12 6.396 8.903 13.93Z",
|
|
94175
|
+
license: "CC-BY-4.0",
|
|
94176
|
+
licenseUrl: "https://creativecommons.org/licenses/by/4.0/legalcode",
|
|
94177
|
+
source: "https://angular.dev/press-kit"
|
|
94040
94178
|
},
|
|
94041
|
-
|
|
94042
|
-
|
|
94043
|
-
|
|
94044
|
-
|
|
94045
|
-
|
|
94046
|
-
|
|
94047
|
-
external: "Untrusted external"
|
|
94179
|
+
apache: {
|
|
94180
|
+
title: "Apache",
|
|
94181
|
+
d: "M17.805 2.197v.066h.156v.44h.072v-.44h.156v-.066zm.9 0l-.175.353-.172-.353h-.087v.506h.067V2.3l.172.35h.045l.172-.35v.404h.066v-.506zm-4.257 1c-.204.31-.424.66-.66 1.06l-.04.062a44.457 44.457 0 00-1.265 2.29c-.187.36-.38.742-.577 1.146l2.267-.25c.66-.302.955-.578 1.242-.976a15.5 15.5 0 00.23-.342c.23-.363.46-.763.663-1.16.197-.386.37-.767.505-1.11.083-.22.15-.422.198-.6.042-.158.074-.307.1-.45-.884.15-1.965.295-2.668.33zM11.894 7.78l-.077.16c-.078.16-.157.32-.236.488-.086.18-.172.364-.26.552l-.132.287a75.265 75.265 0 00-1.427 3.3c-.163.397-.327.807-.493 1.23-.15.38-.297.765-.45 1.164l-.02.06c-.15.396-.3.802-.453 1.22l-.01.027.72-.08a.213.213 0 01-.042-.006c.863-.106 2.01-.75 2.75-1.547.342-.367.652-.8.94-1.306.213-.377.413-.795.604-1.258.168-.405.328-.843.48-1.318-.196.105-.423.18-.673.235a2.184 2.184 0 01-.273.046c.806-.31 1.314-.905 1.683-1.64a2.816 2.816 0 01-.968.428c-.06.012-.116.022-.174.03l-.043.006h.002c.278-.118.514-.248.718-.403a2.571 2.571 0 00.637-.698l.063-.104.077-.154a8.107 8.107 0 00.367-.85l.03-.088a3.04 3.04 0 00.123-.463.733.733 0 01-.094.065c-.243.145-.66.277-.996.34l.663-.074-.664.073h-.017l-.1.017c.006-.003.01-.006.017-.008l-2.265.25-.013.022zM8.27 16.45c-.117.323-.236.654-.355.992l-.005.015c-.016.046-.032.094-.05.142-.08.227-.15.432-.31.9.264.12.475.435.675.793a1.44 1.44 0 00-.466-.99c1.293.06 2.41-.27 2.99-1.217.05-.084.096-.173.14-.268-.26.333-.59.474-1.2.44 0 0-.004 0-.005.002l.004-.002c.9-.404 1.354-.79 1.754-1.433.094-.153.186-.32.28-.503-.788.81-1.702 1.04-2.664.865l-.72.078a6.43 6.43 0 00-.067.183zM15.42.112c-.376.222-1 .85-1.748 1.763l.686 1.294c.48-.687.97-1.307 1.462-1.836l.058-.062c-.02.02-.04.04-.057.062-.16.176-.644.74-1.375 1.863.703-.035 1.784-.18 2.666-.33.262-1.47-.258-2.142-.258-2.142s-.66-1.07-1.436-.61zm-3.084 6.402a40.253 40.253 0 011.306-2.26l.04-.064c.224-.352.45-.693.677-1.02l-.685-1.293-.157.192c-.197.245-.403.51-.613.79a39.853 39.853 0 00-2.016 2.97l-.022.038.893 1.763c.19-.378.38-.752.575-1.118zm-3.73 8.32c.158-.406.319-.81.483-1.225.156-.394.32-.79.484-1.19a91.133 91.133 0 011.6-3.604l.205-.424c.12-.243.237-.485.36-.724a.125.125 0 01.02-.04l-.895-1.763-.044.07c-.207.34-.414.687-.617 1.042a38.056 38.056 0 00-1.092 2.04l-.094.193a24.573 24.573 0 00-1.258 3.087 18.492 18.492 0 00-.52 1.997l.896 1.77c.117-.317.24-.638.364-.963zm-1.376-.476a13.38 13.38 0 00-.234 1.692c0 .02-.004.04-.005.06-.28-.45-1.03-.888-1.026-.884.537.778.944 1.55 1.005 2.31-.29.058-.684-.027-1.14-.195.475.436.83.556.97.588-.434.03-.89.328-1.346.67.668-.27 1.21-.38 1.596-.29-.61 1.74-1.23 3.655-1.843 5.69a.538.538 0 00.364-.354c.11-.368.84-2.786 1.978-5.965l.097-.27.028-.078c.12-.332.246-.672.374-1.02l.09-.237v-.004L7.24 14.3c-.003.02-.01.04-.012.06z",
|
|
94182
|
+
license: "Apache-2.0",
|
|
94183
|
+
licenseUrl: "https://www.apache.org/licenses/LICENSE-2.0.txt",
|
|
94184
|
+
source: "https://www.apache.org/foundation/press/kit"
|
|
94048
94185
|
},
|
|
94049
|
-
|
|
94050
|
-
|
|
94051
|
-
|
|
94052
|
-
|
|
94053
|
-
|
|
94054
|
-
|
|
94055
|
-
external: "Externe non ma\xEEtris\xE9"
|
|
94186
|
+
apachekafka: {
|
|
94187
|
+
title: "Apache Kafka",
|
|
94188
|
+
d: "M9.71 2.136a1.43 1.43 0 0 0-2.047 0h-.007a1.48 1.48 0 0 0-.421 1.042c0 .41.161.777.422 1.039l.007.007c.257.264.616.426 1.019.426.404 0 .766-.162 1.027-.426l.003-.007c.261-.262.421-.629.421-1.039 0-.408-.159-.777-.421-1.042H9.71zM8.683 22.295c.404 0 .766-.167 1.027-.429l.003-.008c.261-.261.421-.631.421-1.036 0-.41-.159-.778-.421-1.044H9.71a1.42 1.42 0 0 0-1.027-.432 1.4 1.4 0 0 0-1.02.432h-.007c-.26.266-.422.634-.422 1.044 0 .406.161.775.422 1.036l.007.008c.258.262.617.429 1.02.429zm7.89-4.462c.359-.096.683-.33.882-.684l.027-.052a1.47 1.47 0 0 0 .114-1.067 1.454 1.454 0 0 0-.675-.896l-.021-.014a1.425 1.425 0 0 0-1.078-.132c-.36.091-.684.335-.881.686-.2.349-.241.75-.146 1.119.099.363.33.691.675.896h.002c.346.203.737.239 1.101.144zm-6.405-7.342a2.083 2.083 0 0 0-1.485-.627c-.58 0-1.103.242-1.482.627-.378.385-.612.916-.612 1.507s.233 1.124.612 1.514a2.08 2.08 0 0 0 2.967 0c.379-.39.612-.923.612-1.514s-.233-1.122-.612-1.507zm-.835-2.51c.843.141 1.6.552 2.178 1.144h.004c.092.093.182.196.265.299l1.446-.851a3.176 3.176 0 0 1-.047-1.808 3.149 3.149 0 0 1 1.456-1.926l.025-.016a3.062 3.062 0 0 1 2.345-.306c.77.21 1.465.721 1.898 1.482v.002c.431.757.518 1.626.313 2.408a3.145 3.145 0 0 1-1.456 1.928l-.198.118h-.02a3.095 3.095 0 0 1-2.154.201 3.127 3.127 0 0 1-1.514-.944l-1.444.848a4.162 4.162 0 0 1 0 2.879l1.444.846c.413-.47.939-.789 1.514-.944a3.041 3.041 0 0 1 2.371.319l.048.023v.002a3.17 3.17 0 0 1 1.408 1.906 3.215 3.215 0 0 1-.313 2.405l-.026.053-.003-.005a3.147 3.147 0 0 1-1.867 1.436 3.096 3.096 0 0 1-2.371-.318v-.006a3.156 3.156 0 0 1-1.456-1.927 3.175 3.175 0 0 1 .047-1.805l-1.446-.848a3.905 3.905 0 0 1-.265.294l-.004.005a3.938 3.938 0 0 1-2.178 1.138v1.699a3.09 3.09 0 0 1 1.56.862l.002.004c.565.572.914 1.368.914 2.243 0 .873-.35 1.664-.914 2.239l-.002.009a3.1 3.1 0 0 1-2.21.931 3.1 3.1 0 0 1-2.206-.93h-.002v-.009a3.186 3.186 0 0 1-.916-2.239c0-.875.35-1.672.916-2.243v-.004h.002a3.1 3.1 0 0 1 1.558-.862v-1.699a3.926 3.926 0 0 1-2.176-1.138l-.006-.005a4.098 4.098 0 0 1-1.173-2.874c0-1.122.452-2.136 1.173-2.872h.006a3.947 3.947 0 0 1 2.176-1.144V6.289a3.137 3.137 0 0 1-1.558-.864h-.002v-.004a3.192 3.192 0 0 1-.916-2.243c0-.871.35-1.669.916-2.243l.002-.002A3.084 3.084 0 0 1 8.683 0c.861 0 1.641.355 2.21.932v.002h.002c.565.574.914 1.372.914 2.243 0 .876-.35 1.667-.914 2.243l-.002.005a3.142 3.142 0 0 1-1.56.864v1.692zm8.121-1.129l-.012-.019a1.452 1.452 0 0 0-.87-.668 1.43 1.43 0 0 0-1.103.146h.002c-.347.2-.58.529-.677.896-.095.365-.054.768.146 1.119l.007.009c.2.347.519.579.874.673.357.103.755.059 1.098-.144l.019-.009a1.47 1.47 0 0 0 .657-.885 1.493 1.493 0 0 0-.141-1.118",
|
|
94189
|
+
license: "Apache-2.0",
|
|
94190
|
+
licenseUrl: "https://www.apache.org/licenses/LICENSE-2.0.txt",
|
|
94191
|
+
source: "https://apache.org/logos"
|
|
94056
94192
|
},
|
|
94057
|
-
|
|
94058
|
-
|
|
94059
|
-
|
|
94060
|
-
|
|
94193
|
+
apachespark: {
|
|
94194
|
+
title: "Apache Spark",
|
|
94195
|
+
d: "M10.812 0c-.425.013-.845.215-1.196.605a3.593 3.593 0 00-.493.722c-.355.667-.425 1.415-.556 2.143a551.9 551.9 0 00-.726 4.087c-.027.16-.096.227-.244.273C5.83 8.386 4.06 8.94 2.3 9.514c-.387.125-.773.289-1.114.506-1.042.665-1.196 1.753-.415 2.71.346.422.79.715 1.284.936 1.1.49 2.202.976 3.3 1.47.019.01.036.013.053.019h-.004l1.306.535c0 .023.002.045 0 .073-.2 2.03-.39 4.063-.58 6.095-.04.419-.012.831.134 1.23.317.87 1.065 1.148 1.881.701.372-.204.666-.497.937-.818 1.372-1.623 2.746-3.244 4.113-4.872.111-.133.205-.15.363-.098.349.117.697.231 1.045.347h.001c.02.012.045.02.073.03l.142.042c1.248.416 2.68.775 3.929 1.19.4.132.622.164 1.045.098.311-.048.592-.062.828-.236.602-.33.995-.957.988-1.682-.005-.427-.154-.813-.35-1.186-.82-1.556-1.637-3.113-2.461-4.666-.078-.148-.076-.243.037-.375 1.381-1.615 2.756-3.236 4.133-4.855.272-.32.513-.658.653-1.058.308-.878-.09-1.57-1-1.741a2.783 2.783 0 00-1.235.069c-1.974.521-3.947 1.041-5.918 1.57-.175.047-.26.015-.355-.144a353.08 353.08 0 00-2.421-4.018 4.61 4.61 0 00-.652-.849c-.371-.37-.802-.549-1.227-.536zm.172 3.703a.592.592 0 01.189.211c.87 1.446 1.742 2.89 2.609 4.338.07.118.135.16.277.121 1.525-.41 3.052-.813 4.579-1.217.367-.098.735-.193 1.103-.289a.399.399 0 01-.1.2c-1.259 1.48-2.516 2.962-3.779 4.438-.11.13-.12.22-.04.37.937 1.803 1.768 3.309 2.498 4.76l-3.696-1.019c-.538-.18-1.077-.358-1.615-.539-.163-.055-.25-.03-.36.1-1.248 1.488-2.504 2.97-3.759 4.454a.398.398 0 01-.18.132c.035-.378.068-.757.104-1.136.149-1.572.297-3.144.451-4.716-.03-.318.117-.405-.322-.545-1.493-.593-3.346-1.321-4.816-1.905a.595.595 0 01.24-.134c1.797-.57 3.595-1.14 5.394-1.705.127-.04.199-.092.211-.233.013-.148.05-.294.076-.441.241-1.363.483-2.726.726-4.088.068-.386.14-.771.21-1.157z",
|
|
94196
|
+
license: "Apache-2.0",
|
|
94197
|
+
licenseUrl: "https://www.apache.org/licenses/LICENSE-2.0.txt",
|
|
94198
|
+
source: "https://apache.org/logos"
|
|
94061
94199
|
},
|
|
94062
|
-
|
|
94063
|
-
|
|
94064
|
-
|
|
94065
|
-
partitionByOrder: true,
|
|
94066
|
-
flowLabelRequired: {
|
|
94067
|
-
code: "E0203",
|
|
94068
|
-
message: "flow without a label",
|
|
94069
|
-
help: 'add a label describing the exchange: `A -> B : "\u2026" (TLS1.3)`'
|
|
94200
|
+
django: {
|
|
94201
|
+
title: "Django",
|
|
94202
|
+
d: "M11.146 0h3.924v18.166c-2.013.382-3.491.535-5.096.535-4.791 0-7.288-2.166-7.288-6.32 0-4.002 2.65-6.6 6.753-6.6.637 0 1.121.05 1.707.203zm0 9.143a3.894 3.894 0 00-1.325-.204c-1.988 0-3.134 1.223-3.134 3.365 0 2.09 1.096 3.236 3.109 3.236.433 0 .79-.025 1.35-.102V9.142zM21.314 6.06v9.098c0 3.134-.229 4.638-.917 5.937-.637 1.249-1.478 2.039-3.211 2.905l-3.644-1.733c1.733-.815 2.574-1.53 3.109-2.625.561-1.121.739-2.421.739-5.835V6.059h3.924zM17.39.021h3.924v4.026H17.39z"
|
|
94070
94203
|
},
|
|
94071
|
-
|
|
94072
|
-
|
|
94073
|
-
|
|
94074
|
-
kind: "trust-zone",
|
|
94075
|
-
values: SEC_LEVELS,
|
|
94076
|
-
code: "E0250",
|
|
94077
|
-
message: "trust zone without a valid sensitivity level",
|
|
94078
|
-
help: 'set a level in parentheses: `trust-zone DMZ "DMZ" (public)` \u2014 one of public, internal, restricted, secret'
|
|
94204
|
+
docker: {
|
|
94205
|
+
title: "Docker",
|
|
94206
|
+
d: "M13.983 11.078h2.119a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.119a.185.185 0 00-.185.185v1.888c0 .102.083.185.185.185m-2.954-5.43h2.118a.186.186 0 00.186-.186V3.574a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m0 2.716h2.118a.187.187 0 00.186-.186V6.29a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.887c0 .102.082.185.185.186m-2.93 0h2.12a.186.186 0 00.184-.186V6.29a.185.185 0 00-.185-.185H8.1a.185.185 0 00-.185.185v1.887c0 .102.083.185.185.186m-2.964 0h2.119a.186.186 0 00.185-.186V6.29a.185.185 0 00-.185-.185H5.136a.186.186 0 00-.186.185v1.887c0 .102.084.185.186.186m5.893 2.715h2.118a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m-2.93 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.083.185.185.185m-2.964 0h2.119a.185.185 0 00.185-.185V9.006a.185.185 0 00-.184-.186h-2.12a.186.186 0 00-.186.186v1.887c0 .102.084.185.186.185m-2.92 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.082.185.185.185M23.763 9.89c-.065-.051-.672-.51-1.954-.51-.338.001-.676.03-1.01.087-.248-1.7-1.653-2.53-1.716-2.566l-.344-.199-.226.327c-.284.438-.49.922-.612 1.43-.23.97-.09 1.882.403 2.661-.595.332-1.55.413-1.744.42H.751a.751.751 0 00-.75.748 11.376 11.376 0 00.692 4.062c.545 1.428 1.355 2.48 2.41 3.124 1.18.723 3.1 1.137 5.275 1.137.983.003 1.963-.086 2.93-.266a12.248 12.248 0 003.823-1.389c.98-.567 1.86-1.288 2.61-2.136 1.252-1.418 1.998-2.997 2.553-4.4h.221c1.372 0 2.215-.549 2.68-1.009.309-.293.55-.65.707-1.046l.098-.288Z"
|
|
94079
94207
|
},
|
|
94080
|
-
|
|
94081
|
-
|
|
94082
|
-
|
|
94083
|
-
nodeKind: "security-node",
|
|
94084
|
-
message: "unfiltered trust-boundary crossing",
|
|
94085
|
-
help: "route this flow through a `security-node` (firewall/WAF/bastion), or confirm the direct path is intended"
|
|
94208
|
+
dotnet: {
|
|
94209
|
+
title: ".NET",
|
|
94210
|
+
d: "M24 8.77h-2.468v7.565h-1.425V8.77h-2.462V7.53H24zm-6.852 7.565h-4.821V7.53h4.63v1.24h-3.205v2.494h2.953v1.234h-2.953v2.604h3.396zm-6.708 0H8.882L4.78 9.863a2.896 2.896 0 0 1-.258-.51h-.036c.032.189.048.592.048 1.21v5.772H3.157V7.53h1.659l3.965 6.32c.167.261.275.442.323.54h.024c-.04-.233-.06-.629-.06-1.185V7.529h1.372zm-8.703-.693a.868.829 0 0 1-.869.829.868.829 0 0 1-.868-.83.868.829 0 0 1 .868-.828.868.829 0 0 1 .869.829Z"
|
|
94086
94211
|
},
|
|
94087
|
-
|
|
94088
|
-
|
|
94089
|
-
|
|
94090
|
-
help: 'add the protocol/encryption on inter-zone flows: `A -> B : "\u2026" (TLS1.3)`'
|
|
94212
|
+
elasticsearch: {
|
|
94213
|
+
title: "Elasticsearch",
|
|
94214
|
+
d: "M13.394 0C8.683 0 4.609 2.716 2.644 6.667h15.641a4.77 4.77 0 0 0 3.073-1.11c.446-.375.864-.785 1.247-1.243l.001-.002A11.974 11.974 0 0 0 13.394 0zM1.804 8.889a12.009 12.009 0 0 0 0 6.222h14.7a3.111 3.111 0 1 0 0-6.222zm.84 8.444C4.61 21.283 8.684 24 13.395 24c3.701 0 7.011-1.677 9.212-4.312l-.001-.002a9.958 9.958 0 0 0-1.247-1.243 4.77 4.77 0 0 0-3.073-1.11z"
|
|
94091
94215
|
},
|
|
94092
|
-
|
|
94093
|
-
|
|
94094
|
-
|
|
94095
|
-
child: "asset",
|
|
94096
|
-
parents: ["trust-zone"],
|
|
94097
|
-
message: "sensitive asset outside any trust zone",
|
|
94098
|
-
help: "move this `asset` inside a `trust-zone`"
|
|
94099
|
-
},
|
|
94100
|
-
{
|
|
94101
|
-
code: "E0218",
|
|
94102
|
-
child: "security-node",
|
|
94103
|
-
parents: ["trust-zone"],
|
|
94104
|
-
message: "security node outside any trust zone",
|
|
94105
|
-
help: "place this `security-node` inside a `trust-zone` (typically the exposed one it protects)"
|
|
94106
|
-
},
|
|
94107
|
-
{
|
|
94108
|
-
code: "E0211",
|
|
94109
|
-
child: "actor",
|
|
94110
|
-
parents: ["actor-group"],
|
|
94111
|
-
message: "actor outside any group",
|
|
94112
|
-
help: "move this `actor` inside an `actor-group`"
|
|
94113
|
-
}
|
|
94114
|
-
],
|
|
94115
|
-
minCounts: [],
|
|
94116
|
-
isolatedWarn: {
|
|
94117
|
-
code: "W0510",
|
|
94118
|
-
kinds: ["asset"],
|
|
94119
|
-
message: "isolated element: no incoming or outgoing flow"
|
|
94216
|
+
express: {
|
|
94217
|
+
title: "Express",
|
|
94218
|
+
d: "M12.262 16.666h1.146l6.975-9.325H19.22zm9.778 1.441v.004l-4.334-5.706-.557.74 4.873 6.682H.945V4.173h9.505l5.026 6.7.574-.772-4.374-5.928h.003l-.719-.945H0v17.544h24zM10.917 8.705a3.8 3.8 0 0 0-1.292-1.183q-.796-.45-1.916-.45c-.746 0-1.37.14-1.906.424a3.76 3.76 0 0 0-1.31 1.12 4.9 4.9 0 0 0-.75 1.581 7.17 7.17 0 0 0 0 3.696c.148.567.402 1.101.75 1.573a3.5 3.5 0 0 0 1.31 1.066q.803.39 1.906.389 1.77 0 2.739-.868.966-.867 1.328-2.457h-1.139q-.271 1.084-.977 1.734-.704.651-1.952.65-.812 0-1.392-.342a3.1 3.1 0 0 1-.957-.869 3.5 3.5 0 0 1-.551-1.182 5 5 0 0 1-.17-1.133 9 9 0 0 0-.015-.286 4.5 4.5 0 0 1 .015-.829c.047-.418.147-.83.296-1.223A3.7 3.7 0 0 1 5.54 9.05a2.9 2.9 0 0 1 .922-.742q.541-.28 1.246-.28c.47 0 .869.093 1.23.28q.541.281.922.742.379.461.587 1.057t.225 1.246H5.625l.004.957h6.182a7.3 7.3 0 0 0-.18-1.924 4.9 4.9 0 0 0-.715-1.68z"
|
|
94120
94219
|
},
|
|
94121
|
-
|
|
94122
|
-
"
|
|
94123
|
-
|
|
94124
|
-
stroke: { color: "#8a8a85", style: "solid", width: 1.3 }
|
|
94125
|
-
},
|
|
94126
|
-
"security-node": {
|
|
94127
|
-
fill: "#fff7e6",
|
|
94128
|
-
stroke: { color: "#c46b2a", style: "solid", width: 1.6 }
|
|
94129
|
-
},
|
|
94130
|
-
asset: {
|
|
94131
|
-
fill: "#ffffff",
|
|
94132
|
-
stroke: { color: "#55606b", style: "solid", width: 1.3 }
|
|
94133
|
-
},
|
|
94134
|
-
"actor-group": {
|
|
94135
|
-
fill: "#eef4fb",
|
|
94136
|
-
stroke: { color: "#7a9cc4", style: "dashed", width: 1.2 }
|
|
94137
|
-
},
|
|
94138
|
-
external: {
|
|
94139
|
-
fill: "#fdecea",
|
|
94140
|
-
stroke: { color: "#d9534f", style: "dashed", width: 1.3 }
|
|
94141
|
-
},
|
|
94142
|
-
actor: {}
|
|
94220
|
+
fastapi: {
|
|
94221
|
+
title: "FastAPI",
|
|
94222
|
+
d: "M12 .0387C5.3729.0384.0003 5.3931 0 11.9988c-.001 6.6066 5.372 11.9628 12 11.9625 6.628.0003 12.001-5.3559 12-11.9625-.0003-6.6057-5.3729-11.9604-12-11.96m-.829 5.4153h7.55l-7.5805 5.3284h5.1828L5.279 18.5436q2.9466-6.5444 5.892-13.0896"
|
|
94143
94223
|
},
|
|
94144
|
-
|
|
94145
|
-
"
|
|
94146
|
-
|
|
94147
|
-
stroke: { color: "#8a8a72", style: "solid", width: 1.3 }
|
|
94148
|
-
},
|
|
94149
|
-
"security-node": {
|
|
94150
|
-
fill: "#2e2717",
|
|
94151
|
-
stroke: { color: "#c46b2a", style: "solid", width: 1.6 }
|
|
94152
|
-
},
|
|
94153
|
-
asset: {
|
|
94154
|
-
fill: "#252a31",
|
|
94155
|
-
stroke: { color: "#6b7885", style: "solid", width: 1.3 }
|
|
94156
|
-
},
|
|
94157
|
-
"actor-group": {
|
|
94158
|
-
fill: "#232a33",
|
|
94159
|
-
stroke: { color: "#5c7fa8", style: "dashed", width: 1.2 }
|
|
94160
|
-
},
|
|
94161
|
-
external: {
|
|
94162
|
-
fill: "#3a2422",
|
|
94163
|
-
stroke: { color: "#c25a54", style: "dashed", width: 1.3 }
|
|
94164
|
-
},
|
|
94165
|
-
actor: {}
|
|
94224
|
+
github: {
|
|
94225
|
+
title: "GitHub",
|
|
94226
|
+
d: "M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"
|
|
94166
94227
|
},
|
|
94167
|
-
|
|
94168
|
-
|
|
94169
|
-
|
|
94170
|
-
stroke: { color: "#d9534f", style: "solid", width: 1.4 }
|
|
94171
|
-
},
|
|
94172
|
-
internal: {
|
|
94173
|
-
fill: "#fff4e5",
|
|
94174
|
-
stroke: { color: "#e0a458", style: "solid", width: 1.4 }
|
|
94175
|
-
},
|
|
94176
|
-
restricted: {
|
|
94177
|
-
fill: "#e8f1f8",
|
|
94178
|
-
stroke: { color: "#5b8db8", style: "solid", width: 1.4 }
|
|
94179
|
-
},
|
|
94180
|
-
secret: {
|
|
94181
|
-
fill: "#ece8f5",
|
|
94182
|
-
stroke: { color: "#7a5fae", style: "solid", width: 1.4 }
|
|
94183
|
-
}
|
|
94228
|
+
gitlab: {
|
|
94229
|
+
title: "GitLab",
|
|
94230
|
+
d: "m23.6004 9.5927-.0337-.0862L20.3.9814a.851.851 0 0 0-.3362-.405.8748.8748 0 0 0-.9997.0539.8748.8748 0 0 0-.29.4399l-2.2055 6.748H7.5375l-2.2057-6.748a.8573.8573 0 0 0-.29-.4412.8748.8748 0 0 0-.9997-.0537.8585.8585 0 0 0-.3362.4049L.4332 9.5015l-.0325.0862a6.0657 6.0657 0 0 0 2.0119 7.0105l.0113.0087.03.0213 4.976 3.7264 2.462 1.8633 1.4995 1.1321a1.0085 1.0085 0 0 0 1.2197 0l1.4995-1.1321 2.4619-1.8633 5.006-3.7489.0125-.01a6.0682 6.0682 0 0 0 2.0094-7.003z"
|
|
94184
94231
|
},
|
|
94185
|
-
|
|
94186
|
-
|
|
94187
|
-
|
|
94188
|
-
|
|
94189
|
-
|
|
94190
|
-
|
|
94191
|
-
|
|
94192
|
-
|
|
94193
|
-
|
|
94194
|
-
|
|
94195
|
-
|
|
94196
|
-
|
|
94197
|
-
|
|
94198
|
-
|
|
94199
|
-
|
|
94200
|
-
|
|
94201
|
-
|
|
94232
|
+
go: {
|
|
94233
|
+
title: "Go",
|
|
94234
|
+
d: "M1.811 10.231c-.047 0-.058-.023-.035-.059l.246-.315c.023-.035.081-.058.128-.058h4.172c.046 0 .058.035.035.07l-.199.303c-.023.036-.082.07-.117.07zM.047 11.306c-.047 0-.059-.023-.035-.058l.245-.316c.023-.035.082-.058.129-.058h5.328c.047 0 .07.035.058.07l-.093.28c-.012.047-.058.07-.105.07zm2.828 1.075c-.047 0-.059-.035-.035-.07l.163-.292c.023-.035.07-.07.117-.07h2.337c.047 0 .07.035.07.082l-.023.28c0 .047-.047.082-.082.082zm12.129-2.36c-.736.187-1.239.327-1.963.514-.176.046-.187.058-.34-.117-.174-.199-.303-.327-.548-.444-.737-.362-1.45-.257-2.115.175-.795.514-1.204 1.274-1.192 2.22.011.935.654 1.706 1.577 1.835.795.105 1.46-.175 1.987-.77.105-.13.198-.27.315-.434H10.47c-.245 0-.304-.152-.222-.35.152-.362.432-.97.596-1.274a.315.315 0 01.292-.187h4.253c-.023.316-.023.631-.07.947a4.983 4.983 0 01-.958 2.29c-.841 1.11-1.94 1.8-3.33 1.986-1.145.152-2.209-.07-3.143-.77-.865-.655-1.356-1.52-1.484-2.595-.152-1.274.222-2.419.993-3.424.83-1.086 1.928-1.776 3.272-2.02 1.098-.2 2.15-.07 3.096.571.62.41 1.063.97 1.356 1.648.07.105.023.164-.117.2m3.868 6.461c-1.064-.024-2.034-.328-2.852-1.029a3.665 3.665 0 01-1.262-2.255c-.21-1.32.152-2.489.947-3.529.853-1.122 1.881-1.706 3.272-1.95 1.192-.21 2.314-.095 3.33.595.923.63 1.496 1.484 1.648 2.605.198 1.578-.257 2.863-1.344 3.962-.771.783-1.718 1.273-2.805 1.495-.315.06-.63.07-.934.106zm2.78-4.72c-.011-.153-.011-.27-.034-.387-.21-1.157-1.274-1.81-2.384-1.554-1.087.245-1.788.935-2.045 2.033-.21.912.234 1.835 1.075 2.21.643.28 1.285.244 1.905-.07.923-.48 1.425-1.228 1.484-2.233z"
|
|
94235
|
+
},
|
|
94236
|
+
googlecloud: {
|
|
94237
|
+
title: "Google Cloud",
|
|
94238
|
+
d: "M12.19 2.38a9.344 9.344 0 0 0-9.234 6.893c.053-.02-.055.013 0 0-3.875 2.551-3.922 8.11-.247 10.941l.006-.007-.007.03a6.717 6.717 0 0 0 4.077 1.356h5.173l.03.03h5.192c6.687.053 9.376-8.605 3.835-12.35a9.365 9.365 0 0 0-2.821-4.552l-.043.043.006-.05A9.344 9.344 0 0 0 12.19 2.38zm-.358 4.146c1.244-.04 2.518.368 3.486 1.15a5.186 5.186 0 0 1 1.862 4.078v.518c3.53-.07 3.53 5.262 0 5.193h-5.193l-.008.009v-.04H6.785a2.59 2.59 0 0 1-1.067-.23h.001a2.597 2.597 0 1 1 3.437-3.437l3.013-3.012A6.747 6.747 0 0 0 8.11 8.24c.018-.01.04-.026.054-.023a5.186 5.186 0 0 1 3.67-1.69z"
|
|
94239
|
+
},
|
|
94240
|
+
grafana: {
|
|
94241
|
+
title: "Grafana",
|
|
94242
|
+
d: "M23.02 10.59a8.578 8.578 0 0 0-.862-3.034 8.911 8.911 0 0 0-1.789-2.445c.337-1.342-.413-2.505-.413-2.505-1.292-.08-2.113.4-2.416.62-.052-.02-.102-.044-.154-.064-.22-.089-.446-.172-.677-.247-.231-.073-.47-.14-.711-.197a9.867 9.867 0 0 0-.875-.161C14.557.753 12.94 0 12.94 0c-1.804 1.145-2.147 2.744-2.147 2.744l-.018.093c-.098.029-.2.057-.298.088-.138.042-.275.094-.413.143-.138.055-.275.107-.41.166a8.869 8.869 0 0 0-1.557.87l-.063-.029c-2.497-.955-4.716.195-4.716.195-.203 2.658.996 4.33 1.235 4.636a11.608 11.608 0 0 0-.607 2.635C1.636 12.677.953 15.014.953 15.014c1.926 2.214 4.171 2.351 4.171 2.351.003-.002.006-.002.006-.005.285.509.615.994.986 1.446.156.19.32.371.488.548-.704 2.009.099 3.68.099 3.68 2.144.08 3.553-.937 3.849-1.173a9.784 9.784 0 0 0 3.164.501h.08l.055-.003.107-.002.103-.005.003.002c1.01 1.44 2.788 1.646 2.788 1.646 1.264-1.332 1.337-2.653 1.337-2.94v-.058c0-.02-.003-.039-.003-.06.265-.187.52-.387.758-.6a7.875 7.875 0 0 0 1.415-1.7c1.43.083 2.437-.885 2.437-.885-.236-1.49-1.085-2.216-1.264-2.354l-.018-.013-.016-.013a.217.217 0 0 1-.031-.02c.008-.092.016-.18.02-.27.011-.162.016-.323.016-.48v-.253l-.005-.098-.008-.135a1.891 1.891 0 0 0-.01-.13c-.003-.042-.008-.083-.013-.125l-.016-.124-.018-.122a6.215 6.215 0 0 0-2.032-3.73 6.015 6.015 0 0 0-3.222-1.46 6.292 6.292 0 0 0-.85-.048l-.107.002h-.063l-.044.003-.104.008a4.777 4.777 0 0 0-3.335 1.695c-.332.4-.592.84-.768 1.297a4.594 4.594 0 0 0-.312 1.817l.003.091c.005.055.007.11.013.164a3.615 3.615 0 0 0 .698 1.82 3.53 3.53 0 0 0 1.827 1.282c.33.098.66.14.971.137.039 0 .078 0 .114-.002l.063-.003c.02 0 .041-.003.062-.003.034-.002.065-.007.099-.01.007 0 .018-.003.028-.003l.031-.005.06-.008a1.18 1.18 0 0 0 .112-.02c.036-.008.072-.013.109-.024a2.634 2.634 0 0 0 .914-.415c.028-.02.056-.041.085-.065a.248.248 0 0 0 .039-.35.244.244 0 0 0-.309-.06l-.078.042c-.09.044-.184.083-.283.116a2.476 2.476 0 0 1-.475.096c-.028.003-.054.006-.083.006l-.083.002c-.026 0-.054 0-.08-.002l-.102-.006h-.012l-.024.006c-.016-.003-.031-.003-.044-.006-.031-.002-.06-.007-.091-.01a2.59 2.59 0 0 1-.724-.213 2.557 2.557 0 0 1-.667-.438 2.52 2.52 0 0 1-.805-1.475 2.306 2.306 0 0 1-.029-.444l.006-.122v-.023l.002-.031c.003-.021.003-.04.005-.06a3.163 3.163 0 0 1 1.352-2.29 3.12 3.12 0 0 1 .937-.43 2.946 2.946 0 0 1 .776-.101h.06l.07.002.045.003h.026l.07.005a4.041 4.041 0 0 1 1.635.49 3.94 3.94 0 0 1 1.602 1.662 3.77 3.77 0 0 1 .397 1.414l.005.076.003.075c.002.026.002.05.002.075 0 .024.003.052 0 .07v.065l-.002.073-.008.174a6.195 6.195 0 0 1-.08.639 5.1 5.1 0 0 1-.267.927 5.31 5.31 0 0 1-.624 1.13 5.052 5.052 0 0 1-3.237 2.014 4.82 4.82 0 0 1-.649.066l-.039.003h-.287a6.607 6.607 0 0 1-1.716-.265 6.776 6.776 0 0 1-3.4-2.274 6.75 6.75 0 0 1-.746-1.15 6.616 6.616 0 0 1-.714-2.596l-.005-.083-.002-.02v-.056l-.003-.073v-.096l-.003-.104v-.07l.003-.163c.008-.22.026-.45.054-.678a8.707 8.707 0 0 1 .28-1.355c.128-.444.286-.872.473-1.277a7.04 7.04 0 0 1 1.456-2.1 5.925 5.925 0 0 1 .953-.763c.169-.111.343-.213.524-.306.089-.05.182-.091.273-.135.047-.02.093-.042.138-.062a7.177 7.177 0 0 1 .714-.267l.145-.045c.049-.015.098-.026.148-.041.098-.029.197-.052.296-.076.049-.013.1-.02.15-.033l.15-.032.151-.028.076-.013.075-.01.153-.024c.057-.01.114-.013.171-.023l.169-.021c.036-.003.073-.008.106-.01l.073-.008.036-.003.042-.002c.057-.003.114-.008.171-.01l.086-.006h.023l.037-.003.145-.007a7.999 7.999 0 0 1 1.708.125 7.917 7.917 0 0 1 2.048.68 8.253 8.253 0 0 1 1.672 1.09l.09.077.089.078c.06.052.114.107.171.159.057.052.112.106.166.16.052.055.107.107.159.164a8.671 8.671 0 0 1 1.41 1.978c.012.026.028.052.04.078l.04.078.075.156c.023.051.05.1.07.153l.065.15a8.848 8.848 0 0 1 .45 1.34.19.19 0 0 0 .201.142.186.186 0 0 0 .172-.184c.01-.246.002-.532-.024-.856z"
|
|
94243
|
+
},
|
|
94244
|
+
graphql: {
|
|
94245
|
+
title: "GraphQL",
|
|
94246
|
+
d: "M12.002 0a2.138 2.138 0 1 0 0 4.277 2.138 2.138 0 1 0 0-4.277zm8.54 4.931a2.138 2.138 0 1 0 0 4.277 2.138 2.138 0 1 0 0-4.277zm0 9.862a2.138 2.138 0 1 0 0 4.277 2.138 2.138 0 1 0 0-4.277zm-8.54 4.931a2.138 2.138 0 1 0 0 4.276 2.138 2.138 0 1 0 0-4.276zm-8.542-4.93a2.138 2.138 0 1 0 0 4.276 2.138 2.138 0 1 0 0-4.277zm0-9.863a2.138 2.138 0 1 0 0 4.277 2.138 2.138 0 1 0 0-4.277zm8.542-3.378L2.953 6.777v10.448l9.049 5.224 9.047-5.224V6.777zm0 1.601 7.66 13.27H4.34zm-1.387.371L3.97 15.037V7.363zm2.774 0 6.646 3.838v7.674zM5.355 17.44h13.293l-6.646 3.836z"
|
|
94247
|
+
},
|
|
94248
|
+
javascript: {
|
|
94249
|
+
title: "JavaScript",
|
|
94250
|
+
d: "M0 0h24v24H0V0zm22.034 18.276c-.175-1.095-.888-2.015-3.003-2.873-.736-.345-1.554-.585-1.797-1.14-.091-.33-.105-.51-.046-.705.15-.646.915-.84 1.515-.66.39.12.75.42.976.9 1.034-.676 1.034-.676 1.755-1.125-.27-.42-.404-.601-.586-.78-.63-.705-1.469-1.065-2.834-1.034l-.705.089c-.676.165-1.32.525-1.71 1.005-1.14 1.291-.811 3.541.569 4.471 1.365 1.02 3.361 1.244 3.616 2.205.24 1.17-.87 1.545-1.966 1.41-.811-.18-1.26-.586-1.755-1.336l-1.83 1.051c.21.48.45.689.81 1.109 1.74 1.756 6.09 1.666 6.871-1.004.029-.09.24-.705.074-1.65l.046.067zm-8.983-7.245h-2.248c0 1.938-.009 3.864-.009 5.805 0 1.232.063 2.363-.138 2.711-.33.689-1.18.601-1.566.48-.396-.196-.597-.466-.83-.855-.063-.105-.11-.196-.127-.196l-1.825 1.125c.305.63.75 1.172 1.324 1.517.855.51 2.004.675 3.207.405.783-.226 1.458-.691 1.811-1.411.51-.93.402-2.07.397-3.346.012-2.054 0-4.109 0-6.179l.004-.056z",
|
|
94251
|
+
license: "MIT",
|
|
94252
|
+
licenseUrl: "https://spdx.org/licenses/MIT.html",
|
|
94253
|
+
source: "https://github.com/voodootikigod/logo.js/blob/1544bdeed6d618a6cfe4f0650d04ab8d9cfa76d9/js.svg",
|
|
94254
|
+
copyright: "Copyright (c) 2011 Christopher Williams <chris@iterativedesigns.com>"
|
|
94255
|
+
},
|
|
94256
|
+
kotlin: { title: "Kotlin", d: "M24 24H0V0h24L12 12Z" },
|
|
94257
|
+
kubernetes: {
|
|
94258
|
+
title: "Kubernetes",
|
|
94259
|
+
d: "M10.204 14.35l.007.01-.999 2.413a5.171 5.171 0 0 1-2.075-2.597l2.578-.437.004.005a.44.44 0 0 1 .484.606zm-.833-2.129a.44.44 0 0 0 .173-.756l.002-.011L7.585 9.7a5.143 5.143 0 0 0-.73 3.255l2.514-.725.002-.009zm1.145-1.98a.44.44 0 0 0 .699-.337l.01-.005.15-2.62a5.144 5.144 0 0 0-3.01 1.442l2.147 1.523.004-.002zm.76 2.75l.723.349.722-.347.18-.78-.5-.623h-.804l-.5.623.179.779zm1.5-3.095a.44.44 0 0 0 .7.336l.008.003 2.134-1.513a5.188 5.188 0 0 0-2.992-1.442l.148 2.615.002.001zm10.876 5.97l-5.773 7.181a1.6 1.6 0 0 1-1.248.594l-9.261.003a1.6 1.6 0 0 1-1.247-.596l-5.776-7.18a1.583 1.583 0 0 1-.307-1.34L2.1 5.573c.108-.47.425-.864.863-1.073L11.305.513a1.606 1.606 0 0 1 1.385 0l8.345 3.985c.438.209.755.604.863 1.073l2.062 8.955c.108.47-.005.963-.308 1.34zm-3.289-2.057c-.042-.01-.103-.026-.145-.034-.174-.033-.315-.025-.479-.038-.35-.037-.638-.067-.895-.148-.105-.04-.18-.165-.216-.216l-.201-.059a6.45 6.45 0 0 0-.105-2.332 6.465 6.465 0 0 0-.936-2.163c.052-.047.15-.133.177-.159.008-.09.001-.183.094-.282.197-.185.444-.338.743-.522.142-.084.273-.137.415-.242.032-.024.076-.062.11-.089.24-.191.295-.52.123-.736-.172-.216-.506-.236-.745-.045-.034.027-.08.062-.111.088-.134.116-.217.23-.33.35-.246.25-.45.458-.673.609-.097.056-.239.037-.303.033l-.19.135a6.545 6.545 0 0 0-4.146-2.003l-.012-.223c-.065-.062-.143-.115-.163-.25-.022-.268.015-.557.057-.905.023-.163.061-.298.068-.475.001-.04-.001-.099-.001-.142 0-.306-.224-.555-.5-.555-.275 0-.499.249-.499.555l.001.014c0 .041-.002.092 0 .128.006.177.044.312.067.475.042.348.078.637.056.906a.545.545 0 0 1-.162.258l-.012.211a6.424 6.424 0 0 0-4.166 2.003 8.373 8.373 0 0 1-.18-.128c-.09.012-.18.04-.297-.029-.223-.15-.427-.358-.673-.608-.113-.12-.195-.234-.329-.349-.03-.026-.077-.062-.111-.088a.594.594 0 0 0-.348-.132.481.481 0 0 0-.398.176c-.172.216-.117.546.123.737l.007.005.104.083c.142.105.272.159.414.242.299.185.546.338.743.522.076.082.09.226.1.288l.16.143a6.462 6.462 0 0 0-1.02 4.506l-.208.06c-.055.072-.133.184-.215.217-.257.081-.546.11-.895.147-.164.014-.305.006-.48.039-.037.007-.09.02-.133.03l-.004.002-.007.002c-.295.071-.484.342-.423.608.061.267.349.429.645.365l.007-.001.01-.003.129-.029c.17-.046.294-.113.448-.172.33-.118.604-.217.87-.256.112-.009.23.069.288.101l.217-.037a6.5 6.5 0 0 0 2.88 3.596l-.09.218c.033.084.069.199.044.282-.097.252-.263.517-.452.813-.091.136-.185.242-.268.399-.02.037-.045.095-.064.134-.128.275-.034.591.213.71.248.12.556-.007.69-.282v-.002c.02-.039.046-.09.062-.127.07-.162.094-.301.144-.458.132-.332.205-.68.387-.897.05-.06.13-.082.215-.105l.113-.205a6.453 6.453 0 0 0 4.609.012l.106.192c.086.028.18.042.256.155.136.232.229.507.342.84.05.156.074.295.145.457.016.037.043.09.062.129.133.276.442.402.69.282.247-.118.341-.435.213-.71-.02-.039-.045-.096-.065-.134-.083-.156-.177-.261-.268-.398-.19-.296-.346-.541-.443-.793-.04-.13.007-.21.038-.294-.018-.022-.059-.144-.083-.202a6.499 6.499 0 0 0 2.88-3.622c.064.01.176.03.213.038.075-.05.144-.114.28-.104.266.039.54.138.87.256.154.06.277.128.448.173.036.01.088.019.13.028l.009.003.007.001c.297.064.584-.098.645-.365.06-.266-.128-.537-.423-.608zM16.4 9.701l-1.95 1.746v.005a.44.44 0 0 0 .173.757l.003.01 2.526.728a5.199 5.199 0 0 0-.108-1.674A5.208 5.208 0 0 0 16.4 9.7zm-4.013 5.325a.437.437 0 0 0-.404-.232.44.44 0 0 0-.372.233h-.002l-1.268 2.292a5.164 5.164 0 0 0 3.326.003l-1.27-2.296h-.01zm1.888-1.293a.44.44 0 0 0-.27.036.44.44 0 0 0-.214.572l-.003.004 1.01 2.438a5.15 5.15 0 0 0 2.081-2.615l-2.6-.44-.004.005z"
|
|
94260
|
+
},
|
|
94261
|
+
mongodb: {
|
|
94262
|
+
title: "MongoDB",
|
|
94263
|
+
d: "M17.193 9.555c-1.264-5.58-4.252-7.414-4.573-8.115-.28-.394-.53-.954-.735-1.44-.036.495-.055.685-.523 1.184-.723.566-4.438 3.682-4.74 10.02-.282 5.912 4.27 9.435 4.888 9.884l.07.05A73.49 73.49 0 0111.91 24h.481c.114-1.032.284-2.056.51-3.07.417-.296.604-.463.85-.693a11.342 11.342 0 003.639-8.464c.01-.814-.103-1.662-.197-2.218zm-5.336 8.195s0-8.291.275-8.29c.213 0 .49 10.695.49 10.695-.381-.045-.765-1.76-.765-2.405z"
|
|
94264
|
+
},
|
|
94265
|
+
mysql: {
|
|
94266
|
+
title: "MySQL",
|
|
94267
|
+
d: "M16.405 5.501c-.115 0-.193.014-.274.033v.013h.014c.054.104.146.18.214.273.054.107.1.214.154.32l.014-.015c.094-.066.14-.172.14-.333-.04-.047-.046-.094-.08-.14-.04-.067-.126-.1-.18-.153zM5.77 18.695h-.927a50.854 50.854 0 00-.27-4.41h-.008l-1.41 4.41H2.45l-1.4-4.41h-.01a72.892 72.892 0 00-.195 4.41H0c.055-1.966.192-3.81.41-5.53h1.15l1.335 4.064h.008l1.347-4.064h1.095c.242 2.015.384 3.86.428 5.53zm4.017-4.08c-.378 2.045-.876 3.533-1.492 4.46-.482.716-1.01 1.073-1.583 1.073-.153 0-.34-.046-.566-.138v-.494c.11.017.24.026.386.026.268 0 .483-.075.647-.222.197-.18.295-.382.295-.605 0-.155-.077-.47-.23-.944L6.23 14.615h.91l.727 2.36c.164.536.233.91.205 1.123.4-1.064.678-2.227.835-3.483zm12.325 4.08h-2.63v-5.53h.885v4.85h1.745zm-3.32.135l-1.016-.5c.09-.076.177-.158.255-.25.433-.506.648-1.258.648-2.253 0-1.83-.718-2.746-2.155-2.746-.704 0-1.254.232-1.65.697-.43.508-.646 1.256-.646 2.245 0 .972.19 1.686.574 2.14.35.41.877.615 1.583.615.264 0 .506-.033.725-.098l1.325.772.36-.622zM15.5 17.588c-.225-.36-.337-.94-.337-1.736 0-1.393.424-2.09 1.27-2.09.443 0 .77.167.977.5.224.362.336.936.336 1.723 0 1.404-.424 2.108-1.27 2.108-.445 0-.77-.167-.978-.5zm-1.658-.425c0 .47-.172.856-.516 1.156-.344.3-.803.45-1.384.45-.543 0-1.064-.172-1.573-.515l.237-.476c.438.22.833.328 1.19.328.332 0 .593-.073.783-.22a.754.754 0 00.3-.615c0-.33-.23-.61-.648-.845-.388-.213-1.163-.657-1.163-.657-.422-.307-.632-.636-.632-1.177 0-.45.157-.81.47-1.085.315-.278.72-.415 1.22-.415.512 0 .98.136 1.4.41l-.213.476a2.726 2.726 0 00-1.064-.23c-.283 0-.502.068-.654.206a.685.685 0 00-.248.524c0 .328.234.61.666.85.393.215 1.187.67 1.187.67.433.305.648.63.648 1.168zm9.382-5.852c-.535-.014-.95.04-1.297.188-.1.04-.26.04-.274.167.055.053.063.14.11.214.08.134.218.313.346.407.14.11.28.216.427.31.26.16.555.255.81.416.145.094.293.213.44.313.073.05.12.14.214.172v-.02c-.046-.06-.06-.147-.105-.214-.067-.067-.134-.127-.2-.193a3.223 3.223 0 00-.695-.675c-.214-.146-.682-.35-.77-.595l-.013-.014c.146-.013.32-.066.46-.106.227-.06.435-.047.67-.106.106-.027.213-.06.32-.094v-.06c-.12-.12-.21-.283-.334-.395a8.867 8.867 0 00-1.104-.823c-.21-.134-.476-.22-.697-.334-.08-.04-.214-.06-.26-.127-.12-.146-.19-.34-.275-.514a17.69 17.69 0 01-.547-1.163c-.12-.262-.193-.523-.34-.763-.69-1.137-1.437-1.826-2.586-2.5-.247-.14-.543-.2-.856-.274-.167-.008-.334-.02-.5-.027-.11-.047-.216-.174-.31-.235-.38-.24-1.364-.76-1.644-.072-.18.434.267.862.422 1.082.115.153.26.328.34.5.047.116.06.235.107.356.106.294.207.622.347.897.073.14.153.287.247.413.054.073.146.107.167.227-.094.136-.1.334-.154.5-.24.757-.146 1.693.194 2.25.107.166.362.534.703.393.3-.12.234-.5.32-.835.02-.08.007-.133.048-.187v.015c.094.188.188.367.274.555.206.328.566.668.867.895.16.12.287.328.487.402v-.02h-.015c-.043-.058-.1-.086-.154-.133a3.445 3.445 0 01-.35-.4 8.76 8.76 0 01-.747-1.218c-.11-.21-.202-.436-.29-.643-.04-.08-.04-.2-.107-.24-.1.146-.247.273-.32.453-.127.288-.14.642-.188 1.01-.027.007-.014 0-.027.014-.214-.052-.287-.274-.367-.46-.2-.475-.233-1.238-.06-1.785.047-.14.247-.582.167-.716-.042-.127-.174-.2-.247-.303a2.478 2.478 0 01-.24-.427c-.16-.374-.24-.788-.414-1.162-.08-.173-.22-.354-.334-.513-.127-.18-.267-.307-.368-.52-.033-.073-.08-.194-.027-.274.014-.054.042-.075.094-.09.088-.072.335.022.422.062.247.1.455.194.662.334.094.066.195.193.315.226h.14c.214.047.455.014.655.073.355.114.675.28.962.46a5.953 5.953 0 012.085 2.286c.08.154.115.295.188.455.14.33.313.663.455.982.14.315.275.636.476.897.1.14.502.213.682.286.133.06.34.115.46.188.23.14.454.3.67.454.11.076.443.243.463.378z"
|
|
94268
|
+
},
|
|
94269
|
+
natsdotio: {
|
|
94270
|
+
title: "NATS.io",
|
|
94271
|
+
d: "M12.004 0H.404v18.807h9.938l1.714 1.602v-.026L15.966 24v-5.193h7.63V0H12.003zm7.578 14.45H15.38L6.898 6.519v7.93H4.116V4.376h4.349l8.344 7.784V4.375h2.773V14.45z"
|
|
94272
|
+
},
|
|
94273
|
+
nextdotjs: {
|
|
94274
|
+
title: "Next.js",
|
|
94275
|
+
d: "M18.665 21.978C16.758 23.255 14.465 24 12 24 5.377 24 0 18.623 0 12S5.377 0 12 0s12 5.377 12 12c0 3.583-1.574 6.801-4.067 9.001L9.219 7.2H7.2v9.596h1.615V9.251l9.85 12.727Zm-3.332-8.533 1.6 2.061V7.2h-1.6v6.245Z"
|
|
94276
|
+
},
|
|
94277
|
+
nginx: {
|
|
94278
|
+
title: "NGINX",
|
|
94279
|
+
d: "M12 0L1.605 6v12L12 24l10.395-6V6L12 0zm6 16.59c0 .705-.646 1.29-1.529 1.29-.631 0-1.351-.255-1.801-.81l-6-7.141v6.66c0 .721-.57 1.29-1.274 1.29H7.32c-.721 0-1.29-.6-1.29-1.29V7.41c0-.705.63-1.29 1.5-1.29.646 0 1.38.255 1.83.81l5.97 7.141V7.41c0-.721.6-1.29 1.29-1.29h.075c.72 0 1.29.6 1.29 1.29v9.18H18z"
|
|
94280
|
+
},
|
|
94281
|
+
nodedotjs: {
|
|
94282
|
+
title: "Node.js",
|
|
94283
|
+
d: "M11.998,24c-0.321,0-0.641-0.084-0.922-0.247l-2.936-1.737c-0.438-0.245-0.224-0.332-0.08-0.383 c0.585-0.203,0.703-0.25,1.328-0.604c0.065-0.037,0.151-0.023,0.218,0.017l2.256,1.339c0.082,0.045,0.197,0.045,0.272,0l8.795-5.076 c0.082-0.047,0.134-0.141,0.134-0.238V6.921c0-0.099-0.053-0.192-0.137-0.242l-8.791-5.072c-0.081-0.047-0.189-0.047-0.271,0 L3.075,6.68C2.99,6.729,2.936,6.825,2.936,6.921v10.15c0,0.097,0.054,0.189,0.139,0.235l2.409,1.392 c1.307,0.654,2.108-0.116,2.108-0.89V7.787c0-0.142,0.114-0.253,0.256-0.253h1.115c0.139,0,0.255,0.112,0.255,0.253v10.021 c0,1.745-0.95,2.745-2.604,2.745c-0.508,0-0.909,0-2.026-0.551L2.28,18.675c-0.57-0.329-0.922-0.945-0.922-1.604V6.921 c0-0.659,0.353-1.275,0.922-1.603l8.795-5.082c0.557-0.315,1.296-0.315,1.848,0l8.794,5.082c0.57,0.329,0.924,0.944,0.924,1.603 v10.15c0,0.659-0.354,1.273-0.924,1.604l-8.794,5.078C12.643,23.916,12.324,24,11.998,24z M19.099,13.993 c0-1.9-1.284-2.406-3.987-2.763c-2.731-0.361-3.009-0.548-3.009-1.187c0-0.528,0.235-1.233,2.258-1.233 c1.807,0,2.473,0.389,2.747,1.607c0.024,0.115,0.129,0.199,0.247,0.199h1.141c0.071,0,0.138-0.031,0.186-0.081 c0.048-0.054,0.074-0.123,0.067-0.196c-0.177-2.098-1.571-3.076-4.388-3.076c-2.508,0-4.004,1.058-4.004,2.833 c0,1.925,1.488,2.457,3.895,2.695c2.88,0.282,3.103,0.703,3.103,1.269c0,0.983-0.789,1.402-2.642,1.402 c-2.327,0-2.839-0.584-3.011-1.742c-0.02-0.124-0.126-0.215-0.253-0.215h-1.137c-0.141,0-0.254,0.112-0.254,0.253 c0,1.482,0.806,3.248,4.655,3.248C17.501,17.007,19.099,15.91,19.099,13.993z"
|
|
94284
|
+
},
|
|
94285
|
+
openjdk: {
|
|
94286
|
+
title: "OpenJDK",
|
|
94287
|
+
d: "M11.915 0 11.7.215C9.515 2.4 7.47 6.39 6.046 10.483c-1.064 1.024-3.633 2.81-3.711 3.551-.093.87 1.746 2.611 1.55 3.235-.198.625-1.304 1.408-1.014 1.939.1.188.823.011 1.277-.491a13.389 13.389 0 0 0-.017 2.14c.076.906.27 1.668.643 2.232.372.563.956.911 1.667.911.397 0 .727-.114 1.024-.264.298-.149.571-.33.91-.5.68-.34 1.634-.666 3.53-.604 1.903.062 2.872.39 3.559.704.687.314 1.15.664 1.925.664.767 0 1.395-.336 1.807-.9.412-.563.631-1.33.72-2.24.06-.623.055-1.32 0-2.066.454.45 1.117.604 1.213.424.29-.53-.816-1.314-1.013-1.937-.198-.624 1.642-2.366 1.549-3.236-.08-.748-2.707-2.568-3.748-3.586C16.428 6.374 14.308 2.394 12.13.215zm.175 6.038a2.95 2.95 0 0 1 2.943 2.942 2.95 2.95 0 0 1-2.943 2.943A2.95 2.95 0 0 1 9.148 8.98a2.95 2.95 0 0 1 2.942-2.942zM8.685 7.983a3.515 3.515 0 0 0-.145.997c0 1.951 1.6 3.55 3.55 3.55 1.95 0 3.55-1.598 3.55-3.55 0-.329-.046-.648-.132-.951.334.095.64.208.915.336a42.699 42.699 0 0 1 2.042 5.829c.678 2.545 1.01 4.92.846 6.607-.082.844-.29 1.51-.606 1.94-.315.431-.713.651-1.315.651-.593 0-.932-.27-1.673-.61-.741-.338-1.825-.694-3.792-.758-1.974-.064-3.073.293-3.821.669-.375.188-.659.373-.911.5s-.466.2-.752.2c-.53 0-.876-.209-1.16-.64-.285-.43-.474-1.101-.545-1.948-.141-1.693.176-4.069.823-6.614a43.155 43.155 0 0 1 1.934-5.783c.348-.167.749-.31 1.192-.425zm-3.382 4.362a.216.216 0 0 1 .13.031c-.166.56-.323 1.116-.463 1.665a33.849 33.849 0 0 0-.547 2.555 3.9 3.9 0 0 0-.2-.39c-.58-1.012-.914-1.642-1.16-2.08.315-.24 1.679-1.755 2.24-1.781zm13.394.01c.562.027 1.926 1.543 2.24 1.783-.246.438-.58 1.068-1.16 2.08a4.428 4.428 0 0 0-.163.309 32.354 32.354 0 0 0-.562-2.49 40.579 40.579 0 0 0-.482-1.652.216.216 0 0 1 .127-.03z",
|
|
94288
|
+
license: "BSD-3-Clause",
|
|
94289
|
+
licenseUrl: "https://spdx.org/licenses/BSD-3-Clause.html",
|
|
94290
|
+
source: "https://github.com/openjdk/duke/blob/master/vector/Agent.svg"
|
|
94291
|
+
},
|
|
94292
|
+
postgresql: {
|
|
94293
|
+
title: "PostgreSQL",
|
|
94294
|
+
d: "M23.5594 14.7228a.5269.5269 0 0 0-.0563-.1191c-.139-.2632-.4768-.3418-1.0074-.2321-1.6533.3411-2.2935.1312-2.5256-.0191 1.342-2.0482 2.445-4.522 3.0411-6.8297.2714-1.0507.7982-3.5237.1222-4.7316a1.5641 1.5641 0 0 0-.1509-.235C21.6931.9086 19.8007.0248 17.5099.0005c-1.4947-.0158-2.7705.3461-3.1161.4794a9.449 9.449 0 0 0-.5159-.0816 8.044 8.044 0 0 0-1.3114-.1278c-1.1822-.0184-2.2038.2642-3.0498.8406-.8573-.3211-4.7888-1.645-7.2219.0788C.9359 2.1526.3086 3.8733.4302 6.3043c.0409.818.5069 3.334 1.2423 5.7436.4598 1.5065.9387 2.7019 1.4334 3.582.553.9942 1.1259 1.5933 1.7143 1.7895.4474.1491 1.1327.1441 1.8581-.7279.8012-.9635 1.5903-1.8258 1.9446-2.2069.4351.2355.9064.3625 1.39.3772a.0569.0569 0 0 0 .0004.0041 11.0312 11.0312 0 0 0-.2472.3054c-.3389.4302-.4094.5197-1.5002.7443-.3102.064-1.1344.2339-1.1464.8115-.0025.1224.0329.2309.0919.3268.2269.4231.9216.6097 1.015.6331 1.3345.3335 2.5044.092 3.3714-.6787-.017 2.231.0775 4.4174.3454 5.0874.2212.5529.7618 1.9045 2.4692 1.9043.2505 0 .5263-.0291.8296-.0941 1.7819-.3821 2.5557-1.1696 2.855-2.9059.1503-.8707.4016-2.8753.5388-4.1012.0169-.0703.0357-.1207.057-.1362.0007-.0005.0697-.0471.4272.0307a.3673.3673 0 0 0 .0443.0068l.2539.0223.0149.001c.8468.0384 1.9114-.1426 2.5312-.4308.6438-.2988 1.8057-1.0323 1.5951-1.6698zM2.371 11.8765c-.7435-2.4358-1.1779-4.8851-1.2123-5.5719-.1086-2.1714.4171-3.6829 1.5623-4.4927 1.8367-1.2986 4.8398-.5408 6.108-.13-.0032.0032-.0066.0061-.0098.0094-2.0238 2.044-1.9758 5.536-1.9708 5.7495-.0002.0823.0066.1989.0162.3593.0348.5873.0996 1.6804-.0735 2.9184-.1609 1.1504.1937 2.2764.9728 3.0892.0806.0841.1648.1631.2518.2374-.3468.3714-1.1004 1.1926-1.9025 2.1576-.5677.6825-.9597.5517-1.0886.5087-.3919-.1307-.813-.5871-1.2381-1.3223-.4796-.839-.9635-2.0317-1.4155-3.5126zm6.0072 5.0871c-.1711-.0428-.3271-.1132-.4322-.1772.0889-.0394.2374-.0902.4833-.1409 1.2833-.2641 1.4815-.4506 1.9143-1.0002.0992-.126.2116-.2687.3673-.4426a.3549.3549 0 0 0 .0737-.1298c.1708-.1513.2724-.1099.4369-.0417.156.0646.3078.26.3695.4752.0291.1016.0619.2945-.0452.4444-.9043 1.2658-2.2216 1.2494-3.1676 1.0128zm2.094-3.988-.0525.141c-.133.3566-.2567.6881-.3334 1.003-.6674-.0021-1.3168-.2872-1.8105-.8024-.6279-.6551-.9131-1.5664-.7825-2.5004.1828-1.3079.1153-2.4468.079-3.0586-.005-.0857-.0095-.1607-.0122-.2199.2957-.2621 1.6659-.9962 2.6429-.7724.4459.1022.7176.4057.8305.928.5846 2.7038.0774 3.8307-.3302 4.7363-.084.1866-.1633.3629-.2311.5454zm7.3637 4.5725c-.0169.1768-.0358.376-.0618.5959l-.146.4383a.3547.3547 0 0 0-.0182.1077c-.0059.4747-.054.6489-.115.8693-.0634.2292-.1353.4891-.1794 1.0575-.11 1.4143-.8782 2.2267-2.4172 2.5565-1.5155.3251-1.7843-.4968-2.0212-1.2217a6.5824 6.5824 0 0 0-.0769-.2266c-.2154-.5858-.1911-1.4119-.1574-2.5551.0165-.5612-.0249-1.9013-.3302-2.6462.0044-.2932.0106-.5909.019-.8918a.3529.3529 0 0 0-.0153-.1126 1.4927 1.4927 0 0 0-.0439-.208c-.1226-.4283-.4213-.7866-.7797-.9351-.1424-.059-.4038-.1672-.7178-.0869.067-.276.1831-.5875.309-.9249l.0529-.142c.0595-.16.134-.3257.213-.5012.4265-.9476 1.0106-2.2453.3766-5.1772-.2374-1.0981-1.0304-1.6343-2.2324-1.5098-.7207.0746-1.3799.3654-1.7088.5321a5.6716 5.6716 0 0 0-.1958.1041c.0918-1.1064.4386-3.1741 1.7357-4.4823a4.0306 4.0306 0 0 1 .3033-.276.3532.3532 0 0 0 .1447-.0644c.7524-.5706 1.6945-.8506 2.802-.8325.4091.0067.8017.0339 1.1742.081 1.939.3544 3.2439 1.4468 4.0359 2.3827.8143.9623 1.2552 1.9315 1.4312 2.4543-1.3232-.1346-2.2234.1268-2.6797.779-.9926 1.4189.543 4.1729 1.2811 5.4964.1353.2426.2522.4522.2889.5413.2403.5825.5515.9713.7787 1.2552.0696.087.1372.1714.1885.245-.4008.1155-1.1208.3825-1.0552 1.717-.0123.1563-.0423.4469-.0834.8148-.0461.2077-.0702.4603-.0994.7662zm.8905-1.6211c-.0405-.8316.2691-.9185.5967-1.0105a2.8566 2.8566 0 0 0 .135-.0406 1.202 1.202 0 0 0 .1342.103c.5703.3765 1.5823.4213 3.0068.1344-.2016.1769-.5189.3994-.9533.6011-.4098.1903-1.0957.333-1.7473.3636-.7197.0336-1.0859-.0807-1.1721-.151zm.5695-9.2712c-.0059.3508-.0542.6692-.1054 1.0017-.055.3576-.112.7274-.1264 1.1762-.0142.4368.0404.8909.0932 1.3301.1066.887.216 1.8003-.2075 2.7014a3.5272 3.5272 0 0 1-.1876-.3856c-.0527-.1276-.1669-.3326-.3251-.6162-.6156-1.1041-2.0574-3.6896-1.3193-4.7446.3795-.5427 1.3408-.5661 2.1781-.463zm.2284 7.0137a12.3762 12.3762 0 0 0-.0853-.1074l-.0355-.0444c.7262-1.1995.5842-2.3862.4578-3.4385-.0519-.4318-.1009-.8396-.0885-1.2226.0129-.4061.0666-.7543.1185-1.0911.0639-.415.1288-.8443.1109-1.3505.0134-.0531.0188-.1158.0118-.1902-.0457-.4855-.5999-1.938-1.7294-3.253-.6076-.7073-1.4896-1.4972-2.6889-2.0395.5251-.1066 1.2328-.2035 2.0244-.1859 2.0515.0456 3.6746.8135 4.8242 2.2824a.908.908 0 0 1 .0667.1002c.7231 1.3556-.2762 6.2751-2.9867 10.5405zm-8.8166-6.1162c-.025.1794-.3089.4225-.6211.4225a.5821.5821 0 0 1-.0809-.0056c-.1873-.026-.3765-.144-.5059-.3156-.0458-.0605-.1203-.178-.1055-.2844.0055-.0401.0261-.0985.0925-.1488.1182-.0894.3518-.1226.6096-.0867.3163.0441.6426.1938.6113.4186zm7.9305-.4114c.0111.0792-.049.201-.1531.3102-.0683.0717-.212.1961-.4079.2232a.5456.5456 0 0 1-.075.0052c-.2935 0-.5414-.2344-.5607-.3717-.024-.1765.2641-.3106.5611-.352.297-.0414.6111.0088.6356.1851z"
|
|
94295
|
+
},
|
|
94296
|
+
prometheus: {
|
|
94297
|
+
title: "Prometheus",
|
|
94298
|
+
d: "M12 0C5.373 0 0 5.372 0 12c0 6.627 5.373 12 12 12s12-5.373 12-12c0-6.628-5.373-12-12-12zm0 22.46c-1.885 0-3.414-1.26-3.414-2.814h6.828c0 1.553-1.528 2.813-3.414 2.813zm5.64-3.745H6.36v-2.046h11.28v2.046zm-.04-3.098H6.391c-.037-.043-.075-.086-.111-.13-1.155-1.401-1.427-2.133-1.69-2.879-.005-.025 1.4.287 2.395.511 0 0 .513.119 1.262.255-.72-.843-1.147-1.915-1.147-3.01 0-2.406 1.845-4.508 1.18-6.207.648.053 1.34 1.367 1.387 3.422.689-.951.977-2.69.977-3.755 0-1.103.727-2.385 1.454-2.429-.648 1.069.168 1.984.894 4.256.272.854.237 2.29.447 3.201.07-1.892.395-4.652 1.595-5.605-.529 1.2.079 2.702.494 3.424.671 1.164 1.078 2.047 1.078 3.716a4.642 4.642 0 01-1.11 2.996c.792-.149 1.34-.283 1.34-.283l2.573-.502s-.374 1.538-1.81 3.019z"
|
|
94299
|
+
},
|
|
94300
|
+
python: {
|
|
94301
|
+
title: "Python",
|
|
94302
|
+
d: "M14.25.18l.9.2.73.26.59.3.45.32.34.34.25.34.16.33.1.3.04.26.02.2-.01.13V8.5l-.05.63-.13.55-.21.46-.26.38-.3.31-.33.25-.35.19-.35.14-.33.1-.3.07-.26.04-.21.02H8.77l-.69.05-.59.14-.5.22-.41.27-.33.32-.27.35-.2.36-.15.37-.1.35-.07.32-.04.27-.02.21v3.06H3.17l-.21-.03-.28-.07-.32-.12-.35-.18-.36-.26-.36-.36-.35-.46-.32-.59-.28-.73-.21-.88-.14-1.05-.05-1.23.06-1.22.16-1.04.24-.87.32-.71.36-.57.4-.44.42-.33.42-.24.4-.16.36-.1.32-.05.24-.01h.16l.06.01h8.16v-.83H6.18l-.01-2.75-.02-.37.05-.34.11-.31.17-.28.25-.26.31-.23.38-.2.44-.18.51-.15.58-.12.64-.1.71-.06.77-.04.84-.02 1.27.05zm-6.3 1.98l-.23.33-.08.41.08.41.23.34.33.22.41.09.41-.09.33-.22.23-.34.08-.41-.08-.41-.23-.33-.33-.22-.41-.09-.41.09zm13.09 3.95l.28.06.32.12.35.18.36.27.36.35.35.47.32.59.28.73.21.88.14 1.04.05 1.23-.06 1.23-.16 1.04-.24.86-.32.71-.36.57-.4.45-.42.33-.42.24-.4.16-.36.09-.32.05-.24.02-.16-.01h-8.22v.82h5.84l.01 2.76.02.36-.05.34-.11.31-.17.29-.25.25-.31.24-.38.2-.44.17-.51.15-.58.13-.64.09-.71.07-.77.04-.84.01-1.27-.04-1.07-.14-.9-.2-.73-.25-.59-.3-.45-.33-.34-.34-.25-.34-.16-.33-.1-.3-.04-.25-.02-.2.01-.13v-5.34l.05-.64.13-.54.21-.46.26-.38.3-.32.33-.24.35-.2.35-.14.33-.1.3-.06.26-.04.21-.02.13-.01h5.84l.69-.05.59-.14.5-.21.41-.28.33-.32.27-.35.2-.36.15-.36.1-.35.07-.32.04-.28.02-.21V6.07h2.09l.14.01zm-6.47 14.25l-.23.33-.08.41.08.41.23.33.33.23.41.08.41-.08.33-.23.23-.33.08-.41-.08-.41-.23-.33-.33-.23-.41-.08-.41.08z"
|
|
94303
|
+
},
|
|
94304
|
+
rabbitmq: {
|
|
94305
|
+
title: "RabbitMQ",
|
|
94306
|
+
d: "M23.035 9.601h-7.677a.956.956 0 01-.962-.962V.962a.956.956 0 00-.962-.956H10.56a.956.956 0 00-.962.956V8.64a.956.956 0 01-.962.962H5.762a.956.956 0 01-.961-.962V.962A.956.956 0 003.839 0H.959a.956.956 0 00-.956.962v22.076A.956.956 0 00.965 24h22.07a.956.956 0 00.962-.962V10.58a.956.956 0 00-.962-.98zm-3.86 8.152a1.437 1.437 0 01-1.437 1.443h-1.924a1.437 1.437 0 01-1.436-1.443v-1.917a1.437 1.437 0 011.436-1.443h1.924a1.437 1.437 0 011.437 1.443z"
|
|
94307
|
+
},
|
|
94308
|
+
react: {
|
|
94309
|
+
title: "React",
|
|
94310
|
+
d: "M14.23 12.004a2.236 2.236 0 0 1-2.235 2.236 2.236 2.236 0 0 1-2.236-2.236 2.236 2.236 0 0 1 2.235-2.236 2.236 2.236 0 0 1 2.236 2.236zm2.648-10.69c-1.346 0-3.107.96-4.888 2.622-1.78-1.653-3.542-2.602-4.887-2.602-.41 0-.783.093-1.106.278-1.375.793-1.683 3.264-.973 6.365C1.98 8.917 0 10.42 0 12.004c0 1.59 1.99 3.097 5.043 4.03-.704 3.113-.39 5.588.988 6.38.32.187.69.275 1.102.275 1.345 0 3.107-.96 4.888-2.624 1.78 1.654 3.542 2.603 4.887 2.603.41 0 .783-.09 1.106-.275 1.374-.792 1.683-3.263.973-6.365C22.02 15.096 24 13.59 24 12.004c0-1.59-1.99-3.097-5.043-4.032.704-3.11.39-5.587-.988-6.38-.318-.184-.688-.277-1.092-.278zm-.005 1.09v.006c.225 0 .406.044.558.127.666.382.955 1.835.73 3.704-.054.46-.142.945-.25 1.44-.96-.236-2.006-.417-3.107-.534-.66-.905-1.345-1.727-2.035-2.447 1.592-1.48 3.087-2.292 4.105-2.295zm-9.77.02c1.012 0 2.514.808 4.11 2.28-.686.72-1.37 1.537-2.02 2.442-1.107.117-2.154.298-3.113.538-.112-.49-.195-.964-.254-1.42-.23-1.868.054-3.32.714-3.707.19-.09.4-.127.563-.132zm4.882 3.05c.455.468.91.992 1.36 1.564-.44-.02-.89-.034-1.345-.034-.46 0-.915.01-1.36.034.44-.572.895-1.096 1.345-1.565zM12 8.1c.74 0 1.477.034 2.202.093.406.582.802 1.203 1.183 1.86.372.64.71 1.29 1.018 1.946-.308.655-.646 1.31-1.013 1.95-.38.66-.773 1.288-1.18 1.87-.728.063-1.466.098-2.21.098-.74 0-1.477-.035-2.202-.093-.406-.582-.802-1.204-1.183-1.86-.372-.64-.71-1.29-1.018-1.946.303-.657.646-1.313 1.013-1.954.38-.66.773-1.286 1.18-1.868.728-.064 1.466-.098 2.21-.098zm-3.635.254c-.24.377-.48.763-.704 1.16-.225.39-.435.782-.635 1.174-.265-.656-.49-1.31-.676-1.947.64-.15 1.315-.283 2.015-.386zm7.26 0c.695.103 1.365.23 2.006.387-.18.632-.405 1.282-.66 1.933-.2-.39-.41-.783-.64-1.174-.225-.392-.465-.774-.705-1.146zm3.063.675c.484.15.944.317 1.375.498 1.732.74 2.852 1.708 2.852 2.476-.005.768-1.125 1.74-2.857 2.475-.42.18-.88.342-1.355.493-.28-.958-.646-1.956-1.1-2.98.45-1.017.81-2.01 1.085-2.964zm-13.395.004c.278.96.645 1.957 1.1 2.98-.45 1.017-.812 2.01-1.086 2.964-.484-.15-.944-.318-1.37-.5-1.732-.737-2.852-1.706-2.852-2.474 0-.768 1.12-1.742 2.852-2.476.42-.18.88-.342 1.356-.494zm11.678 4.28c.265.657.49 1.312.676 1.948-.64.157-1.316.29-2.016.39.24-.375.48-.762.705-1.158.225-.39.435-.788.636-1.18zm-9.945.02c.2.392.41.783.64 1.175.23.39.465.772.705 1.143-.695-.102-1.365-.23-2.006-.386.18-.63.406-1.282.66-1.933zM17.92 16.32c.112.493.2.968.254 1.423.23 1.868-.054 3.32-.714 3.708-.147.09-.338.128-.563.128-1.012 0-2.514-.807-4.11-2.28.686-.72 1.37-1.536 2.02-2.44 1.107-.118 2.154-.3 3.113-.54zm-11.83.01c.96.234 2.006.415 3.107.532.66.905 1.345 1.727 2.035 2.446-1.595 1.483-3.092 2.295-4.11 2.295-.22-.005-.406-.05-.553-.132-.666-.38-.955-1.834-.73-3.703.054-.46.142-.944.25-1.438zm4.56.64c.44.02.89.034 1.345.034.46 0 .915-.01 1.36-.034-.44.572-.895 1.095-1.345 1.565-.455-.47-.91-.993-1.36-1.565z"
|
|
94311
|
+
},
|
|
94312
|
+
redis: {
|
|
94313
|
+
title: "Redis",
|
|
94314
|
+
d: "M22.71 13.145c-1.66 2.092-3.452 4.483-7.038 4.483-3.203 0-4.397-2.825-4.48-5.12.701 1.484 2.073 2.685 4.214 2.63 4.117-.133 6.94-3.852 6.94-7.239 0-4.05-3.022-6.972-8.268-6.972-3.752 0-8.4 1.428-11.455 3.685C2.59 6.937 3.885 9.958 4.35 9.626c2.648-1.904 4.748-3.13 6.784-3.744C8.12 9.244.886 17.05 0 18.425c.1 1.261 1.66 4.648 2.424 4.648.232 0 .431-.133.664-.365a100.49 100.49 0 0 0 5.54-6.765c.222 3.104 1.748 6.898 6.014 6.898 3.819 0 7.604-2.756 9.33-8.965.2-.764-.73-1.361-1.261-.73zm-4.349-5.013c0 1.959-1.926 2.922-3.685 2.922-.941 0-1.664-.247-2.235-.568 1.051-1.592 2.092-3.225 3.21-4.973 1.972.334 2.71 1.43 2.71 2.619z"
|
|
94315
|
+
},
|
|
94316
|
+
spring: {
|
|
94317
|
+
title: "Spring",
|
|
94318
|
+
d: "M21.8537 1.4158a10.4504 10.4504 0 0 1-1.284 2.2471A11.9666 11.9666 0 1 0 3.8518 20.7757l.4445.3951a11.9543 11.9543 0 0 0 19.6316-8.2971c.3457-3.0126-.568-6.8649-2.0743-11.458zM5.5805 20.8745a1.0174 1.0174 0 1 1-.1482-1.4323 1.0396 1.0396 0 0 1 .1482 1.4323zm16.1991-3.5806c-2.9385 3.9263-9.2601 2.5928-13.2852 2.7904 0 0-.7161.0494-1.4323.1481 0 0 .2717-.1234.6174-.2469 2.8398-.9877 4.1732-1.1853 5.9018-2.0743 3.2349-1.6545 6.4698-5.2844 7.1118-9.0379-1.2347 3.6053-4.9881 6.7167-8.3959 7.9761-2.3459.8643-6.5685 1.7039-6.5685 1.7039l-.1729-.0988c-2.8645-1.4076-2.9632-7.6304 2.2718-9.6306 2.2966-.889 4.4696-.395 6.9637-.9877 2.6422-.6174 5.7043-2.5929 6.939-5.1857 1.3828 4.1732 3.062 10.643.0493 14.6434z"
|
|
94319
|
+
},
|
|
94320
|
+
sqlite: {
|
|
94321
|
+
title: "SQLite",
|
|
94322
|
+
d: "M21.678.521c-1.032-.92-2.28-.55-3.513.544a8.71 8.71 0 0 0-.547.535c-2.109 2.237-4.066 6.38-4.674 9.544.237.48.422 1.093.544 1.561a13.044 13.044 0 0 1 .164.703s-.019-.071-.096-.296l-.05-.146a1.689 1.689 0 0 0-.033-.08c-.138-.32-.518-.995-.686-1.289-.143.423-.27.818-.376 1.176.484.884.778 2.4.778 2.4s-.025-.099-.147-.442c-.107-.303-.644-1.244-.772-1.464-.217.804-.304 1.346-.226 1.478.152.256.296.698.422 1.186.286 1.1.485 2.44.485 2.44l.017.224a22.41 22.41 0 0 0 .056 2.748c.095 1.146.273 2.13.5 2.657l.155-.084c-.334-1.038-.47-2.399-.41-3.967.09-2.398.642-5.29 1.661-8.304 1.723-4.55 4.113-8.201 6.3-9.945-1.993 1.8-4.692 7.63-5.5 9.788-.904 2.416-1.545 4.684-1.931 6.857.666-2.037 2.821-2.912 2.821-2.912s1.057-1.304 2.292-3.166c-.74.169-1.955.458-2.362.629-.6.251-.762.337-.762.337s1.945-1.184 3.613-1.72C21.695 7.9 24.195 2.767 21.678.521m-18.573.543A1.842 1.842 0 0 0 1.27 2.9v16.608a1.84 1.84 0 0 0 1.835 1.834h9.418a22.953 22.953 0 0 1-.052-2.707c-.006-.062-.011-.141-.016-.2a27.01 27.01 0 0 0-.473-2.378c-.121-.47-.275-.898-.369-1.057-.116-.197-.098-.31-.097-.432 0-.12.015-.245.037-.386a9.98 9.98 0 0 1 .234-1.045l.217-.028c-.017-.035-.014-.065-.031-.097l-.041-.381a32.8 32.8 0 0 1 .382-1.194l.2-.019c-.008-.016-.01-.038-.018-.053l-.043-.316c.63-3.28 2.587-7.443 4.8-9.791.066-.069.133-.128.198-.194Z"
|
|
94323
|
+
},
|
|
94324
|
+
terraform: {
|
|
94325
|
+
title: "Terraform",
|
|
94326
|
+
d: "M1.44 0v7.575l6.561 3.79V3.787zm21.12 4.227l-6.561 3.791v7.574l6.56-3.787zM8.72 4.23v7.575l6.561 3.787V8.018zm0 8.405v7.575L15.28 24v-7.578z"
|
|
94327
|
+
},
|
|
94328
|
+
typescript: {
|
|
94329
|
+
title: "TypeScript",
|
|
94330
|
+
d: "M1.125 0C.502 0 0 .502 0 1.125v21.75C0 23.498.502 24 1.125 24h21.75c.623 0 1.125-.502 1.125-1.125V1.125C24 .502 23.498 0 22.875 0zm17.363 9.75c.612 0 1.154.037 1.627.111a6.38 6.38 0 0 1 1.306.34v2.458a3.95 3.95 0 0 0-.643-.361 5.093 5.093 0 0 0-.717-.26 5.453 5.453 0 0 0-1.426-.2c-.3 0-.573.028-.819.086a2.1 2.1 0 0 0-.623.242c-.17.104-.3.229-.393.374a.888.888 0 0 0-.14.49c0 .196.053.373.156.529.104.156.252.304.443.444s.423.276.696.41c.273.135.582.274.926.416.47.197.892.407 1.266.628.374.222.695.473.963.753.268.279.472.598.614.957.142.359.214.776.214 1.253 0 .657-.125 1.21-.373 1.656a3.033 3.033 0 0 1-1.012 1.085 4.38 4.38 0 0 1-1.487.596c-.566.12-1.163.18-1.79.18a9.916 9.916 0 0 1-1.84-.164 5.544 5.544 0 0 1-1.512-.493v-2.63a5.033 5.033 0 0 0 3.237 1.2c.333 0 .624-.03.872-.09.249-.06.456-.144.623-.25.166-.108.29-.234.373-.38a1.023 1.023 0 0 0-.074-1.089 2.12 2.12 0 0 0-.537-.5 5.597 5.597 0 0 0-.807-.444 27.72 27.72 0 0 0-1.007-.436c-.918-.383-1.602-.852-2.053-1.405-.45-.553-.676-1.222-.676-2.005 0-.614.123-1.141.369-1.582.246-.441.58-.804 1.004-1.089a4.494 4.494 0 0 1 1.47-.629 7.536 7.536 0 0 1 1.77-.201zm-15.113.188h9.563v2.166H9.506v9.646H6.789v-9.646H3.375z"
|
|
94331
|
+
},
|
|
94332
|
+
vault: {
|
|
94333
|
+
title: "Vault",
|
|
94334
|
+
d: "M0 0l11.955 24L24 0zm13.366 4.827h1.393v1.38h-1.393zm-2.77 5.569H9.22V8.993h1.389zm0-2.087H9.22V6.906h1.389zm0-2.086H9.22V4.819h1.389zm2.087 6.263h-1.377V11.08h1.388zm0-2.09h-1.377V8.993h1.388zm0-2.087h-1.377V6.906h1.388zm0-2.086h-1.377V4.819h1.388zm.683.683h1.393v1.389h-1.393zm0 3.475V8.993h1.389v1.388Z"
|
|
94202
94335
|
}
|
|
94203
94336
|
};
|
|
94204
|
-
var
|
|
94205
|
-
logical: logicalView,
|
|
94206
|
-
application: applicationView,
|
|
94207
|
-
infrastructure: infrastructureView,
|
|
94208
|
-
security: securityView
|
|
94209
|
-
};
|
|
94337
|
+
var LOGO_NAMES = Object.keys(LOGOS);
|
|
94210
94338
|
|
|
94211
94339
|
// src/validator.ts
|
|
94212
94340
|
function validate(model) {
|
|
@@ -94230,8 +94358,8 @@ function validate(model) {
|
|
|
94230
94358
|
...checkMissingLabels(elements),
|
|
94231
94359
|
...checkNesting(elements, view),
|
|
94232
94360
|
...checkFlows(model, view),
|
|
94233
|
-
...
|
|
94234
|
-
...
|
|
94361
|
+
...checkEndpointRoles(model, view),
|
|
94362
|
+
...checkLogos(elements, view),
|
|
94235
94363
|
...checkBusinessObjects(model, view),
|
|
94236
94364
|
...checkMinimumCounts(elements, model, view),
|
|
94237
94365
|
...checkIsolatedElements(model, view, elements)
|
|
@@ -94273,6 +94401,48 @@ function checkUnknownKinds(elements, view) {
|
|
|
94273
94401
|
}
|
|
94274
94402
|
return diagnostics;
|
|
94275
94403
|
}
|
|
94404
|
+
function checkLogos(elements, view) {
|
|
94405
|
+
const diagnostics = [];
|
|
94406
|
+
const logoKinds = view.logoKinds ?? [];
|
|
94407
|
+
for (const element of elements) {
|
|
94408
|
+
const logo = element.logo;
|
|
94409
|
+
if (!logo) continue;
|
|
94410
|
+
if (!logoKinds.includes(element.kind)) {
|
|
94411
|
+
diagnostics.push({
|
|
94412
|
+
code: "E0108",
|
|
94413
|
+
severity: "error",
|
|
94414
|
+
message: `\`${element.kind}\` does not carry a logo`,
|
|
94415
|
+
span: logo.span,
|
|
94416
|
+
note: logoKinds.length ? `the \`${view.name}\` view accepts \`logo\` on: ${logoKinds.join(", ")}` : `the \`${view.name}\` view has no kinds that carry a logo`
|
|
94417
|
+
});
|
|
94418
|
+
continue;
|
|
94419
|
+
}
|
|
94420
|
+
if (logo.source === "builtin") {
|
|
94421
|
+
if (Object.hasOwn(LOGOS, logo.value)) continue;
|
|
94422
|
+
const suggestion = nearest(logo.value, LOGO_NAMES);
|
|
94423
|
+
diagnostics.push({
|
|
94424
|
+
code: "E0107",
|
|
94425
|
+
severity: "error",
|
|
94426
|
+
message: `unknown built-in logo \`${logo.value}\``,
|
|
94427
|
+
span: logo.span,
|
|
94428
|
+
note: `${LOGO_NAMES.length} built-ins available \u2014 run \`cairn logos\` to list them`,
|
|
94429
|
+
help: suggestion !== void 0 ? `did you mean \`${suggestion}\`?` : `use a file instead: \`logo: "./logos/${logo.value}.svg"\``
|
|
94430
|
+
});
|
|
94431
|
+
continue;
|
|
94432
|
+
}
|
|
94433
|
+
if (/^[a-z][a-z0-9+.-]*:/i.test(logo.value) || logo.value.startsWith("//")) {
|
|
94434
|
+
diagnostics.push({
|
|
94435
|
+
code: "E0105",
|
|
94436
|
+
severity: "error",
|
|
94437
|
+
message: `\`logo\` will not fetch \`${logo.value}\``,
|
|
94438
|
+
span: logo.span,
|
|
94439
|
+
note: "a linked logo leaves the diagram depending on a server that can change or vanish",
|
|
94440
|
+
help: 'download it next to the diagram and point at the file: `logo: "./logos/name.svg"`'
|
|
94441
|
+
});
|
|
94442
|
+
}
|
|
94443
|
+
}
|
|
94444
|
+
return diagnostics;
|
|
94445
|
+
}
|
|
94276
94446
|
function checkMissingLabels(elements) {
|
|
94277
94447
|
const diagnostics = [];
|
|
94278
94448
|
for (const element of elements) {
|
|
@@ -94307,6 +94477,42 @@ function checkNesting(elements, view) {
|
|
|
94307
94477
|
}
|
|
94308
94478
|
return diagnostics;
|
|
94309
94479
|
}
|
|
94480
|
+
function checkEndpointRoles(model, view) {
|
|
94481
|
+
const diagnostics = [];
|
|
94482
|
+
const hubKinds = new Set(view.hubKinds ?? []);
|
|
94483
|
+
const isHub = (id) => hubKinds.has(model.index.get(id)?.kind ?? "");
|
|
94484
|
+
for (const flow of model.flows) {
|
|
94485
|
+
for (const [role, hubId, hubSide] of [
|
|
94486
|
+
[flow.fromRole, flow.to, flow.toSide],
|
|
94487
|
+
[flow.toRole, flow.from, flow.fromSide]
|
|
94488
|
+
]) {
|
|
94489
|
+
if (!role) continue;
|
|
94490
|
+
if (!model.index.has(hubId)) continue;
|
|
94491
|
+
if (!isHub(hubId)) {
|
|
94492
|
+
const kinds = [...hubKinds];
|
|
94493
|
+
diagnostics.push({
|
|
94494
|
+
code: "E0224",
|
|
94495
|
+
severity: "error",
|
|
94496
|
+
message: `\`${role.value}\` needs a ${kinds.join(" or ") || "queue"} at the other end of the flow`,
|
|
94497
|
+
span: role.span,
|
|
94498
|
+
note: `\`${hubId}\` is ${model.index.get(hubId)?.kind ? `a \`${model.index.get(hubId).kind}\`` : "not one"}`,
|
|
94499
|
+
help: "a role says what this element does with a queue \u2014 between two ordinary elements the arrow already says it"
|
|
94500
|
+
});
|
|
94501
|
+
continue;
|
|
94502
|
+
}
|
|
94503
|
+
if (hubSide)
|
|
94504
|
+
diagnostics.push({
|
|
94505
|
+
code: "E0225",
|
|
94506
|
+
severity: "error",
|
|
94507
|
+
message: `\`${hubId}.${hubSide.value}\` and \`${role.value}\` both decide where this flow meets the queue`,
|
|
94508
|
+
span: hubSide.span,
|
|
94509
|
+
note: "`producer` means the queue's left cap and `consumer` its right",
|
|
94510
|
+
help: "keep the role and drop the side, or keep the side and drop the role"
|
|
94511
|
+
});
|
|
94512
|
+
}
|
|
94513
|
+
}
|
|
94514
|
+
return diagnostics;
|
|
94515
|
+
}
|
|
94310
94516
|
function checkFlows(model, view) {
|
|
94311
94517
|
const diagnostics = [];
|
|
94312
94518
|
const isActor = (id) => {
|
|
@@ -94364,75 +94570,6 @@ function checkFlows(model, view) {
|
|
|
94364
94570
|
}
|
|
94365
94571
|
return diagnostics;
|
|
94366
94572
|
}
|
|
94367
|
-
function checkElementAttributes(elements, view) {
|
|
94368
|
-
const spec = view.attrSpec;
|
|
94369
|
-
if (!spec) return [];
|
|
94370
|
-
const diagnostics = [];
|
|
94371
|
-
for (const element of elements) {
|
|
94372
|
-
if (element.kind !== spec.kind) continue;
|
|
94373
|
-
if (!element.attr) {
|
|
94374
|
-
diagnostics.push({
|
|
94375
|
-
code: spec.code,
|
|
94376
|
-
severity: "error",
|
|
94377
|
-
message: spec.message + ` (\`${element.id}\`)`,
|
|
94378
|
-
span: element.idSpan,
|
|
94379
|
-
help: spec.help
|
|
94380
|
-
});
|
|
94381
|
-
} else if (!spec.values.includes(element.attr.value)) {
|
|
94382
|
-
const suggestion = nearest(element.attr.value, spec.values);
|
|
94383
|
-
diagnostics.push({
|
|
94384
|
-
code: spec.code,
|
|
94385
|
-
severity: "error",
|
|
94386
|
-
message: `invalid ${spec.kind} value \`${element.attr.value}\` (\`${element.id}\`)`,
|
|
94387
|
-
span: element.attr.span,
|
|
94388
|
-
note: `allowed: ${spec.values.join(", ")}`,
|
|
94389
|
-
help: suggestion ? `did you mean \`${suggestion}\`?` : spec.help
|
|
94390
|
-
});
|
|
94391
|
-
}
|
|
94392
|
-
}
|
|
94393
|
-
return diagnostics;
|
|
94394
|
-
}
|
|
94395
|
-
function checkTrustBoundaries(model, view) {
|
|
94396
|
-
if (!view.boundaryLint && !view.crossZoneTechRecommended) return [];
|
|
94397
|
-
const diagnostics = [];
|
|
94398
|
-
const zoneOf2 = (id) => {
|
|
94399
|
-
for (let ancestor = model.index.get(id)?.parent; ancestor; ancestor = ancestor.parent)
|
|
94400
|
-
if (ancestor.kind === "trust-zone") return ancestor;
|
|
94401
|
-
return void 0;
|
|
94402
|
-
};
|
|
94403
|
-
const trustLevelOf = (id) => {
|
|
94404
|
-
const level = zoneOf2(id)?.attr?.value;
|
|
94405
|
-
return level && view.trustOrder?.[level] !== void 0 ? view.trustOrder[level] : -1;
|
|
94406
|
-
};
|
|
94407
|
-
const lint = view.boundaryLint;
|
|
94408
|
-
const isSecurityNode = (id) => lint !== void 0 && model.index.get(id)?.kind === lint.nodeKind;
|
|
94409
|
-
for (const flow of model.flows) {
|
|
94410
|
-
if (!model.index.has(flow.from) || !model.index.has(flow.to)) continue;
|
|
94411
|
-
const crossesZone = zoneOf2(flow.from) !== zoneOf2(flow.to);
|
|
94412
|
-
const boundaryViolation = lint !== void 0 && trustLevelOf(flow.to) > trustLevelOf(flow.from) && !isSecurityNode(flow.from) && !isSecurityNode(flow.to);
|
|
94413
|
-
if (boundaryViolation) {
|
|
94414
|
-
diagnostics.push({
|
|
94415
|
-
code: lint.code,
|
|
94416
|
-
severity: "warning",
|
|
94417
|
-
message: lint.message,
|
|
94418
|
-
span: flow.span,
|
|
94419
|
-
note: `flow enters a more-trusted zone without passing a \`${lint.nodeKind}\``,
|
|
94420
|
-
help: lint.help
|
|
94421
|
-
});
|
|
94422
|
-
}
|
|
94423
|
-
if (view.crossZoneTechRecommended && crossesZone && !flow.tech?.protocol) {
|
|
94424
|
-
diagnostics.push({
|
|
94425
|
-
code: view.crossZoneTechRecommended.code,
|
|
94426
|
-
severity: "warning",
|
|
94427
|
-
message: view.crossZoneTechRecommended.message,
|
|
94428
|
-
span: flow.span,
|
|
94429
|
-
note: "inter-zone flow \u2014 state how the traffic is protected",
|
|
94430
|
-
help: view.crossZoneTechRecommended.help
|
|
94431
|
-
});
|
|
94432
|
-
}
|
|
94433
|
-
}
|
|
94434
|
-
return diagnostics;
|
|
94435
|
-
}
|
|
94436
94573
|
function checkForbiddenBusinessObjects(model, view) {
|
|
94437
94574
|
const diagnostics = [];
|
|
94438
94575
|
for (const businessObject of model.businessObjects) {
|
|
@@ -94591,6 +94728,8 @@ function editDistance(wordA, wordB, cap) {
|
|
|
94591
94728
|
var DEFAULT_FONT_SIZE_NODE = 12.5;
|
|
94592
94729
|
var FONT_SIZE_BASE = 12.5;
|
|
94593
94730
|
var CHAR_WIDTH = 0.56;
|
|
94731
|
+
var GLYPH_GUTTER = 26;
|
|
94732
|
+
var LOGO_GUTTER = 30;
|
|
94594
94733
|
var fontSizes = (base) => {
|
|
94595
94734
|
const scale = base / FONT_SIZE_BASE;
|
|
94596
94735
|
return {
|
|
@@ -94640,11 +94779,11 @@ var flowLabelBox = (opts) => {
|
|
|
94640
94779
|
height: measured.height + (tech ? 12 * scale : 0) + (chipNames.length ? CHIP_HEIGHT * scale : 0)
|
|
94641
94780
|
};
|
|
94642
94781
|
};
|
|
94643
|
-
var nodeSize = (kind, label, fontSize = DEFAULT_FONT_SIZE_NODE) => {
|
|
94782
|
+
var nodeSize = (kind, label, fontSize = DEFAULT_FONT_SIZE_NODE, gutter = 0) => {
|
|
94644
94783
|
const isActor = kind === "actor";
|
|
94645
94784
|
const measured = measure(label, isActor ? fontSize - 1.5 : fontSize);
|
|
94646
94785
|
return {
|
|
94647
|
-
width: isActor ? Math.max(64, measured.width + 8) : Math.max(140, measured.width + 16),
|
|
94786
|
+
width: isActor ? Math.max(64, measured.width + 8) : Math.max(140, measured.width + 16 + gutter),
|
|
94648
94787
|
height: isActor ? 56 + (label.split("\n").length - 1) * 11 : Math.max(46, measured.height + 18)
|
|
94649
94788
|
};
|
|
94650
94789
|
};
|
|
@@ -94672,12 +94811,13 @@ var LaneAllocator = class {
|
|
|
94672
94811
|
return this.lanes.length - 1;
|
|
94673
94812
|
}
|
|
94674
94813
|
};
|
|
94675
|
-
function foldStyle(model) {
|
|
94814
|
+
function foldStyle(model, view) {
|
|
94676
94815
|
const businessObjectNames = new Map(model.businessObjects.map((bo) => [bo.id, bo.name]));
|
|
94677
94816
|
const numbered = model.style.flowText === "numbered";
|
|
94678
94817
|
const { edge, node, cont, scale } = fontSizes(model.style.font.size);
|
|
94679
94818
|
return {
|
|
94680
94819
|
numbered,
|
|
94820
|
+
glyphKinds: new Set(view.glyphKinds ?? []),
|
|
94681
94821
|
edge,
|
|
94682
94822
|
node,
|
|
94683
94823
|
cont,
|
|
@@ -94692,7 +94832,15 @@ function foldStyle(model) {
|
|
|
94692
94832
|
})
|
|
94693
94833
|
};
|
|
94694
94834
|
}
|
|
94695
|
-
function
|
|
94835
|
+
function leafSize(element, style) {
|
|
94836
|
+
return nodeSize(
|
|
94837
|
+
element.kind,
|
|
94838
|
+
element.label ?? element.id,
|
|
94839
|
+
style.node,
|
|
94840
|
+
style.glyphKinds.has(element.kind) ? GLYPH_GUTTER : 0
|
|
94841
|
+
);
|
|
94842
|
+
}
|
|
94843
|
+
function toElkNode(element, style) {
|
|
94696
94844
|
if (element.children.length) {
|
|
94697
94845
|
const lineCount = (element.label ?? element.id).split("\n").length;
|
|
94698
94846
|
return {
|
|
@@ -94703,13 +94851,13 @@ function toElkNode(element, containerFontSize, nodeFontSize) {
|
|
|
94703
94851
|
labels: [
|
|
94704
94852
|
{
|
|
94705
94853
|
text: element.label ?? element.id,
|
|
94706
|
-
...measure(element.label ?? element.id,
|
|
94854
|
+
...measure(element.label ?? element.id, style.cont)
|
|
94707
94855
|
}
|
|
94708
94856
|
],
|
|
94709
|
-
children: element.children.map((child) => toElkNode(child,
|
|
94857
|
+
children: element.children.map((child) => toElkNode(child, style))
|
|
94710
94858
|
};
|
|
94711
94859
|
}
|
|
94712
|
-
const size =
|
|
94860
|
+
const size = leafSize(element, style);
|
|
94713
94861
|
return { id: element.id, width: size.width, height: size.height };
|
|
94714
94862
|
}
|
|
94715
94863
|
function walkFoldedNodes(elkNode, offset, elementById, syntheticIds) {
|
|
@@ -94788,7 +94936,7 @@ function internalFlowLabels(flow, style) {
|
|
|
94788
94936
|
];
|
|
94789
94937
|
}
|
|
94790
94938
|
function buildGroupGraph(group, style, fg) {
|
|
94791
|
-
const node = toElkNode(group, style
|
|
94939
|
+
const node = toElkNode(group, style);
|
|
94792
94940
|
const nodeChildren = node.children ??= [];
|
|
94793
94941
|
for (const flow of fg.interFlows) {
|
|
94794
94942
|
if (fg.rootOf.get(flow.from) === group) {
|
|
@@ -94846,7 +94994,7 @@ function buildGroupGraph(group, style, fg) {
|
|
|
94846
94994
|
function layoutColumn(elements, style) {
|
|
94847
94995
|
return elements.map((group) => {
|
|
94848
94996
|
const blocks = group.children.map((child) => {
|
|
94849
|
-
const size =
|
|
94997
|
+
const size = leafSize(child, style);
|
|
94850
94998
|
return { element: child, width: size.width, height: size.height, x: 0, y: 0 };
|
|
94851
94999
|
});
|
|
94852
95000
|
const columnWidth = Math.max(
|
|
@@ -94884,7 +95032,7 @@ function layoutMiddleRows(middles, middleResults, geom, style) {
|
|
|
94884
95032
|
let yCursor = 16 + geom.gutterHeight(0);
|
|
94885
95033
|
middles.forEach((element, index) => {
|
|
94886
95034
|
const result = middleResults.get(element.id) ?? null;
|
|
94887
|
-
const size = result ? { width: result.children[0].width, height: result.children[0].height } :
|
|
95035
|
+
const size = result ? { width: result.children[0].width, height: result.children[0].height } : leafSize(element, style);
|
|
94888
95036
|
rows.push({
|
|
94889
95037
|
element,
|
|
94890
95038
|
box: { x: geom.xMiddle, y: yCursor, width: size.width, height: size.height },
|
|
@@ -95048,7 +95196,7 @@ var sideMid = (box, side) => ({
|
|
|
95048
95196
|
});
|
|
95049
95197
|
async function foldedLayout(model, view, elk) {
|
|
95050
95198
|
const roots = model.elements;
|
|
95051
|
-
const style = foldStyle(model);
|
|
95199
|
+
const style = foldStyle(model, view);
|
|
95052
95200
|
const partitionOf = (element) => view.partitions[element.kind] ?? 1;
|
|
95053
95201
|
const sources = roots.filter((element) => partitionOf(element) === 0);
|
|
95054
95202
|
const middles = roots.filter((element) => partitionOf(element) === 1);
|
|
@@ -95095,7 +95243,7 @@ async function foldedLayout(model, view, elk) {
|
|
|
95095
95243
|
const widthSource = Math.max(0, ...sourceColumns.map((col) => col.width));
|
|
95096
95244
|
const widthMiddle = Math.max(
|
|
95097
95245
|
...middles.map(
|
|
95098
|
-
(element) => element.children.length ? middleResults.get(element.id).children[0].width :
|
|
95246
|
+
(element) => element.children.length ? middleResults.get(element.id).children[0].width : leafSize(element, style).width
|
|
95099
95247
|
)
|
|
95100
95248
|
);
|
|
95101
95249
|
const widthSink = Math.max(0, ...sinkColumns.map((col) => col.width));
|
|
@@ -95954,6 +96102,27 @@ function compactVertical(scene) {
|
|
|
95954
96102
|
}
|
|
95955
96103
|
scene.height = Math.ceil(heightAfter + bottomMargin);
|
|
95956
96104
|
}
|
|
96105
|
+
var CANVAS_MARGIN = 10;
|
|
96106
|
+
function fitCanvas(scene) {
|
|
96107
|
+
let maxX = 0;
|
|
96108
|
+
let maxY = 0;
|
|
96109
|
+
for (const node of scene.nodes) {
|
|
96110
|
+
maxX = Math.max(maxX, node.x + node.width);
|
|
96111
|
+
maxY = Math.max(maxY, node.y + node.height);
|
|
96112
|
+
}
|
|
96113
|
+
for (const edge of scene.edges) {
|
|
96114
|
+
for (const point of edge.pts) {
|
|
96115
|
+
maxX = Math.max(maxX, point.x);
|
|
96116
|
+
maxY = Math.max(maxY, point.y);
|
|
96117
|
+
}
|
|
96118
|
+
for (const label of edge.labels) {
|
|
96119
|
+
maxX = Math.max(maxX, label.x + label.width);
|
|
96120
|
+
maxY = Math.max(maxY, label.y + label.height);
|
|
96121
|
+
}
|
|
96122
|
+
}
|
|
96123
|
+
scene.width = Math.max(scene.width, Math.ceil(maxX) + CANVAS_MARGIN);
|
|
96124
|
+
scene.height = Math.max(scene.height, Math.ceil(maxY) + CANVAS_MARGIN);
|
|
96125
|
+
}
|
|
95957
96126
|
|
|
95958
96127
|
// src/readability.ts
|
|
95959
96128
|
var FAN_REACH = 48;
|
|
@@ -96085,8 +96254,7 @@ function labelSeatable(blockers, pts, label) {
|
|
|
96085
96254
|
function scanLabelSeats(ctx, subj, profile) {
|
|
96086
96255
|
for (const label of subj.edge.labels) {
|
|
96087
96256
|
if (!label.width || !label.height) continue;
|
|
96088
|
-
if (!labelSeatable(ctx.blockers, subj.pts, label))
|
|
96089
|
-
profile.set(`unlabelled:${subj.edge.id}`, 1);
|
|
96257
|
+
if (!labelSeatable(ctx.blockers, subj.pts, label)) profile.set(`unlabelled:${subj.edge.id}`, 1);
|
|
96090
96258
|
}
|
|
96091
96259
|
}
|
|
96092
96260
|
function scanArrowRoom(subj, profile) {
|
|
@@ -96159,8 +96327,7 @@ function scanCrossings(a, b, key, profile) {
|
|
|
96159
96327
|
if (!end) continue;
|
|
96160
96328
|
const dx = Math.max(0, end.node.x - hit.x, hit.x - (end.node.x + end.node.width));
|
|
96161
96329
|
const dy = Math.max(0, end.node.y - hit.y, hit.y - (end.node.y + end.node.height));
|
|
96162
|
-
if (dx * dx + dy * dy <= FAN_REACH * FAN_REACH)
|
|
96163
|
-
profile.set(`fan:${key}@${end.node.id}`, 2);
|
|
96330
|
+
if (dx * dx + dy * dy <= FAN_REACH * FAN_REACH) profile.set(`fan:${key}@${end.node.id}`, 2);
|
|
96164
96331
|
}
|
|
96165
96332
|
}
|
|
96166
96333
|
}
|
|
@@ -96188,8 +96355,7 @@ function scanSharedSeats(a, b, key, profile) {
|
|
|
96188
96355
|
}
|
|
96189
96356
|
const side = vertical ? seatA.node.height : seatA.node.width;
|
|
96190
96357
|
const need = Math.min(12, (side - 6) / 2);
|
|
96191
|
-
if (apart < need * 0.8)
|
|
96192
|
-
profile.set(`tight:${key}@${seatA.node.id}|${seatA.side}`, 4);
|
|
96358
|
+
if (apart < need * 0.8) profile.set(`tight:${key}@${seatA.node.id}|${seatA.side}`, 4);
|
|
96193
96359
|
}
|
|
96194
96360
|
}
|
|
96195
96361
|
function scanPairs(ctx, subj, query) {
|
|
@@ -96204,7 +96370,11 @@ function scanPairs(ctx, subj, query) {
|
|
|
96204
96370
|
if (ids.has(other.id) && other.id < subj.edge.id) continue;
|
|
96205
96371
|
const overridden = overrides.has(other.id);
|
|
96206
96372
|
if (farApart(myBounds, ctx.boundsFor(other, theirs, overridden))) continue;
|
|
96207
|
-
const them = {
|
|
96373
|
+
const them = {
|
|
96374
|
+
edge: other,
|
|
96375
|
+
pts: theirs,
|
|
96376
|
+
ends: ctx.endsFor(other, theirs, overridden)
|
|
96377
|
+
};
|
|
96208
96378
|
const key = pair(subj.edge.id, other.id);
|
|
96209
96379
|
scanCrossings(subj, them, key, profile);
|
|
96210
96380
|
scanParallelRuns(mine, ctx.runsFor(other, theirs, overridden), key, profile);
|
|
@@ -96271,6 +96441,7 @@ function ladderVerdict(before, after) {
|
|
|
96271
96441
|
}
|
|
96272
96442
|
|
|
96273
96443
|
// src/edge-tidy.ts
|
|
96444
|
+
var sideFixed = (edge, end) => !!(edge.pinned?.[end] || edge.hubSided?.[end]);
|
|
96274
96445
|
var ORTHOGONAL_EPSILON = 0.5;
|
|
96275
96446
|
var MIN_HUG_SPAN = 24;
|
|
96276
96447
|
var CHANNEL_INSET = 24;
|
|
@@ -98664,8 +98835,8 @@ function optimiseRoutes(scene, titleBoxes = [], folded = false) {
|
|
|
98664
98835
|
const subject = { ends, edge };
|
|
98665
98836
|
const out = [];
|
|
98666
98837
|
const seen = /* @__PURE__ */ new Set();
|
|
98667
|
-
const aSides = edge
|
|
98668
|
-
const bSides = edge
|
|
98838
|
+
const aSides = sideFixed(edge, "start") ? [ends[0].side] : SIDES;
|
|
98839
|
+
const bSides = sideFixed(edge, "end") ? [ends[1].side] : SIDES;
|
|
98669
98840
|
for (const aSide of aSides)
|
|
98670
98841
|
for (const bSide of bSides) {
|
|
98671
98842
|
const sides = { a: aSide, b: bSide };
|
|
@@ -99001,7 +99172,8 @@ function computeIngressExternalElements(model) {
|
|
|
99001
99172
|
}
|
|
99002
99173
|
var orderOption = (element) => element.order ? { "elk.position": `(0,${element.order.value})` } : {};
|
|
99003
99174
|
var semiInteractiveOption = (children) => children.some((child) => child.order) ? { "elk.layered.crossingMinimization.semiInteractive": "true" } : {};
|
|
99004
|
-
function toElkNode2(element,
|
|
99175
|
+
function toElkNode2(element, sizing, root = false) {
|
|
99176
|
+
const { compact, fonts, glyphKinds } = sizing;
|
|
99005
99177
|
const { cont: containerFontSize, node: nodeFontSize } = fonts;
|
|
99006
99178
|
if (element.children.length) {
|
|
99007
99179
|
const lineCount = (element.label ?? element.id).split("\n").length;
|
|
@@ -99018,17 +99190,16 @@ function toElkNode2(element, compact, fonts, root = false) {
|
|
|
99018
99190
|
...measure(element.label ?? element.id, containerFontSize)
|
|
99019
99191
|
}
|
|
99020
99192
|
],
|
|
99021
|
-
children: element.children.map(
|
|
99022
|
-
(child) => toElkNode2(child, compact, fonts)
|
|
99023
|
-
)
|
|
99193
|
+
children: element.children.map((child) => toElkNode2(child, sizing))
|
|
99024
99194
|
};
|
|
99025
99195
|
}
|
|
99026
99196
|
const measured = measure(element.label ?? element.id, nodeFontSize);
|
|
99027
99197
|
const isActor = element.kind === "actor";
|
|
99198
|
+
const gutter = (glyphKinds.has(element.kind) ? GLYPH_GUTTER : 0) + (element.logo ? LOGO_GUTTER : 0);
|
|
99028
99199
|
return {
|
|
99029
99200
|
id: element.id,
|
|
99030
99201
|
...element.order && !root ? { layoutOptions: orderOption(element) } : {},
|
|
99031
|
-
width: isActor ? Math.max(64, measure(element.label ?? element.id, nodeFontSize - 1.5).width + 8) : Math.max(compact ? 98 : 108, measured.width + (compact ? 10 : 12)),
|
|
99202
|
+
width: isActor ? Math.max(64, measure(element.label ?? element.id, nodeFontSize - 1.5).width + 8) : Math.max(compact ? 98 : 108, measured.width + (compact ? 10 : 12) + gutter),
|
|
99032
99203
|
height: isActor ? 54 + ((element.label ?? element.id).split("\n").length - 1) * 11 : Math.max(compact ? 36 : 38, measured.height + (compact ? 10 : 12))
|
|
99033
99204
|
};
|
|
99034
99205
|
}
|
|
@@ -99187,20 +99358,20 @@ function selectionExtras(scene, model) {
|
|
|
99187
99358
|
}
|
|
99188
99359
|
return extra;
|
|
99189
99360
|
}
|
|
99190
|
-
function
|
|
99361
|
+
function tallyProfile(profile) {
|
|
99191
99362
|
const normalize = (key) => key.replace(/@[-\d.,]+$/, "").replace(/:\d+(?=@|$)/, "");
|
|
99192
|
-
const
|
|
99193
|
-
|
|
99194
|
-
|
|
99195
|
-
|
|
99196
|
-
|
|
99197
|
-
|
|
99198
|
-
|
|
99199
|
-
|
|
99200
|
-
|
|
99201
|
-
|
|
99202
|
-
const was =
|
|
99203
|
-
const now =
|
|
99363
|
+
const out = /* @__PURE__ */ new Map();
|
|
99364
|
+
for (const [key, tier] of profile) {
|
|
99365
|
+
const id = normalize(key);
|
|
99366
|
+
const entry = out.get(id) ?? { tier, count: 0 };
|
|
99367
|
+
entry.count++;
|
|
99368
|
+
out.set(id, entry);
|
|
99369
|
+
}
|
|
99370
|
+
return out;
|
|
99371
|
+
}
|
|
99372
|
+
function relayoutVerdict(before, after) {
|
|
99373
|
+
const was = tallyProfile(before);
|
|
99374
|
+
const now = tallyProfile(after);
|
|
99204
99375
|
for (let tier = 0; tier < 5; tier++) {
|
|
99205
99376
|
let gained = false;
|
|
99206
99377
|
let lost = false;
|
|
@@ -99216,6 +99387,62 @@ function relayoutVerdict(before, after) {
|
|
|
99216
99387
|
}
|
|
99217
99388
|
return -1;
|
|
99218
99389
|
}
|
|
99390
|
+
function noLadderRegression(before, after) {
|
|
99391
|
+
const perTier = (profile) => {
|
|
99392
|
+
const totals = [0, 0, 0, 0, 0];
|
|
99393
|
+
for (const { tier, count } of tallyProfile(profile).values()) totals[tier] += count;
|
|
99394
|
+
return totals;
|
|
99395
|
+
};
|
|
99396
|
+
const was = perTier(before);
|
|
99397
|
+
const now = perTier(after);
|
|
99398
|
+
return now.every((count, tier) => count <= was[tier]);
|
|
99399
|
+
}
|
|
99400
|
+
function nodeCoverage(scene) {
|
|
99401
|
+
if (!scene.nodes.length) return 1;
|
|
99402
|
+
const left = Math.min(...scene.nodes.map((n) => n.x));
|
|
99403
|
+
const top = Math.min(...scene.nodes.map((n) => n.y));
|
|
99404
|
+
const right = Math.max(...scene.nodes.map((n) => n.x + n.width));
|
|
99405
|
+
const bottom = Math.max(...scene.nodes.map((n) => n.y + n.height));
|
|
99406
|
+
const width = right - left;
|
|
99407
|
+
const height = bottom - top;
|
|
99408
|
+
if (width <= 0 || height <= 0) return 1;
|
|
99409
|
+
const COLUMNS = 32;
|
|
99410
|
+
const ROWS = 16;
|
|
99411
|
+
let covered = 0;
|
|
99412
|
+
for (let row = 0; row < ROWS; row++) {
|
|
99413
|
+
for (let column = 0; column < COLUMNS; column++) {
|
|
99414
|
+
const cellLeft = left + column * width / COLUMNS;
|
|
99415
|
+
const cellRight = left + (column + 1) * width / COLUMNS;
|
|
99416
|
+
const cellTop = top + row * height / ROWS;
|
|
99417
|
+
const cellBottom = top + (row + 1) * height / ROWS;
|
|
99418
|
+
if (scene.nodes.some(
|
|
99419
|
+
(n) => n.x < cellRight && n.x + n.width > cellLeft && n.y < cellBottom && n.y + n.height > cellTop
|
|
99420
|
+
))
|
|
99421
|
+
covered++;
|
|
99422
|
+
}
|
|
99423
|
+
}
|
|
99424
|
+
return covered / (COLUMNS * ROWS);
|
|
99425
|
+
}
|
|
99426
|
+
async function denserLayout(base, elkPass) {
|
|
99427
|
+
const densitySpecs = [
|
|
99428
|
+
{ minLayers: true, dense: true },
|
|
99429
|
+
{ placement: "LINEAR_SEGMENTS", dense: true }
|
|
99430
|
+
];
|
|
99431
|
+
const laidOut = await Promise.allSettled(densitySpecs.map((spec) => elkPass.layout(spec)));
|
|
99432
|
+
const areaOf = (scene) => scene.width * scene.height;
|
|
99433
|
+
const baseProfile = elkPass.profile(base);
|
|
99434
|
+
let bestArea = areaOf(base) * DENSITY_GAIN;
|
|
99435
|
+
let winner = null;
|
|
99436
|
+
for (const [index, settled] of laidOut.entries()) {
|
|
99437
|
+
if (settled.status !== "fulfilled") continue;
|
|
99438
|
+
const candidate = elkPass.toScene(settled.value);
|
|
99439
|
+
if (areaOf(candidate) > bestArea) continue;
|
|
99440
|
+
if (!noLadderRegression(baseProfile, elkPass.profile(candidate))) continue;
|
|
99441
|
+
bestArea = areaOf(candidate);
|
|
99442
|
+
winner = { scene: candidate, options: densitySpecs[index] };
|
|
99443
|
+
}
|
|
99444
|
+
return winner;
|
|
99445
|
+
}
|
|
99219
99446
|
var centerOf = (n) => ({ x: n.x + n.width / 2, y: n.y + n.height / 2 });
|
|
99220
99447
|
function sideToward(from, to) {
|
|
99221
99448
|
const dx = centerOf(to).x - centerOf(from).x;
|
|
@@ -99277,13 +99504,16 @@ function constrainPorts(graph, scene, flagged, model) {
|
|
|
99277
99504
|
elkNode.ports = [...elkNode.ports ?? [], ...ports];
|
|
99278
99505
|
}
|
|
99279
99506
|
}
|
|
99507
|
+
var DENSE_ENOUGH = 0.6;
|
|
99508
|
+
var DENSITY_GAIN = 0.95;
|
|
99280
99509
|
var INGRESS_PARTITION = -1;
|
|
99510
|
+
var DEFAULT_INGRESS_KINDS = ["actor", "actor-group"];
|
|
99281
99511
|
var EGRESS_PARTITION = 900;
|
|
99282
99512
|
var COMPACT_WRAP = 10;
|
|
99283
99513
|
var SLOT_SCALE = 1e3;
|
|
99284
99514
|
function elkPartitionOf(element, index, view, ingressExternal) {
|
|
99285
99515
|
if (!view.partitionByOrder) return view.partitions[element.kind] ?? 1;
|
|
99286
|
-
if (
|
|
99516
|
+
if ((view.ingressKinds ?? DEFAULT_INGRESS_KINDS).includes(element.kind)) return INGRESS_PARTITION;
|
|
99287
99517
|
if (element.kind === "external")
|
|
99288
99518
|
return ingressExternal.has(element.id) ? INGRESS_PARTITION : EGRESS_PARTITION;
|
|
99289
99519
|
if (view.partitions[element.kind] !== void 0) return 90 + view.partitions[element.kind];
|
|
@@ -99307,16 +99537,13 @@ function readingSlots(model, view, ingressExternal) {
|
|
|
99307
99537
|
const lowestOf = /* @__PURE__ */ new Map();
|
|
99308
99538
|
for (const band of new Set(bandOf.values())) {
|
|
99309
99539
|
const members = model.elements.filter((element) => bandOf.get(element.id) === band);
|
|
99310
|
-
const declared = [
|
|
99311
|
-
|
|
99312
|
-
|
|
99540
|
+
const declared = [...new Set(members.filter((m) => m.order).map((m) => m.order.value))].sort(
|
|
99541
|
+
(a, b) => a - b
|
|
99542
|
+
);
|
|
99313
99543
|
const lowest = declared.length ? 1 : 0;
|
|
99314
99544
|
lowestOf.set(band, lowest);
|
|
99315
99545
|
for (const member of members)
|
|
99316
|
-
slotOf.set(
|
|
99317
|
-
member.id,
|
|
99318
|
-
member.order ? declared.indexOf(member.order.value) + 1 : lowest
|
|
99319
|
-
);
|
|
99546
|
+
slotOf.set(member.id, member.order ? declared.indexOf(member.order.value) + 1 : lowest);
|
|
99320
99547
|
}
|
|
99321
99548
|
const ordered = new Set(model.elements.filter((element) => element.order).map((e) => e.id));
|
|
99322
99549
|
for (let pass = 0; pass < model.elements.length; pass++) {
|
|
@@ -99335,13 +99562,15 @@ function readingSlots(model, view, ingressExternal) {
|
|
|
99335
99562
|
}
|
|
99336
99563
|
return slotOf;
|
|
99337
99564
|
}
|
|
99565
|
+
function elkEnds(flow) {
|
|
99566
|
+
return laidOutReversed(flow) ? { sources: [flow.to], targets: [flow.from] } : { sources: [flow.from], targets: [flow.to] };
|
|
99567
|
+
}
|
|
99338
99568
|
function elkFlowEdge(flow, ctx, labelWrap) {
|
|
99339
99569
|
const { compact, numbered, fonts, businessObjectName } = ctx;
|
|
99340
99570
|
if (numbered)
|
|
99341
99571
|
return {
|
|
99342
99572
|
id: flow.id,
|
|
99343
|
-
|
|
99344
|
-
targets: [flow.to],
|
|
99573
|
+
...elkEnds(flow),
|
|
99345
99574
|
labels: [
|
|
99346
99575
|
{
|
|
99347
99576
|
text: String(parseInt(flow.id.slice(1), 10)),
|
|
@@ -99366,8 +99595,7 @@ function elkFlowEdge(flow, ctx, labelWrap) {
|
|
|
99366
99595
|
});
|
|
99367
99596
|
return {
|
|
99368
99597
|
id: flow.id,
|
|
99369
|
-
|
|
99370
|
-
targets: [flow.to],
|
|
99598
|
+
...elkEnds(flow),
|
|
99371
99599
|
labels: text || chips.length ? [{ text, ...labelBox }] : []
|
|
99372
99600
|
};
|
|
99373
99601
|
}
|
|
@@ -99377,8 +99605,32 @@ var SIDE_TO_ELK = {
|
|
|
99377
99605
|
top: "NORTH",
|
|
99378
99606
|
bottom: "SOUTH"
|
|
99379
99607
|
};
|
|
99380
|
-
function
|
|
99381
|
-
|
|
99608
|
+
function laidOutReversed(flow) {
|
|
99609
|
+
return flow.fromRole?.value === "consumer" || flow.toRole?.value === "producer";
|
|
99610
|
+
}
|
|
99611
|
+
function roleCap(role) {
|
|
99612
|
+
if (!role) return null;
|
|
99613
|
+
return role.value === "producer" ? "left" : "right";
|
|
99614
|
+
}
|
|
99615
|
+
function hubFlowSides(model, view) {
|
|
99616
|
+
const derived = /* @__PURE__ */ new Map();
|
|
99617
|
+
const hubKinds = new Set(view.hubKinds ?? []);
|
|
99618
|
+
if (!hubKinds.size) return derived;
|
|
99619
|
+
const hubs = new Set(
|
|
99620
|
+
indexElementsById(model.elements).filter(([, element]) => hubKinds.has(element.kind)).map(([id]) => id)
|
|
99621
|
+
);
|
|
99622
|
+
if (!hubs.size) return derived;
|
|
99623
|
+
for (const flow of model.flows) {
|
|
99624
|
+
const sides = {};
|
|
99625
|
+
if (hubs.has(flow.to) && !flow.toSide) sides.to = roleCap(flow.fromRole) ?? "left";
|
|
99626
|
+
if (hubs.has(flow.from) && !flow.fromSide) sides.from = roleCap(flow.toRole) ?? "right";
|
|
99627
|
+
if (sides.to || sides.from) derived.set(flow.id, sides);
|
|
99628
|
+
}
|
|
99629
|
+
return derived;
|
|
99630
|
+
}
|
|
99631
|
+
var sideRequest = (side) => side ? { value: side } : void 0;
|
|
99632
|
+
function applyDeclaredPorts(graph, model, derived) {
|
|
99633
|
+
const pinned = model.flows.filter((flow) => flow.fromSide || flow.toSide || derived.has(flow.id));
|
|
99382
99634
|
if (!pinned.length) return;
|
|
99383
99635
|
const elkById = /* @__PURE__ */ new Map();
|
|
99384
99636
|
const register = (node) => {
|
|
@@ -99389,14 +99641,15 @@ function applyDeclaredPorts(graph, model) {
|
|
|
99389
99641
|
for (const flow of pinned) {
|
|
99390
99642
|
const elkEdge = (graph.edges ?? []).find((edge) => edge.id === flow.id);
|
|
99391
99643
|
if (!elkEdge) continue;
|
|
99644
|
+
const hub = derived.get(flow.id);
|
|
99392
99645
|
for (const [role, declared, nodeId] of [
|
|
99393
|
-
["out", flow.fromSide, flow.from],
|
|
99394
|
-
["in", flow.toSide, flow.to]
|
|
99646
|
+
["out", flow.fromSide ?? sideRequest(hub?.from), flow.from],
|
|
99647
|
+
["in", flow.toSide ?? sideRequest(hub?.to), flow.to]
|
|
99395
99648
|
]) {
|
|
99396
99649
|
if (!declared) continue;
|
|
99397
99650
|
const elkNode = elkById.get(nodeId);
|
|
99398
99651
|
if (!elkNode) continue;
|
|
99399
|
-
const portId = `${flow.id}#${role}`;
|
|
99652
|
+
const portId = `${flow.id}#${role === "out" !== laidOutReversed(flow) ? "out" : "in"}`;
|
|
99400
99653
|
elkNode.ports = [
|
|
99401
99654
|
...elkNode.ports ?? [],
|
|
99402
99655
|
{
|
|
@@ -99407,7 +99660,7 @@ function applyDeclaredPorts(graph, model) {
|
|
|
99407
99660
|
}
|
|
99408
99661
|
];
|
|
99409
99662
|
elkNode.layoutOptions = { ...elkNode.layoutOptions, "elk.portConstraints": "FIXED_SIDE" };
|
|
99410
|
-
if (role === "out") elkEdge.sources = [portId];
|
|
99663
|
+
if (role === "out" !== laidOutReversed(flow)) elkEdge.sources = [portId];
|
|
99411
99664
|
else elkEdge.targets = [portId];
|
|
99412
99665
|
}
|
|
99413
99666
|
}
|
|
@@ -99452,6 +99705,7 @@ function attachSideDiagnostics(scene, model) {
|
|
|
99452
99705
|
}
|
|
99453
99706
|
function buildElkGraph(ctx, direction, options) {
|
|
99454
99707
|
const { model, view, ingressExternal, slotOf, compact, numbered, fonts } = ctx;
|
|
99708
|
+
const glyphKinds = new Set(view.glyphKinds ?? []);
|
|
99455
99709
|
const graph = {
|
|
99456
99710
|
id: "root",
|
|
99457
99711
|
layoutOptions: {
|
|
@@ -99468,7 +99722,7 @@ function buildElkGraph(ctx, direction, options) {
|
|
|
99468
99722
|
"elk.edgeRouting": "ORTHOGONAL",
|
|
99469
99723
|
"elk.partitioning.activate": "true",
|
|
99470
99724
|
"elk.layered.nodePlacement.strategy": "NETWORK_SIMPLEX",
|
|
99471
|
-
"elk.layered.compaction.postCompaction.strategy": "EDGE_LENGTH",
|
|
99725
|
+
"elk.layered.compaction.postCompaction.strategy": options?.postCompaction ?? "EDGE_LENGTH",
|
|
99472
99726
|
"elk.layered.feedbackEdges": "true",
|
|
99473
99727
|
"elk.layered.thoroughness": "30",
|
|
99474
99728
|
"elk.separateConnectedComponents": "false",
|
|
@@ -99487,25 +99741,38 @@ function buildElkGraph(ctx, direction, options) {
|
|
|
99487
99741
|
"elk.spacing.edgeNode": "18",
|
|
99488
99742
|
"elk.layered.thoroughness": "80",
|
|
99489
99743
|
"elk.layered.nodePlacement.favorStraightEdges": "true"
|
|
99490
|
-
} : {}
|
|
99744
|
+
} : {},
|
|
99745
|
+
// Spread last, after every spacing default above, because overriding them
|
|
99746
|
+
// is the whole point — a density candidate that lands before them is
|
|
99747
|
+
// silently shadowed and lays out exactly like the layout it was meant to
|
|
99748
|
+
// beat.
|
|
99749
|
+
...options?.dense ? {
|
|
99750
|
+
"elk.layered.spacing.nodeNodeBetweenLayers": "14",
|
|
99751
|
+
"elk.spacing.nodeNode": "10",
|
|
99752
|
+
"elk.spacing.edgeEdge": "8",
|
|
99753
|
+
"elk.spacing.edgeNode": "9"
|
|
99754
|
+
} : {},
|
|
99755
|
+
...options?.placement ? { "elk.layered.nodePlacement.strategy": options.placement } : {}
|
|
99491
99756
|
},
|
|
99492
99757
|
children: model.elements.map((element, index) => {
|
|
99493
|
-
const elkNode = toElkNode2(element, compact, fonts, true);
|
|
99758
|
+
const elkNode = toElkNode2(element, { compact, fonts, glyphKinds }, true);
|
|
99494
99759
|
const band = elkPartitionOf(element, index, view, ingressExternal);
|
|
99495
99760
|
const slot = slotOf.get(element.id);
|
|
99496
99761
|
elkNode.layoutOptions = {
|
|
99497
99762
|
...elkNode.layoutOptions,
|
|
99498
99763
|
// Without an `order:` anywhere the band is emitted as it always was, so
|
|
99499
99764
|
// the drawing is byte-identical to one from before the hint existed.
|
|
99500
|
-
"elk.partitioning.partition": String(
|
|
99501
|
-
slot === void 0 ? band : band * SLOT_SCALE + slot
|
|
99502
|
-
)
|
|
99765
|
+
"elk.partitioning.partition": String(slot === void 0 ? band : band * SLOT_SCALE + slot)
|
|
99503
99766
|
};
|
|
99504
99767
|
return elkNode;
|
|
99505
99768
|
}),
|
|
99506
99769
|
edges: model.flows.map((flow) => elkFlowEdge(flow, ctx, options?.labelWrap))
|
|
99507
99770
|
};
|
|
99508
|
-
applyDeclaredPorts(
|
|
99771
|
+
applyDeclaredPorts(
|
|
99772
|
+
graph,
|
|
99773
|
+
model,
|
|
99774
|
+
options?.hubPorts === false ? /* @__PURE__ */ new Map() : hubFlowSides(model, view)
|
|
99775
|
+
);
|
|
99509
99776
|
return graph;
|
|
99510
99777
|
}
|
|
99511
99778
|
function recordRepairs(scene, routesBefore) {
|
|
@@ -99518,8 +99785,127 @@ function recordRepairs(scene, routesBefore) {
|
|
|
99518
99785
|
if (moved) edge.repairedFrom = original;
|
|
99519
99786
|
}
|
|
99520
99787
|
}
|
|
99788
|
+
function segmentsCross2(a1, a2, b1, b2) {
|
|
99789
|
+
const aH = Math.abs(a1.y - a2.y) < 0.5;
|
|
99790
|
+
const bH = Math.abs(b1.y - b2.y) < 0.5;
|
|
99791
|
+
if (aH === bH) return false;
|
|
99792
|
+
const [h1, h2, v1, v2] = aH ? [a1, a2, b1, b2] : [b1, b2, a1, a2];
|
|
99793
|
+
const hy = h1.y;
|
|
99794
|
+
const vx = v1.x;
|
|
99795
|
+
return vx > Math.min(h1.x, h2.x) + 0.5 && vx < Math.max(h1.x, h2.x) - 0.5 && hy > Math.min(v1.y, v2.y) + 0.5 && hy < Math.max(v1.y, v2.y) - 0.5;
|
|
99796
|
+
}
|
|
99797
|
+
function shortJogs(edges) {
|
|
99798
|
+
let total = 0;
|
|
99799
|
+
for (const edge of edges)
|
|
99800
|
+
for (let i = 1; i + 2 < edge.pts.length; i++) {
|
|
99801
|
+
const run = Math.abs(edge.pts[i + 1].x - edge.pts[i].x) + Math.abs(edge.pts[i + 1].y - edge.pts[i].y);
|
|
99802
|
+
if (run > 0 && run <= 20) total++;
|
|
99803
|
+
}
|
|
99804
|
+
return total;
|
|
99805
|
+
}
|
|
99806
|
+
function crossingsAround(scene, subject) {
|
|
99807
|
+
let total = 0;
|
|
99808
|
+
const subjectIds = new Set(subject.map((edge) => edge.id));
|
|
99809
|
+
for (const edge of subject)
|
|
99810
|
+
for (const other of scene.edges) {
|
|
99811
|
+
if (other.id === edge.id) continue;
|
|
99812
|
+
if (subjectIds.has(other.id) && other.id < edge.id) continue;
|
|
99813
|
+
for (let i = 1; i < edge.pts.length; i++)
|
|
99814
|
+
for (let j = 1; j < other.pts.length; j++)
|
|
99815
|
+
if (segmentsCross2(edge.pts[i - 1], edge.pts[i], other.pts[j - 1], other.pts[j])) total++;
|
|
99816
|
+
}
|
|
99817
|
+
return total;
|
|
99818
|
+
}
|
|
99819
|
+
function leafBoxesOf(scene) {
|
|
99820
|
+
return scene.nodes.filter((node) => !node.container);
|
|
99821
|
+
}
|
|
99822
|
+
function crossesLeaf(edge, leaves, attached) {
|
|
99823
|
+
for (let i = 1; i < edge.pts.length; i++) {
|
|
99824
|
+
const a = edge.pts[i - 1];
|
|
99825
|
+
const b = edge.pts[i];
|
|
99826
|
+
const horizontal = Math.abs(a.y - b.y) < 0.5;
|
|
99827
|
+
const vertical = Math.abs(a.x - b.x) < 0.5;
|
|
99828
|
+
if (!horizontal && !vertical) continue;
|
|
99829
|
+
const at = horizontal ? a.y : a.x;
|
|
99830
|
+
const lo = horizontal ? Math.min(a.x, b.x) : Math.min(a.y, b.y);
|
|
99831
|
+
const hi = horizontal ? Math.max(a.x, b.x) : Math.max(a.y, b.y);
|
|
99832
|
+
for (const node of leaves) {
|
|
99833
|
+
if (attached.has(node.id)) continue;
|
|
99834
|
+
const struck = horizontal ? at > node.y + 1 && at < node.y + node.height - 1 && lo < node.x + node.width - 1 && hi > node.x + 1 : at > node.x + 1 && at < node.x + node.width - 1 && lo < node.y + node.height - 1 && hi > node.y + 1;
|
|
99835
|
+
if (struck) return true;
|
|
99836
|
+
}
|
|
99837
|
+
}
|
|
99838
|
+
return false;
|
|
99839
|
+
}
|
|
99840
|
+
function snapLanes(scene, laneOf, axis) {
|
|
99841
|
+
if (!laneOf.size) return;
|
|
99842
|
+
const leaves = leafBoxesOf(scene);
|
|
99843
|
+
const tilted = (edges) => edges.reduce(
|
|
99844
|
+
(total, edge) => total + edge.pts.filter(
|
|
99845
|
+
(point, i) => i > 0 && Math.abs(point.x - edge.pts[i - 1].x) >= 0.5 && Math.abs(point.y - edge.pts[i - 1].y) >= 0.5
|
|
99846
|
+
).length,
|
|
99847
|
+
0
|
|
99848
|
+
);
|
|
99849
|
+
const touching = /* @__PURE__ */ new Map();
|
|
99850
|
+
const attachedTo = /* @__PURE__ */ new Map();
|
|
99851
|
+
for (const edge of scene.edges) {
|
|
99852
|
+
const ends = /* @__PURE__ */ new Set();
|
|
99853
|
+
for (const point of [edge.pts[0], edge.pts[edge.pts.length - 1]]) {
|
|
99854
|
+
if (!point) continue;
|
|
99855
|
+
for (const node of scene.nodes)
|
|
99856
|
+
if (point.x >= node.x - 1 && point.x <= node.x + node.width + 1 && point.y >= node.y - 1 && point.y <= node.y + node.height + 1) {
|
|
99857
|
+
ends.add(node.id);
|
|
99858
|
+
if (!touching.has(node.id)) touching.set(node.id, []);
|
|
99859
|
+
touching.get(node.id).push(edge);
|
|
99860
|
+
}
|
|
99861
|
+
}
|
|
99862
|
+
attachedTo.set(edge.id, ends);
|
|
99863
|
+
}
|
|
99864
|
+
const byLane = /* @__PURE__ */ new Map();
|
|
99865
|
+
for (const node of scene.nodes) {
|
|
99866
|
+
const lane = laneOf.get(node.id);
|
|
99867
|
+
if (lane === void 0) continue;
|
|
99868
|
+
if (!byLane.has(lane)) byLane.set(lane, []);
|
|
99869
|
+
byLane.get(lane).push(node);
|
|
99870
|
+
}
|
|
99871
|
+
for (const members of [...byLane.entries()].sort((a, b) => a[0] - b[0]).map((e) => e[1])) {
|
|
99872
|
+
if (members.length < 2) continue;
|
|
99873
|
+
const target = Math.max(...members.map((node) => node[axis]));
|
|
99874
|
+
for (const node of members) {
|
|
99875
|
+
const delta = target - node[axis];
|
|
99876
|
+
if (!delta) continue;
|
|
99877
|
+
const box = { x: node.x, y: node.y, w: node.width, h: node.height };
|
|
99878
|
+
const edges = touching.get(node.id) ?? [];
|
|
99879
|
+
const before = edges.map((edge) => edge.pts.map((point) => ({ ...point })));
|
|
99880
|
+
const crossingsBefore = crossingsAround(scene, edges);
|
|
99881
|
+
const jogsBefore = shortJogs(edges);
|
|
99882
|
+
const tiltsBefore = tilted(edges);
|
|
99883
|
+
node[axis] = target;
|
|
99884
|
+
for (const edge of edges)
|
|
99885
|
+
for (const point of edge.pts)
|
|
99886
|
+
if (point.x >= box.x - 1 && point.x <= box.x + box.w + 1 && point.y >= box.y - 1 && point.y <= box.y + box.h + 1)
|
|
99887
|
+
point[axis] += delta;
|
|
99888
|
+
const broke = crossingsAround(scene, edges) > crossingsBefore || shortJogs(edges) > jogsBefore || tilted(edges) > tiltsBefore || edges.some((edge) => crossesLeaf(edge, leaves, attachedTo.get(edge.id) ?? /* @__PURE__ */ new Set())) || // Containers included: a lane member is top-level, so it has no
|
|
99889
|
+
// legitimate container ancestor and may not land on one.
|
|
99890
|
+
scene.nodes.some(
|
|
99891
|
+
(other) => other !== node && !node.container && other.x < node.x + node.width && node.x < other.x + other.width && other.y < node.y + node.height && node.y < other.y + other.height
|
|
99892
|
+
);
|
|
99893
|
+
if (broke) {
|
|
99894
|
+
node[axis] = target - delta;
|
|
99895
|
+
edges.forEach((edge, i) => {
|
|
99896
|
+
edge.pts = before[i];
|
|
99897
|
+
});
|
|
99898
|
+
}
|
|
99899
|
+
}
|
|
99900
|
+
}
|
|
99901
|
+
const maxX = Math.max(...scene.nodes.map((node) => node.x + node.width));
|
|
99902
|
+
const maxY = Math.max(...scene.nodes.map((node) => node.y + node.height));
|
|
99903
|
+
scene.width = Math.max(scene.width, Math.ceil(maxX) + 10);
|
|
99904
|
+
scene.height = Math.max(scene.height, Math.ceil(maxY) + 10);
|
|
99905
|
+
}
|
|
99521
99906
|
function runGeometryPasses(scene, model, options) {
|
|
99522
99907
|
const { numbered, sideways } = options;
|
|
99908
|
+
if (options.laneOf) snapLanes(scene, options.laneOf, sideways ? "y" : "x");
|
|
99523
99909
|
const titleBoxes = titleBoxesOf(scene, model);
|
|
99524
99910
|
if (sideways) transpose(scene, titleBoxes);
|
|
99525
99911
|
rerouteDetours(scene, model, numbered, titleBoxes);
|
|
@@ -99538,6 +99924,99 @@ function runGeometryPasses(scene, model, options) {
|
|
|
99538
99924
|
clearSideHugs(scene, settledTitles);
|
|
99539
99925
|
anchorFlowLabels(scene, settledTitles);
|
|
99540
99926
|
swapCrossingSiblingSeats(scene);
|
|
99927
|
+
fitCanvas(scene);
|
|
99928
|
+
}
|
|
99929
|
+
function laneAssignment(model, view) {
|
|
99930
|
+
const laneOf = /* @__PURE__ */ new Map();
|
|
99931
|
+
const laneKinds = new Set(view.laneKinds ?? []);
|
|
99932
|
+
if (!laneKinds.size || model.style.compact) return laneOf;
|
|
99933
|
+
const rootOf = /* @__PURE__ */ new Map();
|
|
99934
|
+
const walk = (element, root) => {
|
|
99935
|
+
rootOf.set(element.id, root);
|
|
99936
|
+
for (const child of element.children ?? []) walk(child, root);
|
|
99937
|
+
};
|
|
99938
|
+
for (const element of model.elements) walk(element, element.id);
|
|
99939
|
+
const adjacency = /* @__PURE__ */ new Map();
|
|
99940
|
+
for (const flow of model.flows) {
|
|
99941
|
+
const from = rootOf.get(flow.from);
|
|
99942
|
+
const to = rootOf.get(flow.to);
|
|
99943
|
+
if (!from || !to || from === to) continue;
|
|
99944
|
+
if (!adjacency.has(from)) adjacency.set(from, /* @__PURE__ */ new Set());
|
|
99945
|
+
adjacency.get(from).add(to);
|
|
99946
|
+
}
|
|
99947
|
+
const reaches = (from, to) => {
|
|
99948
|
+
const seen = /* @__PURE__ */ new Set([from]);
|
|
99949
|
+
const queue = [from];
|
|
99950
|
+
while (queue.length) {
|
|
99951
|
+
for (const next of adjacency.get(queue.pop()) ?? []) {
|
|
99952
|
+
if (next === to) return true;
|
|
99953
|
+
if (!seen.has(next)) {
|
|
99954
|
+
seen.add(next);
|
|
99955
|
+
queue.push(next);
|
|
99956
|
+
}
|
|
99957
|
+
}
|
|
99958
|
+
}
|
|
99959
|
+
return false;
|
|
99960
|
+
};
|
|
99961
|
+
const byKind = /* @__PURE__ */ new Map();
|
|
99962
|
+
for (const element of model.elements) {
|
|
99963
|
+
if (!laneKinds.has(element.kind)) continue;
|
|
99964
|
+
if ((element.children ?? []).length) continue;
|
|
99965
|
+
if (!byKind.has(element.kind)) byKind.set(element.kind, []);
|
|
99966
|
+
byKind.get(element.kind).push(element);
|
|
99967
|
+
}
|
|
99968
|
+
const pinned = /* @__PURE__ */ new Set();
|
|
99969
|
+
for (const flow of model.flows) {
|
|
99970
|
+
if (!flow.fromSide && !flow.toSide) continue;
|
|
99971
|
+
pinned.add(rootOf.get(flow.from) ?? flow.from);
|
|
99972
|
+
pinned.add(rootOf.get(flow.to) ?? flow.to);
|
|
99973
|
+
}
|
|
99974
|
+
let laneId = 0;
|
|
99975
|
+
for (const members of byKind.values()) {
|
|
99976
|
+
if (members.length < 2) continue;
|
|
99977
|
+
if (members.some((member) => pinned.has(member.id))) continue;
|
|
99978
|
+
if (members.some((member) => member.order)) continue;
|
|
99979
|
+
if (members.some((a) => members.some((b) => a !== b && reaches(a.id, b.id)))) continue;
|
|
99980
|
+
laneId++;
|
|
99981
|
+
for (const member of members) laneOf.set(member.id, laneId);
|
|
99982
|
+
}
|
|
99983
|
+
return laneOf;
|
|
99984
|
+
}
|
|
99985
|
+
var ASPECT_TARGETS = {
|
|
99986
|
+
slide: 16 / 9,
|
|
99987
|
+
page: 0.71
|
|
99988
|
+
};
|
|
99989
|
+
async function withHubPortFallback(elk, makeGraph, direction, options) {
|
|
99990
|
+
const run = async (spec) => await elk.layout(makeGraph(direction, spec));
|
|
99991
|
+
const rungs = options?.hubPorts === false ? [] : [
|
|
99992
|
+
{ ...options, postCompaction: "EDGE_LENGTH_CONSTRAINT_LOCKING" },
|
|
99993
|
+
{ ...options, postCompaction: "NONE" },
|
|
99994
|
+
{ ...options, hubPorts: false }
|
|
99995
|
+
];
|
|
99996
|
+
try {
|
|
99997
|
+
return { result: await run(options), options };
|
|
99998
|
+
} catch (error) {
|
|
99999
|
+
for (const [index, rung] of rungs.entries()) {
|
|
100000
|
+
try {
|
|
100001
|
+
return { result: await run(rung), options: rung };
|
|
100002
|
+
} catch (rungError) {
|
|
100003
|
+
if (index === rungs.length - 1) throw rungError;
|
|
100004
|
+
}
|
|
100005
|
+
}
|
|
100006
|
+
throw error;
|
|
100007
|
+
}
|
|
100008
|
+
}
|
|
100009
|
+
function markDeclaredTerminals(edges, model, view, hubPorts) {
|
|
100010
|
+
const pinnedFlows = new Map(
|
|
100011
|
+
model.flows.filter((flow) => flow.fromSide || flow.toSide).map((flow) => [flow.id, { start: !!flow.fromSide, end: !!flow.toSide }])
|
|
100012
|
+
);
|
|
100013
|
+
const hubSides = hubPorts ? hubFlowSides(model, view) : /* @__PURE__ */ new Map();
|
|
100014
|
+
for (const edge of edges) {
|
|
100015
|
+
const pinned = pinnedFlows.get(edge.id);
|
|
100016
|
+
if (pinned) edge.pinned = { ...pinned };
|
|
100017
|
+
const hub = hubSides.get(edge.id);
|
|
100018
|
+
if (hub) edge.hubSided = { start: !!hub.from, end: !!hub.to };
|
|
100019
|
+
}
|
|
99541
100020
|
}
|
|
99542
100021
|
async function layout(model, view) {
|
|
99543
100022
|
const elk = await getElk();
|
|
@@ -99551,10 +100030,6 @@ async function layout(model, view) {
|
|
|
99551
100030
|
scale: fontScale
|
|
99552
100031
|
} = fontSizes(model.style.font.size);
|
|
99553
100032
|
const disposition = model.style.disposition;
|
|
99554
|
-
const ASPECT_TARGETS = {
|
|
99555
|
-
slide: 16 / 9,
|
|
99556
|
-
page: 0.71
|
|
99557
|
-
};
|
|
99558
100033
|
const aspectTarget = ASPECT_TARGETS[disposition];
|
|
99559
100034
|
const ingressExternalElements = view.partitionByOrder ? computeIngressExternalElements(model) : /* @__PURE__ */ new Set();
|
|
99560
100035
|
const graphContext = {
|
|
@@ -99574,7 +100049,7 @@ async function layout(model, view) {
|
|
|
99574
100049
|
};
|
|
99575
100050
|
const makeGraph = (direction, options) => buildElkGraph(graphContext, direction, options);
|
|
99576
100051
|
const kindOf = new Map(indexElementsById(model.elements));
|
|
99577
|
-
const sceneFromResult = (result2, layoutMs2) => {
|
|
100052
|
+
const sceneFromResult = (result2, layoutMs2, laidOutWith, lanes = true) => {
|
|
99578
100053
|
const origins = {
|
|
99579
100054
|
root: { x: 0, y: 0 }
|
|
99580
100055
|
};
|
|
@@ -99582,13 +100057,9 @@ async function layout(model, view) {
|
|
|
99582
100057
|
const nodes = walkedNodes.map((walked) => walked.node);
|
|
99583
100058
|
for (const walked of walkedNodes) origins[walked.id] = { x: walked.x, y: walked.y };
|
|
99584
100059
|
const edges = collectSceneEdges(result2, origins, numbered, edgeFontSize);
|
|
99585
|
-
const
|
|
99586
|
-
|
|
99587
|
-
);
|
|
99588
|
-
for (const edge of edges) {
|
|
99589
|
-
const pinned = pinnedFlows.get(edge.id);
|
|
99590
|
-
if (pinned) edge.pinned = { ...pinned };
|
|
99591
|
-
}
|
|
100060
|
+
const reversed = new Set(model.flows.filter(laidOutReversed).map((flow) => flow.id));
|
|
100061
|
+
for (const edge of edges) if (reversed.has(edge.id)) edge.pts.reverse();
|
|
100062
|
+
markDeclaredTerminals(edges, model, view, laidOutWith?.hubPorts !== false);
|
|
99592
100063
|
const scene = {
|
|
99593
100064
|
width: Math.ceil(result2.width),
|
|
99594
100065
|
height: Math.ceil(result2.height),
|
|
@@ -99598,11 +100069,14 @@ async function layout(model, view) {
|
|
|
99598
100069
|
};
|
|
99599
100070
|
runGeometryPasses(scene, model, {
|
|
99600
100071
|
numbered,
|
|
99601
|
-
sideways: disposition === "page" || disposition === "tall"
|
|
100072
|
+
sideways: disposition === "page" || disposition === "tall",
|
|
100073
|
+
laneOf: lanes ? laneOf : void 0
|
|
99602
100074
|
});
|
|
99603
100075
|
return scene;
|
|
99604
100076
|
};
|
|
100077
|
+
const laneOf = laneAssignment(model, view);
|
|
99605
100078
|
const startTime = Date.now();
|
|
100079
|
+
const layoutGraph = (direction, options) => withHubPortFallback(elk, makeGraph, direction, options);
|
|
99606
100080
|
let result;
|
|
99607
100081
|
let winnerDirection;
|
|
99608
100082
|
let winnerOptions;
|
|
@@ -99613,9 +100087,10 @@ async function layout(model, view) {
|
|
|
99613
100087
|
{ direction: "RIGHT", options: { labelWrap: 14, tight: true } },
|
|
99614
100088
|
{ direction: "RIGHT", options: { labelWrap: 14, tight: true, minLayers: true } }
|
|
99615
100089
|
] : [{ direction: "DOWN" }, { direction: "DOWN", options: { labelWrap: 16 } }];
|
|
99616
|
-
const
|
|
99617
|
-
graphSpecs.map((spec) =>
|
|
100090
|
+
const laidOutSpecs = await Promise.all(
|
|
100091
|
+
graphSpecs.map((spec) => layoutGraph(spec.direction, spec.options))
|
|
99618
100092
|
);
|
|
100093
|
+
const candidates = laidOutSpecs.map((laidOut) => laidOut.result);
|
|
99619
100094
|
const preferWide = disposition === "slide";
|
|
99620
100095
|
const orientedLayouts = candidates.map((layoutResult, index) => ({ layoutResult, index })).filter(
|
|
99621
100096
|
({ layoutResult }) => preferWide ? layoutResult.width >= layoutResult.height : layoutResult.height >= layoutResult.width
|
|
@@ -99628,7 +100103,7 @@ async function layout(model, view) {
|
|
|
99628
100103
|
);
|
|
99629
100104
|
result = winner.layoutResult;
|
|
99630
100105
|
winnerDirection = graphSpecs[winner.index].direction;
|
|
99631
|
-
winnerOptions =
|
|
100106
|
+
winnerOptions = laidOutSpecs[winner.index].options;
|
|
99632
100107
|
if (disposition === "slide") {
|
|
99633
100108
|
const folded = await foldedLayout(model, view, elk);
|
|
99634
100109
|
if (folded && fitScore(result) >= fitScore(folded) * 1.1) {
|
|
@@ -99642,20 +100117,32 @@ async function layout(model, view) {
|
|
|
99642
100117
|
}
|
|
99643
100118
|
} else {
|
|
99644
100119
|
winnerDirection = disposition === "tall" ? "DOWN" : "RIGHT";
|
|
99645
|
-
winnerOptions =
|
|
99646
|
-
result = await elk.layout(makeGraph(winnerDirection));
|
|
100120
|
+
({ result, options: winnerOptions } = await layoutGraph(winnerDirection));
|
|
99647
100121
|
}
|
|
99648
100122
|
const layoutMs = Date.now() - startTime;
|
|
99649
|
-
|
|
99650
|
-
const skipPortPass = !!globalThis.process?.env?.CAIRN_NO_PORT_PASS;
|
|
99651
|
-
if (skipPortPass) return base;
|
|
100123
|
+
let base = sceneFromResult(result, layoutMs, winnerOptions);
|
|
99652
100124
|
const layoutProfile = (candidate) => {
|
|
99653
100125
|
const everyEdge = new Set(candidate.edges.map((edge) => edge.id));
|
|
99654
100126
|
const profile = inspect(candidate, titleBoxesOf(candidate, model)).local(everyEdge, /* @__PURE__ */ new Map());
|
|
99655
100127
|
for (const [key, tier] of selectionExtras(candidate, model)) profile.set(key, tier);
|
|
99656
100128
|
return profile;
|
|
99657
100129
|
};
|
|
100130
|
+
if (!aspectTarget && nodeCoverage(base) < DENSE_ENOUGH) {
|
|
100131
|
+
const denser = await denserLayout(base, {
|
|
100132
|
+
layout: (spec) => elk.layout(makeGraph(winnerDirection, spec)),
|
|
100133
|
+
// Its specs carry the hub ports (none of them sets `hubPorts: false`), and
|
|
100134
|
+
// a candidate elk refuses is dropped rather than retried without them.
|
|
100135
|
+
toScene: (laidOut) => sceneFromResult(laidOut, Date.now() - startTime),
|
|
100136
|
+
profile: layoutProfile
|
|
100137
|
+
});
|
|
100138
|
+
if (denser) {
|
|
100139
|
+
base = denser.scene;
|
|
100140
|
+
winnerOptions = denser.options;
|
|
100141
|
+
}
|
|
100142
|
+
}
|
|
99658
100143
|
const baseProfile = layoutProfile(base);
|
|
100144
|
+
const skipPortPass = !!globalThis.process?.env?.CAIRN_NO_PORT_PASS;
|
|
100145
|
+
if (skipPortPass) return base;
|
|
99659
100146
|
let current = base;
|
|
99660
100147
|
let best = null;
|
|
99661
100148
|
for (let round = 0; round < PORT_PASS_ROUNDS; round++) {
|
|
@@ -99666,7 +100153,7 @@ async function layout(model, view) {
|
|
|
99666
100153
|
const constrained = makeGraph(winnerDirection, winnerOptions);
|
|
99667
100154
|
constrainPorts(constrained, current, flagged, model);
|
|
99668
100155
|
const reresult = await elk.layout(constrained);
|
|
99669
|
-
candidate = sceneFromResult(reresult, Date.now() - startTime);
|
|
100156
|
+
candidate = sceneFromResult(reresult, Date.now() - startTime, winnerOptions);
|
|
99670
100157
|
} catch {
|
|
99671
100158
|
break;
|
|
99672
100159
|
}
|
|
@@ -99722,18 +100209,54 @@ var UI = {
|
|
|
99722
100209
|
// src/xml-escape.ts
|
|
99723
100210
|
var esc = (text) => text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
99724
100211
|
var escAttr = (text) => esc(text).replace(/"/g, """);
|
|
100212
|
+
var escComment = (text) => text.replace(/-{2,}/g, (run) => [...run].join(" ")).replace(/-$/, "- ");
|
|
100213
|
+
|
|
100214
|
+
// src/logo-attribution.ts
|
|
100215
|
+
var PREAMBLE = [
|
|
100216
|
+
"This diagram contains third-party artwork under its own licence.",
|
|
100217
|
+
"Keep this notice with the file \u2014 it is the attribution those licences ask for.",
|
|
100218
|
+
"",
|
|
100219
|
+
"Every mark below is modified from the original: simple-icons redrew it as a",
|
|
100220
|
+
"single monochrome path, and cairn paints that path in the diagram's colours."
|
|
100221
|
+
];
|
|
100222
|
+
function logoAttributionComment(drawn) {
|
|
100223
|
+
const licensed = [...drawn].sort().map((slug) => ({ slug, logo: LOGOS[slug] })).filter((entry) => entry.logo?.license);
|
|
100224
|
+
if (licensed.length === 0) return "";
|
|
100225
|
+
const lines = [...PREAMBLE];
|
|
100226
|
+
for (const { slug, logo } of licensed) {
|
|
100227
|
+
lines.push("", `${logo.title} (${slug}) \u2014 ${logo.license}`);
|
|
100228
|
+
if (logo.copyright) lines.push(` ${logo.copyright}`);
|
|
100229
|
+
if (logo.source) lines.push(` artwork: ${logo.source}`);
|
|
100230
|
+
if (logo.licenseUrl) lines.push(` licence: ${logo.licenseUrl}`);
|
|
100231
|
+
}
|
|
100232
|
+
return `<!--
|
|
100233
|
+
${lines.map((line) => escComment(` ${line}`).trimEnd()).join("\n")}
|
|
100234
|
+
-->
|
|
100235
|
+
`;
|
|
100236
|
+
}
|
|
99725
100237
|
|
|
99726
100238
|
// src/svg-render.ts
|
|
99727
100239
|
var HOP_RADIUS = 5;
|
|
99728
100240
|
var LABEL_HALO = 4;
|
|
99729
100241
|
var RENDER_CHAR_WIDTH = 0.52;
|
|
99730
|
-
var
|
|
99731
|
-
|
|
99732
|
-
|
|
99733
|
-
|
|
99734
|
-
|
|
99735
|
-
|
|
100242
|
+
var BAND_CONTENT_X = 150;
|
|
100243
|
+
var MIN_BAND_TEXT = 200;
|
|
100244
|
+
var bandRightMargin = (scene) => scene.width - 20;
|
|
100245
|
+
function bandLines(text, from, right, fontSize) {
|
|
100246
|
+
const chars = Math.floor((right - from) / (fontSize * RENDER_CHAR_WIDTH));
|
|
100247
|
+
return bandWrap(text, Math.max(8, chars));
|
|
100248
|
+
}
|
|
100249
|
+
function bandWrap(text, maxChars) {
|
|
100250
|
+
return wrapText(text, maxChars).split("\n").flatMap((line) => {
|
|
100251
|
+
if (line.length <= maxChars) return [line];
|
|
100252
|
+
const parts = [];
|
|
100253
|
+
for (let index = 0; index < line.length; index += maxChars)
|
|
100254
|
+
parts.push(line.slice(index, index + maxChars));
|
|
100255
|
+
return parts;
|
|
100256
|
+
});
|
|
100257
|
+
}
|
|
99736
100258
|
var dashArray = (lineStyle) => lineStyle === "dashed" ? "5 3" : lineStyle === "dotted" ? "2 2.5" : void 0;
|
|
100259
|
+
var lineStyleOf = (flow, style) => flow?.style?.stroke?.style ?? flow?.lineStyle ?? style.flowStroke.style;
|
|
99737
100260
|
var round1 = (n) => Math.round(n * 10) / 10;
|
|
99738
100261
|
function assignSourceHues(model, hues) {
|
|
99739
100262
|
const sourceHue = /* @__PURE__ */ new Map();
|
|
@@ -99745,7 +100268,7 @@ function assignSourceHues(model, hues) {
|
|
|
99745
100268
|
}
|
|
99746
100269
|
function collectElementStyles(elements) {
|
|
99747
100270
|
return elements.flatMap((element) => [
|
|
99748
|
-
{ id: element.id, style: element.style,
|
|
100271
|
+
{ id: element.id, style: element.style, logo: element.logo },
|
|
99749
100272
|
...collectElementStyles(element.children)
|
|
99750
100273
|
]);
|
|
99751
100274
|
}
|
|
@@ -99789,19 +100312,39 @@ function auditRouteRepairs(deps) {
|
|
|
99789
100312
|
for (let tier = 0; tier < 5; tier++) if (a[tier] !== b[tier]) return a[tier] < b[tier];
|
|
99790
100313
|
return false;
|
|
99791
100314
|
};
|
|
100315
|
+
const flowOfBreach = (key) => {
|
|
100316
|
+
if (key.startsWith("adrift:"))
|
|
100317
|
+
return labels[Number.parseInt(key.slice("adrift:".length), 10)]?.flowId ?? null;
|
|
100318
|
+
const body = key.slice(key.indexOf(":") + 1);
|
|
100319
|
+
const cut = body.search(/[~:]/);
|
|
100320
|
+
return cut < 0 ? body : body.slice(0, cut);
|
|
100321
|
+
};
|
|
99792
100322
|
const withRepair = stateHarm();
|
|
99793
100323
|
const breachesWith = breaches();
|
|
99794
100324
|
const repairedRoutes = repaired.map((edge) => edge.pts);
|
|
99795
|
-
|
|
99796
|
-
|
|
99797
|
-
const withoutRepair = stateHarm();
|
|
99798
|
-
const breachesWithout = breaches();
|
|
99799
|
-
const breaksAPromise = [...breachesWith].some((key) => !breachesWithout.has(key));
|
|
99800
|
-
if (!breaksAPromise && !lessDamaged(withoutRepair, withRepair)) {
|
|
100325
|
+
const replacedRoutes = repaired.map((edge) => edge.repairedFrom);
|
|
100326
|
+
const applyKeep = (keep2) => {
|
|
99801
100327
|
repaired.forEach((edge, index) => {
|
|
99802
|
-
edge.pts = repairedRoutes[index];
|
|
100328
|
+
edge.pts = keep2[index] ? repairedRoutes[index] : replacedRoutes[index];
|
|
99803
100329
|
});
|
|
99804
100330
|
resettle();
|
|
100331
|
+
};
|
|
100332
|
+
applyKeep(repaired.map(() => false));
|
|
100333
|
+
const withoutRepair = stateHarm();
|
|
100334
|
+
const breachesWithout = breaches();
|
|
100335
|
+
const broken = [...breachesWith].filter((key) => !breachesWithout.has(key));
|
|
100336
|
+
if (!broken.length) {
|
|
100337
|
+
if (!lessDamaged(withoutRepair, withRepair)) applyKeep(repaired.map(() => true));
|
|
100338
|
+
for (const edge of repaired) edge.repairedFrom = void 0;
|
|
100339
|
+
return;
|
|
100340
|
+
}
|
|
100341
|
+
const blamed = new Set(broken.map(flowOfBreach).filter((id) => id !== null));
|
|
100342
|
+
const keep = repaired.map((edge) => !blamed.has(edge.id));
|
|
100343
|
+
if (keep.some(Boolean) && keep.some((kept) => !kept)) {
|
|
100344
|
+
applyKeep(keep);
|
|
100345
|
+
const partly = stateHarm();
|
|
100346
|
+
const stillBroken = [...breaches()].some((key) => !breachesWithout.has(key));
|
|
100347
|
+
if (stillBroken || lessDamaged(withoutRepair, partly)) applyKeep(repaired.map(() => false));
|
|
99805
100348
|
}
|
|
99806
100349
|
for (const edge of repaired) edge.repairedFrom = void 0;
|
|
99807
100350
|
}
|
|
@@ -99842,13 +100385,82 @@ function settleOneLabel(s, label) {
|
|
|
99842
100385
|
label.x = origin.x;
|
|
99843
100386
|
label.y = origin.y;
|
|
99844
100387
|
}
|
|
99845
|
-
|
|
99846
|
-
|
|
100388
|
+
var GLYPH_BOX = { width: 18, height: 16, left: 6, top: 7 };
|
|
100389
|
+
var GLYPHS = {
|
|
100390
|
+
// Padlock: authentication is a check something must pass.
|
|
100391
|
+
auth: ({ x, y, r, line, stroke }) => `<rect x="${x(3)}" y="${y(7)}" width="${r(12)}" height="${r(9)}" rx="${r(2)}" ${line}/><path d="M ${x(6)} ${y(7)} v ${-r(3)} a ${r(3)} ${r(3)} 0 0 1 ${r(6)} 0 v ${r(3)}" ${line}/><circle cx="${x(9)}" cy="${y(11)}" r="${r(1.5)}" fill="${stroke}"/>`,
|
|
100392
|
+
// Two posts with traffic passing between them: a gateway routes, it does not block.
|
|
100393
|
+
gateway: ({ x, y, r, line }) => `<path d="M ${x(2)} ${y(1)} V ${y(15)} M ${x(16)} ${y(1)} V ${y(15)}" ${line}/><path d="M ${x(4)} ${y(8)} H ${x(14)}" ${line}/><path d="M ${x(11)} ${y(5)} l ${r(3)} ${r(3)} l ${-r(3)} ${r(3)}" ${line}/>`,
|
|
100394
|
+
// ID badge: an identity provider issues who-you-are, it does not check it.
|
|
100395
|
+
idp: ({ x, y, r, line }) => `<rect x="${x(3)}" y="${y(2)}" width="${r(12)}" height="${r(13)}" rx="${r(2)}" ${line}/><path d="M ${x(7)} ${y(2)} H ${x(11)}" ${line}/><circle cx="${x(9)}" cy="${y(7)}" r="${r(2)}" ${line}/><path d="M ${x(5)} ${y(13)} q ${r(4)} ${-r(4)} ${r(8)} 0" ${line}/>`,
|
|
100396
|
+
// Brick wall: a firewall is a barrier, and no other kind reads as one.
|
|
100397
|
+
firewall: ({ x, y, r, line }) => `<rect x="${x(2)}" y="${y(2)}" width="${r(14)}" height="${r(12)}" rx="${r(1)}" ${line}/><path d="M ${x(2)} ${y(6)} H ${x(16)} M ${x(2)} ${y(10)} H ${x(16)}" ${line}/><path d="M ${x(9)} ${y(2)} V ${y(6)} M ${x(6)} ${y(6)} V ${y(10)} M ${x(12)} ${y(6)} V ${y(10)} M ${x(9)} ${y(10)} V ${y(14)}" ${line}/>`,
|
|
100398
|
+
// Monitor on a stand: a device is the machine a person works at. The screen is
|
|
100399
|
+
// left empty on purpose — that is what separates it from the firewall's wall
|
|
100400
|
+
// at legend size, where both are a rectangle and little else survives.
|
|
100401
|
+
device: ({ x, y, r, line }) => `<rect x="${x(2)}" y="${y(1)}" width="${r(14)}" height="${r(9)}" rx="${r(1)}" ${line}/><path d="M ${x(9)} ${y(10)} V ${y(13)}" ${line}/><path d="M ${x(4)} ${y(13)} H ${x(14)}" ${line}/>`
|
|
100402
|
+
};
|
|
100403
|
+
function glyphSvg(kind, stroke, box) {
|
|
100404
|
+
const glyph = GLYPHS[kind];
|
|
100405
|
+
if (!glyph) return "";
|
|
100406
|
+
const { x, y, scale = 1 } = box;
|
|
100407
|
+
const width = round1(1.3 * scale);
|
|
100408
|
+
return glyph({
|
|
100409
|
+
x: (v) => round1(x + v * scale),
|
|
100410
|
+
y: (v) => round1(y + v * scale),
|
|
100411
|
+
r: (v) => round1(v * scale),
|
|
100412
|
+
line: `fill="none" stroke="${stroke}" stroke-width="${width}"`,
|
|
100413
|
+
stroke
|
|
100414
|
+
});
|
|
100415
|
+
}
|
|
100416
|
+
var LOGO_BOX = { size: 18, right: 7, top: 6 };
|
|
100417
|
+
function logoSvg(mark) {
|
|
100418
|
+
const { logo, resolved, node, stroke, drawn, inset = {} } = mark;
|
|
100419
|
+
if (!logo) return "";
|
|
100420
|
+
const x = round1(node.x + node.width - (inset.right ?? LOGO_BOX.right) - LOGO_BOX.size);
|
|
100421
|
+
const y = round1(node.y + (inset.top ?? LOGO_BOX.top));
|
|
100422
|
+
if (logo.source === "file") {
|
|
100423
|
+
const href = resolved?.get(node.id);
|
|
100424
|
+
if (!href) return "";
|
|
100425
|
+
return `<image x="${x}" y="${y}" width="${LOGO_BOX.size}" height="${LOGO_BOX.size}" href="${escAttr(href)}" preserveAspectRatio="xMidYMid meet"/>
|
|
100426
|
+
`;
|
|
100427
|
+
}
|
|
100428
|
+
const builtin = Object.hasOwn(LOGOS, logo.value) ? LOGOS[logo.value] : void 0;
|
|
100429
|
+
if (!builtin) return "";
|
|
100430
|
+
drawn.add(logo.value);
|
|
100431
|
+
const scale = Math.round(LOGO_BOX.size / 24 * 1e4) / 1e4;
|
|
100432
|
+
return `<g transform="translate(${x} ${y}) scale(${scale})" fill="${stroke}"><title>${esc(builtin.title)}</title><path d="${builtin.d}"/></g>
|
|
100433
|
+
`;
|
|
100434
|
+
}
|
|
100435
|
+
function createNodeLabelHelpers(nodeFontSize) {
|
|
99847
100436
|
const centeredNodeLabel = (lines, centerX2, topBaseline, fill) => lines.map(
|
|
99848
100437
|
(line, index) => `<text x="${centerX2}" y="${topBaseline + index * (nodeFontSize + 2)}" font-size="${nodeFontSize}" text-anchor="middle" fill="${fill}">${esc(line)}</text>
|
|
99849
100438
|
`
|
|
99850
100439
|
).join("");
|
|
99851
100440
|
const centerLinesY = (top, height, lineCount) => top + height / 2 - (lineCount - 1) * (nodeFontSize + 2) / 2 + 4;
|
|
100441
|
+
const glyphLabelCenterX = (node) => node.x + GLYPH_GUTTER + (node.width - GLYPH_GUTTER) / 2;
|
|
100442
|
+
const logoLabelCenterX = (node, hasLogo) => node.x + (node.width - (hasLogo ? LOGO_GUTTER : 0)) / 2;
|
|
100443
|
+
return { centeredNodeLabel, centerLinesY, glyphLabelCenterX, logoLabelCenterX };
|
|
100444
|
+
}
|
|
100445
|
+
function createNodeRenderers(paint) {
|
|
100446
|
+
const {
|
|
100447
|
+
palette,
|
|
100448
|
+
nodeFontSize,
|
|
100449
|
+
containerFontSize,
|
|
100450
|
+
resolveStyle,
|
|
100451
|
+
elementLogo,
|
|
100452
|
+
resolvedLogos,
|
|
100453
|
+
drawnLogos
|
|
100454
|
+
} = paint;
|
|
100455
|
+
const logoFor = (node, stroke, inset) => logoSvg({
|
|
100456
|
+
logo: elementLogo.get(node.id),
|
|
100457
|
+
resolved: resolvedLogos,
|
|
100458
|
+
node,
|
|
100459
|
+
stroke,
|
|
100460
|
+
drawn: drawnLogos,
|
|
100461
|
+
inset
|
|
100462
|
+
});
|
|
100463
|
+
const { centeredNodeLabel, centerLinesY, glyphLabelCenterX, logoLabelCenterX } = createNodeLabelHelpers(nodeFontSize);
|
|
99852
100464
|
const renderContainerNode = (node) => {
|
|
99853
100465
|
const nodeStyle = resolveStyle(node.kind, node.id);
|
|
99854
100466
|
const fill = escAttr(nodeStyle.fill ?? palette.containerFill), stroke = escAttr(nodeStyle.stroke?.color ?? palette.containerStroke), text = escAttr(nodeStyle.text ?? palette.containerLabel);
|
|
@@ -99859,12 +100471,7 @@ function createNodeRenderers(paint) {
|
|
|
99859
100471
|
svg += `<text x="${node.x + 10}" y="${node.y + 18 + index * 14}" font-size="${containerFontSize}" font-weight="bold" fill="${text}">${esc(line)}</text>
|
|
99860
100472
|
`;
|
|
99861
100473
|
});
|
|
99862
|
-
|
|
99863
|
-
if (level) {
|
|
99864
|
-
const word = (style.lang === "fr" ? SEC_LEVEL_FR[level] : level) ?? level;
|
|
99865
|
-
svg += `<text x="${node.x + node.width - 9}" y="${node.y + node.height - 6}" font-size="${annot.tag}" text-anchor="end" font-weight="bold" fill="${stroke}" letter-spacing="0.5">${esc(word.toUpperCase())}</text>
|
|
99866
|
-
`;
|
|
99867
|
-
}
|
|
100474
|
+
svg += logoFor(node, stroke);
|
|
99868
100475
|
return svg;
|
|
99869
100476
|
};
|
|
99870
100477
|
const renderActor = (node, nodeStyle, lines) => {
|
|
@@ -99887,9 +100494,12 @@ function createNodeRenderers(paint) {
|
|
|
99887
100494
|
<ellipse cx="${node.x + node.width / 2}" cy="${node.y + ry}" rx="${node.width / 2}" ry="${ry}" fill="${fill}" stroke="${stroke}" stroke-width="1.3"/>
|
|
99888
100495
|
`;
|
|
99889
100496
|
const centerY2 = node.y + ry + (node.height - ry) / 2 - (lines.length - 1) * (nodeFontSize + 2) / 2 + 4;
|
|
99890
|
-
|
|
100497
|
+
const logo = logoFor(node, stroke, {
|
|
100498
|
+
top: ry + (node.height - 2 * ry - LOGO_BOX.size) / 2
|
|
100499
|
+
});
|
|
100500
|
+
return body + logo + centeredNodeLabel(
|
|
99891
100501
|
lines,
|
|
99892
|
-
node
|
|
100502
|
+
logoLabelCenterX(node, logo !== ""),
|
|
99893
100503
|
centerY2,
|
|
99894
100504
|
escAttr(nodeStyle.text ?? palette.nodeText)
|
|
99895
100505
|
);
|
|
@@ -99900,50 +100510,38 @@ function createNodeRenderers(paint) {
|
|
|
99900
100510
|
const body = `<path d="M ${node.x + rx} ${node.y} h ${node.width - 2 * rx} a ${rx} ${node.height / 2} 0 0 1 0 ${node.height} h ${-(node.width - 2 * rx)} a ${rx} ${node.height / 2} 0 0 1 0 ${-node.height}" fill="${fill}" stroke="${stroke}" stroke-width="1.3"/>
|
|
99901
100511
|
<ellipse cx="${node.x + rx}" cy="${node.y + node.height / 2}" rx="${rx}" ry="${node.height / 2}" fill="${fill}" stroke="${stroke}" stroke-width="1.3"/>
|
|
99902
100512
|
`;
|
|
99903
|
-
|
|
100513
|
+
const logo = logoFor(node, stroke, { right: LOGO_BOX.right + rx });
|
|
100514
|
+
return body + logo + centeredNodeLabel(
|
|
99904
100515
|
lines,
|
|
99905
|
-
node.x + rx + (node.width - rx) / 2,
|
|
100516
|
+
node.x + rx + (node.width - rx - (logo === "" ? 0 : LOGO_GUTTER)) / 2,
|
|
99906
100517
|
centerLinesY(node.y, node.height, lines.length),
|
|
99907
100518
|
text
|
|
99908
100519
|
);
|
|
99909
100520
|
};
|
|
99910
|
-
const
|
|
99911
|
-
const centerX2 = node.x + node.width / 2;
|
|
99912
|
-
const fill = escAttr(nodeStyle.fill ?? palette.nodeFill), stroke = escAttr(nodeStyle.stroke?.color ?? palette.nodeStroke), text = escAttr(nodeStyle.text ?? palette.nodeText);
|
|
99913
|
-
const body = `<rect x="${node.x}" y="${node.y}" width="${node.width}" height="${node.height}" rx="4" fill="${fill}" stroke="${stroke}" stroke-width="1.3"/>
|
|
99914
|
-
<path d="M ${round1(node.x + 8)} ${round1(node.y + 8)} L ${round1(node.x + 22)} ${round1(node.y + 8)} Q ${round1(node.x + 24)} ${round1(node.y + 13)} ${round1(node.x + 15)} ${round1(node.y + 20)} Q ${round1(node.x + 6)} ${round1(node.y + 13)} ${round1(node.x + 8)} ${round1(node.y + 8)}" fill="none" stroke="${stroke}" stroke-width="1.3"/>
|
|
99915
|
-
`;
|
|
99916
|
-
return body + centeredNodeLabel(lines, centerX2 + 10, centerLinesY(node.y, node.height, lines.length), text);
|
|
99917
|
-
};
|
|
99918
|
-
const renderAuth = (node, nodeStyle, lines) => {
|
|
99919
|
-
const centerX2 = node.x + node.width / 2;
|
|
99920
|
-
const fill = escAttr(nodeStyle.fill ?? palette.nodeFill), stroke = escAttr(nodeStyle.stroke?.color ?? palette.nodeStroke), text = escAttr(nodeStyle.text ?? palette.nodeText);
|
|
99921
|
-
const body = `<rect x="${node.x}" y="${node.y}" width="${node.width}" height="${node.height}" rx="4" fill="${fill}" stroke="${stroke}" stroke-width="1.3"/>
|
|
99922
|
-
<rect x="${node.x + 6}" y="${node.y + 6}" width="18" height="14" rx="3" fill="none" stroke="${stroke}" stroke-width="1.3"/>
|
|
99923
|
-
<path d="M ${node.x + 10} ${node.y + 9} v -4 a 5 5 0 0 1 10 0 v 4" fill="none" stroke="${stroke}" stroke-width="1.3"/>
|
|
99924
|
-
<circle cx="${node.x + 15}" cy="${node.y + 16}" r="2.5" fill="${stroke}"/>
|
|
99925
|
-
`;
|
|
99926
|
-
return body + centeredNodeLabel(lines, centerX2 + 10, centerLinesY(node.y, node.height, lines.length), text);
|
|
99927
|
-
};
|
|
99928
|
-
const renderPlainBox = (node, nodeStyle, lines) => {
|
|
100521
|
+
const renderGlyphBox = (node, nodeStyle, lines) => {
|
|
99929
100522
|
const fill = escAttr(nodeStyle.fill ?? palette.nodeFill), stroke = escAttr(nodeStyle.stroke?.color ?? palette.nodeStroke), text = escAttr(nodeStyle.text ?? palette.nodeText);
|
|
99930
100523
|
const dash = dashArray(nodeStyle.stroke?.style);
|
|
99931
100524
|
const body = `<rect x="${node.x}" y="${node.y}" width="${node.width}" height="${node.height}" rx="4" fill="${fill}" stroke="${stroke}" stroke-width="${nodeStyle.stroke?.width ?? 1.3}"${dash ? ` stroke-dasharray="${dash}"` : ""}/>
|
|
99932
|
-
|
|
100525
|
+
` + glyphSvg(node.kind, stroke, {
|
|
100526
|
+
x: node.x + GLYPH_BOX.left,
|
|
100527
|
+
y: node.y + GLYPH_BOX.top
|
|
100528
|
+
}) + "\n";
|
|
99933
100529
|
return body + centeredNodeLabel(
|
|
99934
100530
|
lines,
|
|
99935
|
-
node
|
|
100531
|
+
glyphLabelCenterX(node),
|
|
99936
100532
|
centerLinesY(node.y, node.height, lines.length),
|
|
99937
100533
|
text
|
|
99938
100534
|
);
|
|
99939
100535
|
};
|
|
99940
|
-
const
|
|
100536
|
+
const renderPlainBox = (node, nodeStyle, lines) => {
|
|
99941
100537
|
const fill = escAttr(nodeStyle.fill ?? palette.nodeFill), stroke = escAttr(nodeStyle.stroke?.color ?? palette.nodeStroke), text = escAttr(nodeStyle.text ?? palette.nodeText);
|
|
99942
|
-
const
|
|
100538
|
+
const dash = dashArray(nodeStyle.stroke?.style);
|
|
100539
|
+
const logo = logoFor(node, stroke);
|
|
100540
|
+
const body = `<rect x="${node.x}" y="${node.y}" width="${node.width}" height="${node.height}" rx="4" fill="${fill}" stroke="${stroke}" stroke-width="${nodeStyle.stroke?.width ?? 1.3}"${dash ? ` stroke-dasharray="${dash}"` : ""}/>
|
|
99943
100541
|
`;
|
|
99944
|
-
return body + centeredNodeLabel(
|
|
100542
|
+
return body + logo + centeredNodeLabel(
|
|
99945
100543
|
lines,
|
|
99946
|
-
node
|
|
100544
|
+
logoLabelCenterX(node, logo !== ""),
|
|
99947
100545
|
centerLinesY(node.y, node.height, lines.length),
|
|
99948
100546
|
text
|
|
99949
100547
|
);
|
|
@@ -99958,14 +100556,8 @@ function createNodeRenderers(paint) {
|
|
|
99958
100556
|
return renderDatastore(node, nodeStyle, lines);
|
|
99959
100557
|
case "queue":
|
|
99960
100558
|
return renderQueue(node, nodeStyle, lines);
|
|
99961
|
-
case "gateway":
|
|
99962
|
-
return renderGateway(node, nodeStyle, lines);
|
|
99963
|
-
case "auth":
|
|
99964
|
-
return renderAuth(node, nodeStyle, lines);
|
|
99965
|
-
case "idp":
|
|
99966
|
-
return renderIdp(node, nodeStyle, lines);
|
|
99967
100559
|
default:
|
|
99968
|
-
return renderPlainBox(node, nodeStyle, lines);
|
|
100560
|
+
return GLYPHS[node.kind] ? renderGlyphBox(node, nodeStyle, lines) : renderPlainBox(node, nodeStyle, lines);
|
|
99969
100561
|
}
|
|
99970
100562
|
};
|
|
99971
100563
|
return { renderContainerNode, renderLeafNode };
|
|
@@ -100032,15 +100624,20 @@ function createLabelSettler(deps) {
|
|
|
100032
100624
|
const a = edge.pts[index];
|
|
100033
100625
|
const b = edge.pts[index + 1];
|
|
100034
100626
|
const vertical = Math.abs(a.x - b.x) < Math.abs(a.y - b.y);
|
|
100035
|
-
const
|
|
100036
|
-
const
|
|
100037
|
-
|
|
100038
|
-
|
|
100039
|
-
|
|
100040
|
-
|
|
100041
|
-
|
|
100042
|
-
|
|
100043
|
-
|
|
100627
|
+
const size = vertical ? label.height : label.width;
|
|
100628
|
+
const start = vertical ? Math.min(a.y, b.y) : Math.min(a.x, b.x);
|
|
100629
|
+
const end = vertical ? Math.max(a.y, b.y) : Math.max(a.x, b.x);
|
|
100630
|
+
const seat = vertical ? (a.y + b.y) / 2 - lead : (a.x + b.x) / 2 - label.width / 2;
|
|
100631
|
+
const back = Math.max(0, seat - start);
|
|
100632
|
+
const ahead = Math.max(0, end - size - seat);
|
|
100633
|
+
if (back === 0 && ahead === 0) continue;
|
|
100634
|
+
for (const fraction of [0.25, 0.5, 0.75, 1])
|
|
100635
|
+
for (const room of [-back, ahead]) {
|
|
100636
|
+
const shift = room * fraction;
|
|
100637
|
+
seats.push(
|
|
100638
|
+
vertical ? { x: (a.x + b.x) / 2 - label.width / 2, y: seat + shift } : { x: seat + shift, y: (a.y + b.y) / 2 - lead }
|
|
100639
|
+
);
|
|
100640
|
+
}
|
|
100044
100641
|
}
|
|
100045
100642
|
return seats;
|
|
100046
100643
|
};
|
|
@@ -100087,27 +100684,106 @@ function createLabelSettler(deps) {
|
|
|
100087
100684
|
settleLabelPositions
|
|
100088
100685
|
};
|
|
100089
100686
|
}
|
|
100687
|
+
var legendKinds = (paint) => [...new Set(paint.scene.nodes.map((node) => node.kind))].filter(
|
|
100688
|
+
(kind) => paint.legendNames[kind] && (kind !== "actor" || paint.view.actorLegend)
|
|
100689
|
+
);
|
|
100690
|
+
function kindKeysSvg(paint, kinds, y, x) {
|
|
100691
|
+
const { scene, palette, legendNames, scaled, resolveStyle } = paint;
|
|
100692
|
+
let svg = "";
|
|
100693
|
+
let keyX = x;
|
|
100694
|
+
let bandY = y;
|
|
100695
|
+
const LINE_H = scaled(12);
|
|
100696
|
+
for (const kind of kinds) {
|
|
100697
|
+
const nodeStyle = resolveStyle(kind, "");
|
|
100698
|
+
if (kind === "actor") {
|
|
100699
|
+
const stroke = nodeStyle.stroke?.color ?? palette.actorStroke;
|
|
100700
|
+
svg += `<circle cx="${keyX + scaled(13)}" cy="${bandY + scaled(5)}" r="${scaled(3)}" fill="none" stroke="${stroke}" stroke-width="1.2"/>
|
|
100701
|
+
`;
|
|
100702
|
+
svg += `<path d="M ${keyX + scaled(8)} ${bandY + scaled(15)} q ${scaled(5)} ${scaled(-7)} ${scaled(10)} 0" fill="none" stroke="${stroke}" stroke-width="1.2"/>
|
|
100703
|
+
`;
|
|
100704
|
+
} else {
|
|
100705
|
+
const dash = dashArray(nodeStyle.stroke?.style);
|
|
100706
|
+
const stroke = nodeStyle.stroke?.color ?? palette.nodeStroke;
|
|
100707
|
+
svg += `<rect x="${keyX}" y="${bandY + 2}" width="${scaled(26)}" height="${scaled(14)}" rx="3" fill="${nodeStyle.fill ?? palette.nodeFill}" stroke="${escAttr(stroke)}"${dash ? ` stroke-dasharray="${dash}"` : ""}/>
|
|
100708
|
+
`;
|
|
100709
|
+
const glyphScale = (scaled(14) - scaled(4)) / GLYPH_BOX.height;
|
|
100710
|
+
svg += glyphSvg(kind, escAttr(stroke), {
|
|
100711
|
+
x: keyX + (scaled(26) - GLYPH_BOX.width * glyphScale) / 2,
|
|
100712
|
+
y: bandY + 2 + (scaled(14) - GLYPH_BOX.height * glyphScale) / 2,
|
|
100713
|
+
scale: glyphScale
|
|
100714
|
+
});
|
|
100715
|
+
}
|
|
100716
|
+
const name = legendNames[kind];
|
|
100717
|
+
const lines = bandLines(name, keyX + scaled(32), bandRightMargin(scene), scaled(10));
|
|
100718
|
+
for (const [row, line] of lines.entries())
|
|
100719
|
+
svg += `<text x="${keyX + scaled(32)}" y="${bandY + scaled(13) + row * LINE_H}" font-size="${scaled(10)}" fill="${palette.bandText}">${esc(line)}</text>
|
|
100720
|
+
`;
|
|
100721
|
+
keyX += scaled(40) + Math.ceil(name.length * scaled(10) * RENDER_CHAR_WIDTH) + scaled(24);
|
|
100722
|
+
bandY += (lines.length - 1) * LINE_H;
|
|
100723
|
+
if (lines.length > 1 || keyX > scene.width - 220) {
|
|
100724
|
+
keyX = x;
|
|
100725
|
+
bandY += scaled(22);
|
|
100726
|
+
}
|
|
100727
|
+
}
|
|
100728
|
+
return { svg, bandY: kinds.length ? bandY + scaled(24) : bandY };
|
|
100729
|
+
}
|
|
100730
|
+
function lineStyleKeysSvg(paint, y, x) {
|
|
100731
|
+
const { scene, model, style, palette, legendLineStyles, scaled, defaultEdgeColor, markerName } = paint;
|
|
100732
|
+
const styles = LINE_STYLES2.filter(
|
|
100733
|
+
(lineStyle) => model.flows.some((flow) => lineStyleOf(flow, style) === lineStyle)
|
|
100734
|
+
);
|
|
100735
|
+
if (styles.length < 2) return { svg: "", bandY: y };
|
|
100736
|
+
const maxX = scene.width - 20;
|
|
100737
|
+
let svg = "";
|
|
100738
|
+
let keyX = x;
|
|
100739
|
+
let bandY = y;
|
|
100740
|
+
const LINE_H = scaled(12);
|
|
100741
|
+
for (const [index, lineStyle] of styles.entries()) {
|
|
100742
|
+
const meaning = legendLineStyles[lineStyle];
|
|
100743
|
+
const keyWidth = scaled(40) + Math.ceil(meaning.length * scaled(10) * RENDER_CHAR_WIDTH) + scaled(24);
|
|
100744
|
+
if (keyX > x && keyX + keyWidth > maxX) {
|
|
100745
|
+
keyX = x;
|
|
100746
|
+
bandY += scaled(22);
|
|
100747
|
+
}
|
|
100748
|
+
const dash = dashArray(lineStyle);
|
|
100749
|
+
svg += `<line x1="${keyX}" y1="${bandY + 8}" x2="${keyX + scaled(26)}" y2="${bandY + 8}" stroke="${escAttr(defaultEdgeColor)}" stroke-width="1.3"${dash ? ` stroke-dasharray="${dash}"` : ""} marker-end="url(#${markerName(defaultEdgeColor)})"/>
|
|
100750
|
+
`;
|
|
100751
|
+
const lines = bandLines(meaning, keyX + scaled(40), maxX, scaled(10));
|
|
100752
|
+
for (const [row, line] of lines.entries())
|
|
100753
|
+
svg += `<text x="${keyX + scaled(32)}" y="${bandY + scaled(12) + row * LINE_H}" font-size="${scaled(10)}" fill="${palette.bandText}">${esc(line)}</text>
|
|
100754
|
+
`;
|
|
100755
|
+
if (lines.length === 1) {
|
|
100756
|
+
keyX += keyWidth;
|
|
100757
|
+
continue;
|
|
100758
|
+
}
|
|
100759
|
+
bandY += (lines.length - 1) * LINE_H;
|
|
100760
|
+
if (index < styles.length - 1) {
|
|
100761
|
+
bandY += scaled(22);
|
|
100762
|
+
keyX = x;
|
|
100763
|
+
}
|
|
100764
|
+
}
|
|
100765
|
+
return { svg, bandY: bandY + scaled(24) };
|
|
100766
|
+
}
|
|
100090
100767
|
function createBandRenderers(paint) {
|
|
100091
100768
|
const {
|
|
100092
100769
|
scene,
|
|
100093
100770
|
model,
|
|
100094
|
-
view,
|
|
100095
100771
|
style,
|
|
100096
100772
|
palette,
|
|
100097
100773
|
annot,
|
|
100098
100774
|
ui,
|
|
100099
|
-
legendNames,
|
|
100100
100775
|
legendFlowLabel,
|
|
100101
100776
|
scaled,
|
|
100102
100777
|
objectName,
|
|
100103
|
-
resolveStyle,
|
|
100104
100778
|
defaultEdgeColor,
|
|
100105
100779
|
markerName,
|
|
100106
100780
|
numbered
|
|
100107
100781
|
} = paint;
|
|
100108
100782
|
let bandY = scene.height;
|
|
100109
100783
|
let bandsSvg = "";
|
|
100110
|
-
const
|
|
100784
|
+
const rightMargin = bandRightMargin(scene);
|
|
100785
|
+
const stackedTitle = rightMargin - BAND_CONTENT_X < MIN_BAND_TEXT;
|
|
100786
|
+
const contentX = stackedTitle ? 20 : BAND_CONTENT_X;
|
|
100111
100787
|
const chip = (x, y, name) => {
|
|
100112
100788
|
const width = chipW(name, annot.scale);
|
|
100113
100789
|
return {
|
|
@@ -100122,7 +100798,7 @@ function createBandRenderers(paint) {
|
|
|
100122
100798
|
`;
|
|
100123
100799
|
bandsSvg += `<text x="20" y="${bandY + scaled(32)}" font-size="${scaled(11)}" font-weight="bold" fill="${palette.bandTitle}">${esc(title)}</text>
|
|
100124
100800
|
`;
|
|
100125
|
-
bandY += scaled(20);
|
|
100801
|
+
bandY += scaled(stackedTitle ? 34 : 20);
|
|
100126
100802
|
};
|
|
100127
100803
|
const flowChipsSvg = (flow, startX, startY) => {
|
|
100128
100804
|
if (!flow.objects?.length) return "";
|
|
@@ -100154,7 +100830,7 @@ function createBandRenderers(paint) {
|
|
|
100154
100830
|
const textW = Math.max(60, colW - BADGE - (chipsW ? chipsW + 6 : 0));
|
|
100155
100831
|
const maxChars = Math.max(6, Math.floor(textW / (scaled(10) * RENDER_CHAR_WIDTH)));
|
|
100156
100832
|
const raw = (flow.label ?? "") + (tech ? " " + tech : "");
|
|
100157
|
-
const lines = raw.split("\n").flatMap((segment) =>
|
|
100833
|
+
const lines = raw.split("\n").flatMap((segment) => bandWrap(segment, maxChars));
|
|
100158
100834
|
return { flow, lines };
|
|
100159
100835
|
});
|
|
100160
100836
|
const rows = Math.ceil(entries.length / cols);
|
|
@@ -100181,59 +100857,50 @@ function createBandRenderers(paint) {
|
|
|
100181
100857
|
};
|
|
100182
100858
|
const renderObjectsBand = () => {
|
|
100183
100859
|
beginBand(ui.objects);
|
|
100184
|
-
|
|
100185
|
-
|
|
100860
|
+
const LINE_H = scaled(12);
|
|
100861
|
+
const chipRow = (name, reading) => {
|
|
100862
|
+
const chipResult = chip(contentX, bandY + 2, name);
|
|
100186
100863
|
bandsSvg += chipResult.svg;
|
|
100187
|
-
|
|
100188
|
-
|
|
100864
|
+
const textX = contentX + chipResult.width + 10;
|
|
100865
|
+
const lines = reading ? bandLines(reading, textX, rightMargin, scaled(10)) : [];
|
|
100866
|
+
for (const [row, line] of lines.entries())
|
|
100867
|
+
bandsSvg += `<text x="${textX}" y="${bandY + scaled(13) + row * LINE_H}" font-size="${scaled(10)}" fill="${palette.bandMuted}">${esc(line)}</text>
|
|
100189
100868
|
`;
|
|
100190
|
-
bandY += scaled(24);
|
|
100191
|
-
}
|
|
100192
|
-
|
|
100193
|
-
|
|
100194
|
-
|
|
100195
|
-
|
|
100196
|
-
bandY +=
|
|
100869
|
+
bandY += scaled(24) + Math.max(0, lines.length - 1) * LINE_H;
|
|
100870
|
+
};
|
|
100871
|
+
for (const bo of model.businessObjects)
|
|
100872
|
+
chipRow(bo.name, bo.description ? `\u2014 ${bo.description}` : "");
|
|
100873
|
+
if (model.flows.some((flow) => flow.objects?.length))
|
|
100874
|
+
chipRow(ui.businessObject, ui.carriedByFlow);
|
|
100875
|
+
bandY += 6;
|
|
100197
100876
|
};
|
|
100198
100877
|
const renderLegendBand = () => {
|
|
100878
|
+
const kinds = legendKinds(paint);
|
|
100879
|
+
if (!kinds.length && !model.flows.length && !model.legendNotes.length) return;
|
|
100199
100880
|
beginBand(ui.legend);
|
|
100200
|
-
|
|
100201
|
-
|
|
100202
|
-
|
|
100203
|
-
)
|
|
100204
|
-
|
|
100205
|
-
const nodeStyle = resolveStyle(kind, "");
|
|
100206
|
-
if (kind === "actor") {
|
|
100207
|
-
const stroke = nodeStyle.stroke?.color ?? palette.actorStroke;
|
|
100208
|
-
bandsSvg += `<circle cx="${lx + scaled(13)}" cy="${bandY + scaled(5)}" r="${scaled(3)}" fill="none" stroke="${stroke}" stroke-width="1.2"/>
|
|
100881
|
+
const kindKeys = kindKeysSvg(paint, kinds, bandY, contentX);
|
|
100882
|
+
bandsSvg += kindKeys.svg;
|
|
100883
|
+
bandY = kindKeys.bandY;
|
|
100884
|
+
if (model.flows.length) {
|
|
100885
|
+
bandsSvg += `<line x1="${contentX}" y1="${bandY + 8}" x2="${contentX + scaled(26)}" y2="${bandY + 8}" stroke="${escAttr(defaultEdgeColor)}" stroke-width="1.3" marker-end="url(#${markerName(defaultEdgeColor)})"/>
|
|
100209
100886
|
`;
|
|
100210
|
-
|
|
100887
|
+
const flowLabelText = (numbered ? legendFlowLabel + " \u2014 " + ui.numberedSuffix : legendFlowLabel) + (style.flowColor === "by-source" ? style.lang === "fr" ? " \u2014 couleur = source" : " \u2014 colour = source" : "");
|
|
100888
|
+
const flowKeyX = contentX + scaled(32);
|
|
100889
|
+
const flowKeyLines = bandLines(flowLabelText, flowKeyX, rightMargin, scaled(10));
|
|
100890
|
+
for (const [row, line] of flowKeyLines.entries())
|
|
100891
|
+
bandsSvg += `<text x="${flowKeyX}" y="${bandY + scaled(12) + row * scaled(12)}" font-size="${scaled(10)}" fill="${palette.bandText}">${esc(line)}</text>
|
|
100211
100892
|
`;
|
|
100212
|
-
|
|
100213
|
-
|
|
100214
|
-
|
|
100215
|
-
|
|
100216
|
-
}
|
|
100217
|
-
const name = legendNames[kind];
|
|
100218
|
-
bandsSvg += `<text x="${lx + scaled(32)}" y="${bandY + scaled(13)}" font-size="${scaled(10)}" fill="${palette.bandText}">${esc(name)}</text>
|
|
100219
|
-
`;
|
|
100220
|
-
lx += scaled(40) + Math.ceil(name.length * scaled(10) * RENDER_CHAR_WIDTH) + scaled(24);
|
|
100221
|
-
if (lx > scene.width - 220) {
|
|
100222
|
-
lx = contentX;
|
|
100223
|
-
bandY += scaled(22);
|
|
100224
|
-
}
|
|
100893
|
+
bandY += scaled(24) + (flowKeyLines.length - 1) * scaled(12);
|
|
100894
|
+
const lineStyleKeys = lineStyleKeysSvg(paint, bandY, contentX);
|
|
100895
|
+
bandsSvg += lineStyleKeys.svg;
|
|
100896
|
+
bandY = lineStyleKeys.bandY;
|
|
100225
100897
|
}
|
|
100226
|
-
bandY += scaled(24);
|
|
100227
|
-
bandsSvg += `<line x1="${contentX}" y1="${bandY + 8}" x2="${contentX + scaled(26)}" y2="${bandY + 8}" stroke="${escAttr(defaultEdgeColor)}" stroke-width="1.3" marker-end="url(#${markerName(defaultEdgeColor)})"/>
|
|
100228
|
-
`;
|
|
100229
|
-
const flowLabelText = (numbered ? legendFlowLabel + " \u2014 " + ui.numberedSuffix : legendFlowLabel) + (style.flowColor === "by-source" ? style.lang === "fr" ? " \u2014 couleur = source" : " \u2014 colour = source" : "");
|
|
100230
|
-
bandsSvg += `<text x="${contentX + scaled(32)}" y="${bandY + scaled(12)}" font-size="${scaled(10)}" fill="${palette.bandText}">${esc(flowLabelText)}</text>
|
|
100231
|
-
`;
|
|
100232
|
-
bandY += scaled(24);
|
|
100233
100898
|
for (const note of model.legendNotes) {
|
|
100234
|
-
|
|
100899
|
+
const lines = bandLines(note, contentX, rightMargin, scaled(10));
|
|
100900
|
+
for (const [row, line] of lines.entries())
|
|
100901
|
+
bandsSvg += `<text x="${contentX}" y="${bandY + scaled(12) + row * scaled(12)}" font-size="${scaled(10)}" fill="${palette.bandText}" font-style="italic">${esc(line)}</text>
|
|
100235
100902
|
`;
|
|
100236
|
-
bandY += scaled(20);
|
|
100903
|
+
bandY += scaled(20) + (lines.length - 1) * scaled(12);
|
|
100237
100904
|
}
|
|
100238
100905
|
};
|
|
100239
100906
|
return {
|
|
@@ -100332,7 +100999,7 @@ function createEdgePainter(paint) {
|
|
|
100332
100999
|
const flowStyle = flow?.style;
|
|
100333
101000
|
const color = flowColorOf(flow);
|
|
100334
101001
|
const headColor = style.flowColor === "by-source" ? color : defaultEdgeColor;
|
|
100335
|
-
const dash = dashArray(
|
|
101002
|
+
const dash = dashArray(lineStyleOf(flow, style));
|
|
100336
101003
|
const width = flowStyle?.stroke?.width ?? style.flowStroke.width;
|
|
100337
101004
|
return `<path d="${edgePath(edge.pts)}" fill="none" stroke="${escAttr(color)}" stroke-width="${width}"${dash ? ` stroke-dasharray="${dash}"` : ""} marker-end="url(#${markerName(headColor)})"/>
|
|
100338
101005
|
`;
|
|
@@ -100348,7 +101015,28 @@ function createEdgePainter(paint) {
|
|
|
100348
101015
|
};
|
|
100349
101016
|
return { renderEdgePath, renderEdgeLabels };
|
|
100350
101017
|
}
|
|
100351
|
-
function
|
|
101018
|
+
function svgDocument(args) {
|
|
101019
|
+
const {
|
|
101020
|
+
width,
|
|
101021
|
+
height,
|
|
101022
|
+
fontFamily,
|
|
101023
|
+
background,
|
|
101024
|
+
arrowMarkers,
|
|
101025
|
+
markerSize,
|
|
101026
|
+
body,
|
|
101027
|
+
bandsSvg,
|
|
101028
|
+
attribution
|
|
101029
|
+
} = args;
|
|
101030
|
+
const markers = [...arrowMarkers].map(
|
|
101031
|
+
([color, markerName]) => `<marker id="${markerName}" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="${markerSize}" markerHeight="${markerSize}" orient="auto-start-reverse">
|
|
101032
|
+
<path d="M0,0 L10,5 L0,10 z" fill="${escAttr(color)}"/></marker>`
|
|
101033
|
+
).join("\n");
|
|
101034
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}" font-family="${escAttr(fontFamily)},Arial,sans-serif">
|
|
101035
|
+
${attribution}<defs>${markers}</defs>
|
|
101036
|
+
<rect width="${width}" height="${height}" fill="${escAttr(background)}"/>
|
|
101037
|
+
` + body + bandsSvg + "</svg>\n";
|
|
101038
|
+
}
|
|
101039
|
+
function render(model, view, scene, options) {
|
|
100352
101040
|
const style = model.style;
|
|
100353
101041
|
const fonts = fontSizes(style.font.size);
|
|
100354
101042
|
const { edge: edgeFontSize, node: nodeFontSize, cont: containerFontSize } = fonts;
|
|
@@ -100364,10 +101052,10 @@ function render(model, view, scene) {
|
|
|
100364
101052
|
chipTextDy: round1(11 * fonts.scale)
|
|
100365
101053
|
};
|
|
100366
101054
|
const scaled = (n) => round1(n * fonts.scale);
|
|
100367
|
-
const { palette, kinds: kindDefaults
|
|
100368
|
-
const
|
|
101055
|
+
const { palette, kinds: kindDefaults } = options?.theme ? themeFromSpec(options.theme, view) : themeFor(style.theme, view);
|
|
101056
|
+
const onDarkGround = options?.theme ? options.theme.dark === true : isDarkTheme(style.theme);
|
|
100369
101057
|
const defaultEdgeColor = style.flowStrokeColorSet ? style.flowStroke.color : style.accent ?? palette.edge;
|
|
100370
|
-
const sourceHue = style.flowColor === "by-source" ? assignSourceHues(model, flowPalette[
|
|
101058
|
+
const sourceHue = style.flowColor === "by-source" ? assignSourceHues(model, flowPalette[onDarkGround ? "dark" : "light"]) : /* @__PURE__ */ new Map();
|
|
100371
101059
|
const flowColorOf = (flow) => flow?.style?.stroke?.color ?? (style.flowColor === "by-source" ? sourceHue.get(flow?.from ?? "") ?? defaultEdgeColor : defaultEdgeColor);
|
|
100372
101060
|
const arrowMarkers = /* @__PURE__ */ new Map();
|
|
100373
101061
|
const markerName = (color) => {
|
|
@@ -100384,16 +101072,15 @@ function render(model, view, scene) {
|
|
|
100384
101072
|
const ui = UI[style.lang] ?? UI.en;
|
|
100385
101073
|
const legendNames = style.lang === "fr" ? view.legendNamesFr : view.legendNames;
|
|
100386
101074
|
const legendFlowLabel = style.lang === "fr" ? view.legendFlowLabelFr : view.legendFlowLabel;
|
|
101075
|
+
const legendLineStyles = style.lang === "fr" ? view.legendLineStylesFr : view.legendLineStyles;
|
|
100387
101076
|
const elementStyle = /* @__PURE__ */ new Map();
|
|
100388
|
-
const
|
|
101077
|
+
const elementLogo = /* @__PURE__ */ new Map();
|
|
100389
101078
|
for (const entry of collectElementStyles(model.elements)) {
|
|
100390
101079
|
elementStyle.set(entry.id, entry.style);
|
|
100391
|
-
|
|
101080
|
+
if (entry.logo) elementLogo.set(entry.id, entry.logo);
|
|
100392
101081
|
}
|
|
100393
101082
|
const resolveStyle = (kind, id) => {
|
|
100394
|
-
|
|
100395
|
-
const level = elementAttr.get(id);
|
|
100396
|
-
if (kind === "trust-zone" && level && levelDefaults?.[level]) base = levelDefaults[level];
|
|
101083
|
+
const base = kindDefaults[kind] ?? {};
|
|
100397
101084
|
const perKind = style.kind[kind] ?? {};
|
|
100398
101085
|
const inline = elementStyle.get(id) ?? {};
|
|
100399
101086
|
return {
|
|
@@ -100428,14 +101115,16 @@ function render(model, view, scene) {
|
|
|
100428
101115
|
});
|
|
100429
101116
|
const overlapsAfter = countLabelOverlaps();
|
|
100430
101117
|
compactVertical(scene);
|
|
101118
|
+
fitCanvas(scene);
|
|
101119
|
+
const drawnLogos = /* @__PURE__ */ new Set();
|
|
100431
101120
|
const { renderContainerNode, renderLeafNode } = createNodeRenderers({
|
|
100432
101121
|
palette,
|
|
100433
|
-
style,
|
|
100434
|
-
annot,
|
|
100435
101122
|
nodeFontSize,
|
|
100436
101123
|
containerFontSize,
|
|
100437
101124
|
resolveStyle,
|
|
100438
|
-
|
|
101125
|
+
elementLogo,
|
|
101126
|
+
resolvedLogos: options?.logos,
|
|
101127
|
+
drawnLogos
|
|
100439
101128
|
});
|
|
100440
101129
|
const { renderEdgePath, renderEdgeLabels } = createEdgePainter({
|
|
100441
101130
|
scene,
|
|
@@ -100466,6 +101155,7 @@ function render(model, view, scene) {
|
|
|
100466
101155
|
ui,
|
|
100467
101156
|
legendNames,
|
|
100468
101157
|
legendFlowLabel,
|
|
101158
|
+
legendLineStyles,
|
|
100469
101159
|
scaled,
|
|
100470
101160
|
objectName,
|
|
100471
101161
|
resolveStyle,
|
|
@@ -100478,21 +101168,255 @@ function render(model, view, scene) {
|
|
|
100478
101168
|
if (style.legend === "auto") bands.renderLegendBand();
|
|
100479
101169
|
const bandsSvg = bands.bandsSvg();
|
|
100480
101170
|
const bandY = bands.bandY();
|
|
100481
|
-
const
|
|
100482
|
-
const totalHeight = bandY > viewHeight ? bandY + 14 : viewHeight;
|
|
100483
|
-
const markerSize = style.arrows === "large" ? round1(11 * fonts.scale) : 7;
|
|
101171
|
+
const viewHeight = scene.height;
|
|
100484
101172
|
if (arrowMarkers.size === 0) markerName(defaultEdgeColor);
|
|
100485
|
-
const
|
|
100486
|
-
|
|
100487
|
-
|
|
100488
|
-
|
|
100489
|
-
|
|
100490
|
-
|
|
100491
|
-
|
|
100492
|
-
|
|
101173
|
+
const svg = svgDocument({
|
|
101174
|
+
width: scene.width,
|
|
101175
|
+
height: bandY > viewHeight ? bandY + 14 : viewHeight,
|
|
101176
|
+
fontFamily: style.font.family,
|
|
101177
|
+
background: style.background ?? palette.background,
|
|
101178
|
+
arrowMarkers,
|
|
101179
|
+
markerSize: style.arrows === "large" ? round1(11 * fonts.scale) : 7,
|
|
101180
|
+
body,
|
|
101181
|
+
bandsSvg,
|
|
101182
|
+
// Read after the body is built, so it names the marks that were painted
|
|
101183
|
+
// rather than the ones the model asked for.
|
|
101184
|
+
attribution: logoAttributionComment(drawnLogos)
|
|
101185
|
+
});
|
|
100493
101186
|
return { svg, overlapsBefore, overlapsAfter };
|
|
100494
101187
|
}
|
|
100495
101188
|
|
|
101189
|
+
// src/css-colours.ts
|
|
101190
|
+
var HEX = "#(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})";
|
|
101191
|
+
var NUMBER = String.raw`[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?`;
|
|
101192
|
+
var PERCENT = `${NUMBER}%`;
|
|
101193
|
+
var AMOUNT = `${NUMBER}%?`;
|
|
101194
|
+
var ANGLE = `${NUMBER}(?:deg|grad|rad|turn)?`;
|
|
101195
|
+
var commaForm = (first, second, third) => `${first}\\s*,\\s*${second}\\s*,\\s*${third}(?:\\s*,\\s*${AMOUNT})?`;
|
|
101196
|
+
var spaceForm = (first, second, third) => `${first}\\s+${second}\\s+${third}(?:\\s*/\\s*${AMOUNT})?`;
|
|
101197
|
+
var RGB = `rgba?\\(\\s*(?:${commaForm(NUMBER, NUMBER, NUMBER)}|${commaForm(PERCENT, PERCENT, PERCENT)}|${spaceForm(AMOUNT, AMOUNT, AMOUNT)})\\s*\\)`;
|
|
101198
|
+
var HSL = `hsla?\\(\\s*(?:${commaForm(ANGLE, PERCENT, PERCENT)}|${spaceForm(ANGLE, AMOUNT, AMOUNT)})\\s*\\)`;
|
|
101199
|
+
var NUMERIC_COLOUR = new RegExp(`^(?:${HEX}|${RGB}|${HSL})$`, "i");
|
|
101200
|
+
var COLOUR_KEYWORDS = /* @__PURE__ */ new Set([
|
|
101201
|
+
"currentcolor",
|
|
101202
|
+
"transparent",
|
|
101203
|
+
"aliceblue",
|
|
101204
|
+
"antiquewhite",
|
|
101205
|
+
"aqua",
|
|
101206
|
+
"aquamarine",
|
|
101207
|
+
"azure",
|
|
101208
|
+
"beige",
|
|
101209
|
+
"bisque",
|
|
101210
|
+
"black",
|
|
101211
|
+
"blanchedalmond",
|
|
101212
|
+
"blue",
|
|
101213
|
+
"blueviolet",
|
|
101214
|
+
"brown",
|
|
101215
|
+
"burlywood",
|
|
101216
|
+
"cadetblue",
|
|
101217
|
+
"chartreuse",
|
|
101218
|
+
"chocolate",
|
|
101219
|
+
"coral",
|
|
101220
|
+
"cornflowerblue",
|
|
101221
|
+
"cornsilk",
|
|
101222
|
+
"crimson",
|
|
101223
|
+
"cyan",
|
|
101224
|
+
"darkblue",
|
|
101225
|
+
"darkcyan",
|
|
101226
|
+
"darkgoldenrod",
|
|
101227
|
+
"darkgray",
|
|
101228
|
+
"darkgreen",
|
|
101229
|
+
"darkgrey",
|
|
101230
|
+
"darkkhaki",
|
|
101231
|
+
"darkmagenta",
|
|
101232
|
+
"darkolivegreen",
|
|
101233
|
+
"darkorange",
|
|
101234
|
+
"darkorchid",
|
|
101235
|
+
"darkred",
|
|
101236
|
+
"darksalmon",
|
|
101237
|
+
"darkseagreen",
|
|
101238
|
+
"darkslateblue",
|
|
101239
|
+
"darkslategray",
|
|
101240
|
+
"darkslategrey",
|
|
101241
|
+
"darkturquoise",
|
|
101242
|
+
"darkviolet",
|
|
101243
|
+
"deeppink",
|
|
101244
|
+
"deepskyblue",
|
|
101245
|
+
"dimgray",
|
|
101246
|
+
"dimgrey",
|
|
101247
|
+
"dodgerblue",
|
|
101248
|
+
"firebrick",
|
|
101249
|
+
"floralwhite",
|
|
101250
|
+
"forestgreen",
|
|
101251
|
+
"fuchsia",
|
|
101252
|
+
"gainsboro",
|
|
101253
|
+
"ghostwhite",
|
|
101254
|
+
"gold",
|
|
101255
|
+
"goldenrod",
|
|
101256
|
+
"gray",
|
|
101257
|
+
"green",
|
|
101258
|
+
"greenyellow",
|
|
101259
|
+
"grey",
|
|
101260
|
+
"honeydew",
|
|
101261
|
+
"hotpink",
|
|
101262
|
+
"indianred",
|
|
101263
|
+
"indigo",
|
|
101264
|
+
"ivory",
|
|
101265
|
+
"khaki",
|
|
101266
|
+
"lavender",
|
|
101267
|
+
"lavenderblush",
|
|
101268
|
+
"lawngreen",
|
|
101269
|
+
"lemonchiffon",
|
|
101270
|
+
"lightblue",
|
|
101271
|
+
"lightcoral",
|
|
101272
|
+
"lightcyan",
|
|
101273
|
+
"lightgoldenrodyellow",
|
|
101274
|
+
"lightgray",
|
|
101275
|
+
"lightgreen",
|
|
101276
|
+
"lightgrey",
|
|
101277
|
+
"lightpink",
|
|
101278
|
+
"lightsalmon",
|
|
101279
|
+
"lightseagreen",
|
|
101280
|
+
"lightskyblue",
|
|
101281
|
+
"lightslategray",
|
|
101282
|
+
"lightslategrey",
|
|
101283
|
+
"lightsteelblue",
|
|
101284
|
+
"lightyellow",
|
|
101285
|
+
"lime",
|
|
101286
|
+
"limegreen",
|
|
101287
|
+
"linen",
|
|
101288
|
+
"magenta",
|
|
101289
|
+
"maroon",
|
|
101290
|
+
"mediumaquamarine",
|
|
101291
|
+
"mediumblue",
|
|
101292
|
+
"mediumorchid",
|
|
101293
|
+
"mediumpurple",
|
|
101294
|
+
"mediumseagreen",
|
|
101295
|
+
"mediumslateblue",
|
|
101296
|
+
"mediumspringgreen",
|
|
101297
|
+
"mediumturquoise",
|
|
101298
|
+
"mediumvioletred",
|
|
101299
|
+
"midnightblue",
|
|
101300
|
+
"mintcream",
|
|
101301
|
+
"mistyrose",
|
|
101302
|
+
"moccasin",
|
|
101303
|
+
"navajowhite",
|
|
101304
|
+
"navy",
|
|
101305
|
+
"oldlace",
|
|
101306
|
+
"olive",
|
|
101307
|
+
"olivedrab",
|
|
101308
|
+
"orange",
|
|
101309
|
+
"orangered",
|
|
101310
|
+
"orchid",
|
|
101311
|
+
"palegoldenrod",
|
|
101312
|
+
"palegreen",
|
|
101313
|
+
"paleturquoise",
|
|
101314
|
+
"palevioletred",
|
|
101315
|
+
"papayawhip",
|
|
101316
|
+
"peachpuff",
|
|
101317
|
+
"peru",
|
|
101318
|
+
"pink",
|
|
101319
|
+
"plum",
|
|
101320
|
+
"powderblue",
|
|
101321
|
+
"purple",
|
|
101322
|
+
"rebeccapurple",
|
|
101323
|
+
"red",
|
|
101324
|
+
"rosybrown",
|
|
101325
|
+
"royalblue",
|
|
101326
|
+
"saddlebrown",
|
|
101327
|
+
"salmon",
|
|
101328
|
+
"sandybrown",
|
|
101329
|
+
"seagreen",
|
|
101330
|
+
"seashell",
|
|
101331
|
+
"sienna",
|
|
101332
|
+
"silver",
|
|
101333
|
+
"skyblue",
|
|
101334
|
+
"slateblue",
|
|
101335
|
+
"slategray",
|
|
101336
|
+
"slategrey",
|
|
101337
|
+
"snow",
|
|
101338
|
+
"springgreen",
|
|
101339
|
+
"steelblue",
|
|
101340
|
+
"tan",
|
|
101341
|
+
"teal",
|
|
101342
|
+
"thistle",
|
|
101343
|
+
"tomato",
|
|
101344
|
+
"turquoise",
|
|
101345
|
+
"violet",
|
|
101346
|
+
"wheat",
|
|
101347
|
+
"white",
|
|
101348
|
+
"whitesmoke",
|
|
101349
|
+
"yellow",
|
|
101350
|
+
"yellowgreen"
|
|
101351
|
+
]);
|
|
101352
|
+
var isColour = (value) => NUMERIC_COLOUR.test(value) || COLOUR_KEYWORDS.has(value.toLowerCase());
|
|
101353
|
+
|
|
101354
|
+
// src/theme-spec.ts
|
|
101355
|
+
var DEFAULT_BASE = "light";
|
|
101356
|
+
var ThemeSpecError = class extends Error {
|
|
101357
|
+
};
|
|
101358
|
+
var isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
101359
|
+
var merge = (base, patch) => {
|
|
101360
|
+
const merged = { ...base };
|
|
101361
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
101362
|
+
if (key === "extends") continue;
|
|
101363
|
+
const current = merged[key];
|
|
101364
|
+
merged[key] = isObject(value) && isObject(current) ? { ...current, ...value } : value;
|
|
101365
|
+
}
|
|
101366
|
+
return merged;
|
|
101367
|
+
};
|
|
101368
|
+
var SECTIONS = ["pal", "accentColors"];
|
|
101369
|
+
var arityOf = (section, key) => {
|
|
101370
|
+
if (section === "pal") return key === "chip" ? 3 : key === "badge" ? 2 : 1;
|
|
101371
|
+
return 1;
|
|
101372
|
+
};
|
|
101373
|
+
var describe = (value) => Array.isArray(value) ? `an array of ${value.length}` : typeof value;
|
|
101374
|
+
function checkEntry(path, value, arity) {
|
|
101375
|
+
if (arity === 1) {
|
|
101376
|
+
if (typeof value !== "string") {
|
|
101377
|
+
throw new ThemeSpecError(`\`${path}\` must be a colour, got ${describe(value)}`);
|
|
101378
|
+
}
|
|
101379
|
+
} else if (!Array.isArray(value) || value.length !== arity) {
|
|
101380
|
+
throw new ThemeSpecError(`\`${path}\` must be ${arity} colours, got ${describe(value)}`);
|
|
101381
|
+
}
|
|
101382
|
+
for (const colour of Array.isArray(value) ? value : [value]) {
|
|
101383
|
+
if (typeof colour !== "string" || !isColour(colour)) {
|
|
101384
|
+
throw new ThemeSpecError(`\`${path}\`: \`${String(colour)}\` is not a colour`);
|
|
101385
|
+
}
|
|
101386
|
+
}
|
|
101387
|
+
}
|
|
101388
|
+
function resolveThemeSpec(input) {
|
|
101389
|
+
if (!isObject(input)) throw new ThemeSpecError("a theme must be an object");
|
|
101390
|
+
const base = input.extends ?? DEFAULT_BASE;
|
|
101391
|
+
if (typeof base !== "string") throw new ThemeSpecError("`extends` must be a theme name");
|
|
101392
|
+
const baseSpec = Object.hasOwn(THEME_SPECS, base) ? THEME_SPECS[base] : void 0;
|
|
101393
|
+
if (!baseSpec) {
|
|
101394
|
+
throw new ThemeSpecError(
|
|
101395
|
+
`extends unknown theme \`${base}\` \u2014 pick one of: ${Object.keys(THEME_SPECS).join(", ")}`
|
|
101396
|
+
);
|
|
101397
|
+
}
|
|
101398
|
+
if ("dark" in input && typeof input.dark !== "boolean") {
|
|
101399
|
+
throw new ThemeSpecError("`dark` must be true or false");
|
|
101400
|
+
}
|
|
101401
|
+
for (const [section, value] of Object.entries(input)) {
|
|
101402
|
+
if (section === "extends" || section === "dark") continue;
|
|
101403
|
+
if (!SECTIONS.includes(section)) {
|
|
101404
|
+
throw new ThemeSpecError(
|
|
101405
|
+
`unknown section \`${section}\` \u2014 a theme overrides ${SECTIONS.join(", ")}`
|
|
101406
|
+
);
|
|
101407
|
+
}
|
|
101408
|
+
if (!isObject(value)) {
|
|
101409
|
+
throw new ThemeSpecError(
|
|
101410
|
+
`\`${section}\` must be an object of colours, got ${describe(value)}`
|
|
101411
|
+
);
|
|
101412
|
+
}
|
|
101413
|
+
for (const [key, colour] of Object.entries(value)) {
|
|
101414
|
+
checkEntry(`${section}.${key}`, colour, arityOf(section, key));
|
|
101415
|
+
}
|
|
101416
|
+
}
|
|
101417
|
+
return merge(baseSpec, input);
|
|
101418
|
+
}
|
|
101419
|
+
|
|
100496
101420
|
// src/flow-matrix.ts
|
|
100497
101421
|
var COLUMN_PRESENTATION = {
|
|
100498
101422
|
num: { align: "middle", maxWidth: 220 },
|
|
@@ -100587,8 +101511,9 @@ function matrixMd(matrix) {
|
|
|
100587
101511
|
for (const row of matrix.rows) outLines.push("| " + row.cells.map(mdCell).join(" | ") + " |");
|
|
100588
101512
|
return outLines.join("\n") + "\n";
|
|
100589
101513
|
}
|
|
100590
|
-
function matrixSvg(matrix) {
|
|
100591
|
-
const
|
|
101514
|
+
function matrixSvg(matrix, options) {
|
|
101515
|
+
const requested = options?.theme;
|
|
101516
|
+
const pal = typeof requested === "object" ? paletteFromSpec(resolveThemeSpec(requested)) : paletteFor(requested ?? matrix.style.theme);
|
|
100592
101517
|
const title = matrix.heading;
|
|
100593
101518
|
const headers = matrix.columns.map((column) => column.label);
|
|
100594
101519
|
const cells = matrix.rows.map((row) => row.cells);
|
|
@@ -100654,7 +101579,8 @@ function matrixSvg(matrix) {
|
|
|
100654
101579
|
// src/compile.ts
|
|
100655
101580
|
async function compile(source, options) {
|
|
100656
101581
|
const { model, diags } = parse(source);
|
|
100657
|
-
|
|
101582
|
+
const theme = typeof options?.theme === "object" ? resolveThemeSpec(options.theme) : void 0;
|
|
101583
|
+
if (typeof options?.theme === "string") model.style.theme = options.theme;
|
|
100658
101584
|
diags.push(...validate(model));
|
|
100659
101585
|
const errors = diags.filter((diagnostic) => diagnostic.severity === "error");
|
|
100660
101586
|
if (errors.length || !model.type || !views[model.type]) {
|
|
@@ -100664,7 +101590,7 @@ async function compile(source, options) {
|
|
|
100664
101590
|
const matrix = options?.matrix ? buildFlowMatrix(model, view) : null;
|
|
100665
101591
|
const scene = await layout(model, view);
|
|
100666
101592
|
diags.push(...attachSideDiagnostics(scene, model));
|
|
100667
|
-
const { svg, overlapsAfter } = render(model, view, scene);
|
|
101593
|
+
const { svg, overlapsAfter } = render(model, view, scene, { logos: options?.logos, theme });
|
|
100668
101594
|
return {
|
|
100669
101595
|
svg,
|
|
100670
101596
|
diagnostics: diags,
|
|
@@ -100679,16 +101605,18 @@ async function compile(source, options) {
|
|
|
100679
101605
|
}
|
|
100680
101606
|
|
|
100681
101607
|
// src/api.ts
|
|
100682
|
-
var version = true ? "1.0.0-
|
|
101608
|
+
var version = true ? "1.0.0-RC15" : pkg.version;
|
|
100683
101609
|
|
|
100684
101610
|
// src/playground.ts
|
|
100685
101611
|
var ElkClass = import_elk_bundled.default;
|
|
100686
101612
|
setElkFactory(() => new ElkClass());
|
|
100687
101613
|
export {
|
|
101614
|
+
ThemeSpecError,
|
|
100688
101615
|
compile,
|
|
100689
101616
|
matrixCsv,
|
|
100690
101617
|
matrixMd,
|
|
100691
101618
|
matrixSvg,
|
|
101619
|
+
resolveThemeSpec,
|
|
100692
101620
|
themeNames,
|
|
100693
101621
|
version
|
|
100694
101622
|
};
|