@diagrammo/dgmo 0.33.0 → 0.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/commands/dgmo.md +17 -32
- package/.github/copilot-instructions.md +1 -1
- package/README.md +7 -1
- package/SKILL.md +1 -1
- package/dist/advanced.cjs +791 -614
- package/dist/advanced.d.cts +8 -51
- package/dist/advanced.d.ts +8 -51
- package/dist/advanced.js +791 -615
- package/dist/auto.cjs +793 -292
- package/dist/auto.js +95 -95
- package/dist/auto.mjs +793 -292
- package/dist/cli.cjs +145 -328
- package/dist/index.cjs +792 -291
- package/dist/index.js +792 -291
- package/docs/ai-integration.md +46 -26
- package/docs/language-reference.md +2 -2
- package/package.json +3 -3
- package/src/advanced.ts +0 -12
- package/src/boxes-and-lines/label-placement.ts +339 -0
- package/src/boxes-and-lines/layout-search.ts +16 -2
- package/src/boxes-and-lines/layout.ts +32 -7
- package/src/boxes-and-lines/renderer.ts +67 -139
- package/src/c4/parser.ts +15 -6
- package/src/chart.ts +1 -1
- package/src/class/parser.ts +6 -2
- package/src/cli-banner.ts +2 -3
- package/src/cli.ts +539 -1223
- package/src/cycle/parser.ts +4 -1
- package/src/dgmo-router.ts +16 -2
- package/src/diagnostics.ts +0 -0
- package/src/echarts.ts +5 -1
- package/src/er/parser.ts +5 -1
- package/src/gantt/parser.ts +13 -4
- package/src/graph/flowchart-parser.ts +5 -1
- package/src/graph/state-parser.ts +5 -1
- package/src/infra/parser.ts +10 -6
- package/src/journey-map/parser.ts +5 -2
- package/src/kanban/parser.ts +6 -2
- package/src/map/context-labels.ts +29 -19
- package/src/map/layout.ts +403 -108
- package/src/map/legend-band.ts +28 -0
- package/src/map/parser.ts +13 -4
- package/src/map/renderer.ts +74 -23
- package/src/map/resolver.ts +2 -2
- package/src/org/parser.ts +8 -2
- package/src/pyramid/parser.ts +4 -1
- package/src/raci/parser.ts +4 -1
- package/src/ring/parser.ts +4 -1
- package/src/sequence/parser.ts +6 -3
- package/src/sitemap/parser.ts +12 -3
- package/src/tech-radar/parser.ts +6 -3
- package/src/utils/parsing.ts +2 -2
- package/src/utils/tag-groups.ts +3 -3
- package/src/visualizations/parse.ts +9 -3
- package/src/migrate/data-comma.ts +0 -117
- package/src/migrate/embedded.ts +0 -238
- package/src/migrate/index.ts +0 -295
- package/src/migrate/line-classifier.ts +0 -128
- package/src/migrate/line-transformer.ts +0 -218
package/dist/advanced.cjs
CHANGED
|
@@ -37,6 +37,17 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
37
37
|
function makeDgmoError(line11, message, severity = "error", code) {
|
|
38
38
|
return code !== void 0 ? { line: line11, message, severity, code } : { line: line11, message, severity };
|
|
39
39
|
}
|
|
40
|
+
function dedupeDiagnostics(diagnostics) {
|
|
41
|
+
const seen = /* @__PURE__ */ new Set();
|
|
42
|
+
const out = [];
|
|
43
|
+
for (const d of diagnostics) {
|
|
44
|
+
const key = `${d.line}\0${d.column ?? ""}\0${d.severity}\0${d.code ?? ""}\0${d.message}`;
|
|
45
|
+
if (seen.has(key)) continue;
|
|
46
|
+
seen.add(key);
|
|
47
|
+
out.push(d);
|
|
48
|
+
}
|
|
49
|
+
return out;
|
|
50
|
+
}
|
|
40
51
|
function formatDgmoError(err) {
|
|
41
52
|
return err.line > 0 ? `Line ${err.line}: ${err.message}` : err.message;
|
|
42
53
|
}
|
|
@@ -94,7 +105,7 @@ function vennAliasKeywordRemovedMessage(args) {
|
|
|
94
105
|
return `Venn 'alias' keyword was removed. Use 'as' instead \u2014 '${args.name} as ${args.alias}'.`;
|
|
95
106
|
}
|
|
96
107
|
function pipeOperatorRemovedMessage() {
|
|
97
|
-
return `'|' removed \u2014 'Node | c: red' \u2192 'Node c: red'
|
|
108
|
+
return `'|' removed \u2014 'Node | c: red' \u2192 'Node c: red'`;
|
|
98
109
|
}
|
|
99
110
|
function ganttBarePercentRemovedMessage(percent) {
|
|
100
111
|
return `Bare-percent progress shorthand '| ${percent}' was removed. Use 'progress: ${percent.replace(/%$/, "")}' (integer 0\u2013100, no '%').`;
|
|
@@ -1247,7 +1258,7 @@ var init_parsing = __esm({
|
|
|
1247
1258
|
"no-title",
|
|
1248
1259
|
"no-notes"
|
|
1249
1260
|
]);
|
|
1250
|
-
MULTIPLE_PIPE_ERROR = '
|
|
1261
|
+
MULTIPLE_PIPE_ERROR = "'|' is no longer metadata syntax \u2014 put metadata on the same line as 'key: value, key2: value2' (no pipes), per \xA71.4.";
|
|
1251
1262
|
RESERVED_KEY_RE = /^[A-Za-z][A-Za-z0-9_-]*$/;
|
|
1252
1263
|
AS_ALIAS_RE = /\s+as\s+([A-Za-z][A-Za-z0-9_]{0,11})$/;
|
|
1253
1264
|
POTENTIAL_META_RE = /\b([\w-]+)\s*:/;
|
|
@@ -1428,12 +1439,10 @@ function validateTagValues(entities, tagGroups, pushWarning, suggestFn) {
|
|
|
1428
1439
|
);
|
|
1429
1440
|
if (!isPrefix) {
|
|
1430
1441
|
const defined = group.entries.map((e) => e.value);
|
|
1431
|
-
let msg = `Unknown value '${value}' for tag group '${group.name}'`;
|
|
1442
|
+
let msg = `Unknown value '${value}' for tag group '${group.name}' \u2014 use one of: ${defined.join(", ")}`;
|
|
1432
1443
|
const hint = suggestFn?.(value, defined);
|
|
1433
1444
|
if (hint) {
|
|
1434
1445
|
msg += `. ${hint}`;
|
|
1435
|
-
} else {
|
|
1436
|
-
msg += ` \u2014 defined values: ${defined.join(", ")}`;
|
|
1437
1446
|
}
|
|
1438
1447
|
pushWarning(entity.lineNumber, msg);
|
|
1439
1448
|
}
|
|
@@ -2209,7 +2218,10 @@ function parseVisualizationFull(content, palette) {
|
|
|
2209
2218
|
lineNumber
|
|
2210
2219
|
});
|
|
2211
2220
|
} else {
|
|
2212
|
-
warn(
|
|
2221
|
+
warn(
|
|
2222
|
+
lineNumber,
|
|
2223
|
+
`Unrecognized era entry: "${line11}" \u2014 use '<start> -> <end> Label [color]' (e.g. '1716 -> 1717 Reign').`
|
|
2224
|
+
);
|
|
2213
2225
|
}
|
|
2214
2226
|
continue;
|
|
2215
2227
|
}
|
|
@@ -2237,7 +2249,10 @@ function parseVisualizationFull(content, palette) {
|
|
|
2237
2249
|
lineNumber
|
|
2238
2250
|
});
|
|
2239
2251
|
} else {
|
|
2240
|
-
warn(
|
|
2252
|
+
warn(
|
|
2253
|
+
lineNumber,
|
|
2254
|
+
`Unrecognized marker entry: "${line11}" \u2014 use '<date> Label [color]' (e.g. '1776 Independence').`
|
|
2255
|
+
);
|
|
2241
2256
|
}
|
|
2242
2257
|
continue;
|
|
2243
2258
|
}
|
|
@@ -2915,7 +2930,7 @@ function parseVisualizationFull(content, palette) {
|
|
|
2915
2930
|
result.diagnostics.push(
|
|
2916
2931
|
makeDgmoError(
|
|
2917
2932
|
ov.lineNumber,
|
|
2918
|
-
`Intersection references unknown set or alias "${ref}"`
|
|
2933
|
+
`Intersection references unknown set or alias "${ref}" \u2014 declare the set first on its own line ('Name [as <alias>] [color]', e.g. 'Navigation as nav blue'), then reference it by that name or alias. (\xA716.4)`
|
|
2919
2934
|
)
|
|
2920
2935
|
);
|
|
2921
2936
|
if (!result.error)
|
|
@@ -6298,10 +6313,10 @@ function parseSequenceDgmo(content, palette) {
|
|
|
6298
6313
|
const rawInside = fallbackMatch[1];
|
|
6299
6314
|
const pipeIdx = rawInside.indexOf("|");
|
|
6300
6315
|
const cleanName = rawInside.substring(0, pipeIdx).trim().replace(/\([^)]*\)$/, "").trim();
|
|
6301
|
-
const metaPart = rawInside.substring(pipeIdx).trim();
|
|
6316
|
+
const metaPart = rawInside.substring(pipeIdx).replace(/^\|\s*/, "").trim();
|
|
6302
6317
|
pushError(
|
|
6303
6318
|
lineNumber,
|
|
6304
|
-
`
|
|
6319
|
+
`Metadata goes after the bracket with no pipe \u2014 use '[${cleanName}] ${metaPart}' (e.g. '[Backend] t: Product'), not '[${rawInside.trim()}]'`
|
|
6305
6320
|
);
|
|
6306
6321
|
continue;
|
|
6307
6322
|
}
|
|
@@ -6911,7 +6926,7 @@ function parseSequenceDgmo(content, palette) {
|
|
|
6911
6926
|
}
|
|
6912
6927
|
pushWarning(
|
|
6913
6928
|
lineNumber,
|
|
6914
|
-
`Unexpected line: '${trimmed}'. Expected a message (A -> B), participant, section (== Name ==), or block
|
|
6929
|
+
`Unexpected line: '${trimmed}'. Expected a message ('A -> B' or 'A -label-> B'), participant ('Name' or 'Name is a actor'), note ('note right of A Text'), section ('== Name =='), or block ('if/loop/parallel <label>').`
|
|
6915
6930
|
);
|
|
6916
6931
|
}
|
|
6917
6932
|
if (!hasExplicitChart && result.messages.length === 0) {
|
|
@@ -8073,7 +8088,11 @@ function parseFlowchart(content, palette) {
|
|
|
8073
8088
|
const value = optMatch[2].trim();
|
|
8074
8089
|
if (key === "no-color") {
|
|
8075
8090
|
result.diagnostics.push(
|
|
8076
|
-
makeDgmoError(
|
|
8091
|
+
makeDgmoError(
|
|
8092
|
+
lineNumber,
|
|
8093
|
+
'"no-color" was removed \u2014 node colors are assigned automatically by shape; delete this line.',
|
|
8094
|
+
"warning"
|
|
8095
|
+
)
|
|
8077
8096
|
);
|
|
8078
8097
|
continue;
|
|
8079
8098
|
}
|
|
@@ -8402,7 +8421,11 @@ function parseState(content, palette) {
|
|
|
8402
8421
|
const value = optMatch[2].trim();
|
|
8403
8422
|
if (key === "no-color") {
|
|
8404
8423
|
result.diagnostics.push(
|
|
8405
|
-
makeDgmoError(
|
|
8424
|
+
makeDgmoError(
|
|
8425
|
+
lineNumber,
|
|
8426
|
+
'"no-color" was removed \u2014 state colors are assigned automatically; delete this line.',
|
|
8427
|
+
"warning"
|
|
8428
|
+
)
|
|
8406
8429
|
);
|
|
8407
8430
|
continue;
|
|
8408
8431
|
}
|
|
@@ -8717,7 +8740,7 @@ function parseClassDiagram(content, palette) {
|
|
|
8717
8740
|
result.diagnostics.push(
|
|
8718
8741
|
makeDgmoError(
|
|
8719
8742
|
lineNumber,
|
|
8720
|
-
'"no-auto-color"
|
|
8743
|
+
'"no-auto-color" was removed \u2014 colors are always auto-assigned from the palette; delete this line.',
|
|
8721
8744
|
"warning"
|
|
8722
8745
|
)
|
|
8723
8746
|
);
|
|
@@ -8832,7 +8855,11 @@ function parseClassDiagram(content, palette) {
|
|
|
8832
8855
|
continue;
|
|
8833
8856
|
}
|
|
8834
8857
|
result.diagnostics.push(
|
|
8835
|
-
makeDgmoError(
|
|
8858
|
+
makeDgmoError(
|
|
8859
|
+
lineNumber,
|
|
8860
|
+
`Unexpected line: '${trimmed}'. Classes start uppercase at indent 0 ('Ship'); members are indented and colon-typed ('+ name: string', '+ sail(): void'); relationships are indented arrows ('--|> Vessel'). (\xA710)`,
|
|
8861
|
+
"warning"
|
|
8862
|
+
)
|
|
8836
8863
|
);
|
|
8837
8864
|
}
|
|
8838
8865
|
if (notes.length > 0) {
|
|
@@ -9310,7 +9337,11 @@ function parseERDiagram(content, palette) {
|
|
|
9310
9337
|
continue;
|
|
9311
9338
|
}
|
|
9312
9339
|
result.diagnostics.push(
|
|
9313
|
-
makeDgmoError(
|
|
9340
|
+
makeDgmoError(
|
|
9341
|
+
lineNumber,
|
|
9342
|
+
`Unexpected line: '${trimmed}'. A table is a bare name at indent 0 ('users'); columns are indented and SPACE-separated, no colon ('id int pk'); relationships are indented ('1--* orders'). (\xA79)`,
|
|
9343
|
+
"warning"
|
|
9344
|
+
)
|
|
9314
9345
|
);
|
|
9315
9346
|
}
|
|
9316
9347
|
if (result.tables.length === 0 && !result.error) {
|
|
@@ -9654,7 +9685,10 @@ function parseOrg(content, palette) {
|
|
|
9654
9685
|
const value = metadataMatch[2].trim();
|
|
9655
9686
|
const parent = findMetadataParent(indent, indentStack);
|
|
9656
9687
|
if (!parent) {
|
|
9657
|
-
pushError(
|
|
9688
|
+
pushError(
|
|
9689
|
+
lineNumber,
|
|
9690
|
+
"Metadata 'key: value' must be indented under a node \u2014 no node precedes it."
|
|
9691
|
+
);
|
|
9658
9692
|
} else {
|
|
9659
9693
|
parent.metadata = { ...parent.metadata, [key]: value };
|
|
9660
9694
|
}
|
|
@@ -9672,7 +9706,10 @@ function parseOrg(content, palette) {
|
|
|
9672
9706
|
);
|
|
9673
9707
|
attachNode(node, indent, indentStack, result);
|
|
9674
9708
|
} else {
|
|
9675
|
-
pushError(
|
|
9709
|
+
pushError(
|
|
9710
|
+
lineNumber,
|
|
9711
|
+
"Metadata 'key: value' must be indented under a node \u2014 no node precedes it."
|
|
9712
|
+
);
|
|
9676
9713
|
}
|
|
9677
9714
|
} else {
|
|
9678
9715
|
const node = parseNodeLabel(
|
|
@@ -10021,7 +10058,10 @@ function parseSitemap(content, palette) {
|
|
|
10021
10058
|
if (arrowInfo) {
|
|
10022
10059
|
const source = findParentNode(indent, indentStack);
|
|
10023
10060
|
if (!source) {
|
|
10024
|
-
pushError(
|
|
10061
|
+
pushError(
|
|
10062
|
+
lineNumber,
|
|
10063
|
+
"Arrow '-> target' must be indented under its source page \u2014 no page precedes it."
|
|
10064
|
+
);
|
|
10025
10065
|
} else {
|
|
10026
10066
|
deferredArrows.push({
|
|
10027
10067
|
sourceNode: source,
|
|
@@ -10091,7 +10131,10 @@ function parseSitemap(content, palette) {
|
|
|
10091
10131
|
const value = metadataMatch[2].trim();
|
|
10092
10132
|
const parent = findParentNode(indent, indentStack);
|
|
10093
10133
|
if (!parent) {
|
|
10094
|
-
pushError(
|
|
10134
|
+
pushError(
|
|
10135
|
+
lineNumber,
|
|
10136
|
+
"Metadata 'key: value' must be indented under a page \u2014 no page precedes it."
|
|
10137
|
+
);
|
|
10095
10138
|
} else {
|
|
10096
10139
|
parent.metadata = { ...parent.metadata, [key]: value };
|
|
10097
10140
|
}
|
|
@@ -10111,7 +10154,10 @@ function parseSitemap(content, palette) {
|
|
|
10111
10154
|
const key = normalizeName(node.label);
|
|
10112
10155
|
labelToNode.set(key, node);
|
|
10113
10156
|
} else {
|
|
10114
|
-
pushError(
|
|
10157
|
+
pushError(
|
|
10158
|
+
lineNumber,
|
|
10159
|
+
"Metadata 'key: value' must be indented under a page \u2014 no page precedes it."
|
|
10160
|
+
);
|
|
10115
10161
|
}
|
|
10116
10162
|
} else {
|
|
10117
10163
|
const descResult = tryStripDescriptionKeyword(trimmed);
|
|
@@ -11929,7 +11975,7 @@ function parseChart(content, palette) {
|
|
|
11929
11975
|
result.diagnostics.push(
|
|
11930
11976
|
makeDgmoError(
|
|
11931
11977
|
lineNumber,
|
|
11932
|
-
`'${trimmed}' \u2014 ##
|
|
11978
|
+
`'${trimmed}' removed \u2014 use a bracket container '[${trimmed.replace(/^#+\s*/, "")}]' instead (## headers are no longer supported).`
|
|
11933
11979
|
)
|
|
11934
11980
|
);
|
|
11935
11981
|
continue;
|
|
@@ -12899,7 +12945,11 @@ function parseExtendedChartFull(content, palette) {
|
|
|
12899
12945
|
continue;
|
|
12900
12946
|
}
|
|
12901
12947
|
result.diagnostics.push(
|
|
12902
|
-
makeDgmoError(
|
|
12948
|
+
makeDgmoError(
|
|
12949
|
+
lineNumber,
|
|
12950
|
+
`Unexpected line: '${trimmed}'. Expected a data row ('Label value', space-separated) or a known option.`,
|
|
12951
|
+
"warning"
|
|
12952
|
+
)
|
|
12903
12953
|
);
|
|
12904
12954
|
}
|
|
12905
12955
|
const warn = (line11, message) => {
|
|
@@ -15261,7 +15311,10 @@ function parseKanban(content, palette) {
|
|
|
15261
15311
|
continue;
|
|
15262
15312
|
}
|
|
15263
15313
|
if (!currentColumn) {
|
|
15264
|
-
warn(
|
|
15314
|
+
warn(
|
|
15315
|
+
lineNumber,
|
|
15316
|
+
"Card line found before any column. Declare a column first with '[Column Name]', then indent cards beneath it. (\xA711)"
|
|
15317
|
+
);
|
|
15265
15318
|
continue;
|
|
15266
15319
|
}
|
|
15267
15320
|
if (currentCard && indent > cardBaseIndent) {
|
|
@@ -15400,7 +15453,7 @@ var init_parser13 = __esm({
|
|
|
15400
15453
|
KNOWN_OPTIONS4 = /* @__PURE__ */ new Set(["hide", "active-tag"]);
|
|
15401
15454
|
KNOWN_BOOLEANS3 = /* @__PURE__ */ new Set(["solid-fill", "no-title"]);
|
|
15402
15455
|
REMOVED_BOOLEANS = {
|
|
15403
|
-
"no-auto-color": '"no-auto-color"
|
|
15456
|
+
"no-auto-color": '"no-auto-color" was removed \u2014 colors are always auto-assigned from the palette; delete this line.'
|
|
15404
15457
|
};
|
|
15405
15458
|
}
|
|
15406
15459
|
});
|
|
@@ -15637,7 +15690,7 @@ function parseC4(content, palette) {
|
|
|
15637
15690
|
} else {
|
|
15638
15691
|
pushError(
|
|
15639
15692
|
lineNumber,
|
|
15640
|
-
`"container ${refName}" must be
|
|
15693
|
+
`"container ${refName}" must be indented under a deployment node (e.g. under 'Prod is a deployment-node')`
|
|
15641
15694
|
);
|
|
15642
15695
|
}
|
|
15643
15696
|
continue;
|
|
@@ -15692,7 +15745,10 @@ function parseC4(content, palette) {
|
|
|
15692
15745
|
indent
|
|
15693
15746
|
});
|
|
15694
15747
|
} else {
|
|
15695
|
-
pushError(
|
|
15748
|
+
pushError(
|
|
15749
|
+
lineNumber,
|
|
15750
|
+
`"${sectionType}" must be indented under an element (e.g. under 'Web App is a container')`
|
|
15751
|
+
);
|
|
15696
15752
|
}
|
|
15697
15753
|
continue;
|
|
15698
15754
|
}
|
|
@@ -15719,7 +15775,10 @@ function parseC4(content, palette) {
|
|
|
15719
15775
|
indent
|
|
15720
15776
|
});
|
|
15721
15777
|
} else {
|
|
15722
|
-
pushError(
|
|
15778
|
+
pushError(
|
|
15779
|
+
lineNumber,
|
|
15780
|
+
`Group [${groupName}] must be indented under an element (e.g. under 'Web App is a container')`
|
|
15781
|
+
);
|
|
15723
15782
|
}
|
|
15724
15783
|
continue;
|
|
15725
15784
|
}
|
|
@@ -16049,7 +16108,10 @@ function parseC4(content, palette) {
|
|
|
16049
16108
|
}
|
|
16050
16109
|
desc.push(descResult.text);
|
|
16051
16110
|
} else {
|
|
16052
|
-
pushError(
|
|
16111
|
+
pushError(
|
|
16112
|
+
lineNumber,
|
|
16113
|
+
`Unexpected content: "${trimmed}". Expected an element ('Web App is a container'), a relationship ('-Uses-> Database'), indented metadata ('tech: React'), or a group ('[Backend]'). (\xA78)`
|
|
16114
|
+
);
|
|
16053
16115
|
}
|
|
16054
16116
|
}
|
|
16055
16117
|
finalizeAutoTagColors(result.tagGroups, palette);
|
|
@@ -16111,7 +16173,7 @@ function validateRelationshipTargets(result, knownNames, pushWarning) {
|
|
|
16111
16173
|
for (const el of elements) {
|
|
16112
16174
|
for (const rel of el.relationships) {
|
|
16113
16175
|
if (!knownNames.has(normalizeName(rel.target))) {
|
|
16114
|
-
let msg = `Relationship target "${rel.target}" not found`;
|
|
16176
|
+
let msg = `Relationship target "${rel.target}" not found \u2014 declare it first (e.g. '${rel.target} is a container'), then reference it in the arrow`;
|
|
16115
16177
|
const hint = suggest(normalizeName(rel.target), allNames);
|
|
16116
16178
|
if (hint) msg += `. ${hint}`;
|
|
16117
16179
|
pushWarning(rel.lineNumber, msg, "warning");
|
|
@@ -16139,7 +16201,7 @@ function validateDeploymentRefs(result, knownNames, pushWarning) {
|
|
|
16139
16201
|
for (const node of nodes) {
|
|
16140
16202
|
for (const ref of node.containerRefs) {
|
|
16141
16203
|
if (!knownNames.has(normalizeName(ref))) {
|
|
16142
|
-
let msg = `Deployment reference "container ${ref}" not found`;
|
|
16204
|
+
let msg = `Deployment reference "container ${ref}" not found \u2014 declare the container element first, then reference it under the deployment node`;
|
|
16143
16205
|
const hint = suggest(normalizeName(ref), allNames);
|
|
16144
16206
|
if (hint) msg += `. ${hint}`;
|
|
16145
16207
|
pushWarning(node.lineNumber, msg, "warning");
|
|
@@ -16858,7 +16920,7 @@ function parseInfra(content) {
|
|
|
16858
16920
|
}
|
|
16859
16921
|
warn(
|
|
16860
16922
|
lineNumber,
|
|
16861
|
-
`Invalid tag value '${trimmed}' in tag group '${currentTagGroup.name}'.`
|
|
16923
|
+
`Invalid tag value '${trimmed}' in tag group '${currentTagGroup.name}' \u2014 a value is a bare word with an optional trailing color (e.g. 'Production red'); no ':' or '|'.`
|
|
16862
16924
|
);
|
|
16863
16925
|
continue;
|
|
16864
16926
|
}
|
|
@@ -16931,7 +16993,7 @@ function parseInfra(content) {
|
|
|
16931
16993
|
const n = deprecatedFanout[1];
|
|
16932
16994
|
setError(
|
|
16933
16995
|
lineNumber,
|
|
16934
|
-
`'x${n}' fanout syntax is no longer supported \u2014 use '
|
|
16996
|
+
`'x${n}' fanout syntax is no longer supported \u2014 use 'fanout: ${n}' instead`
|
|
16935
16997
|
);
|
|
16936
16998
|
continue;
|
|
16937
16999
|
}
|
|
@@ -17105,8 +17167,10 @@ function parseInfra(content) {
|
|
|
17105
17167
|
const hint = suggest(key, allKeys);
|
|
17106
17168
|
const valueLooksNumeric = /^[\d.]+%?$/.test(rawVal);
|
|
17107
17169
|
if (hint || valueLooksNumeric) {
|
|
17108
|
-
let msg = `Unknown property '${key}'.`;
|
|
17170
|
+
let msg = `Unknown infra property '${key}'.`;
|
|
17109
17171
|
if (hint) msg += ` ${hint}`;
|
|
17172
|
+
else
|
|
17173
|
+
msg += ` Properties are colon-keyed 'key: value' from the known schema (e.g. latency-ms, max-rps, cache-hit, instances, concurrency).`;
|
|
17110
17174
|
warn(lineNumber, msg);
|
|
17111
17175
|
} else if (!currentNode.isEdge) {
|
|
17112
17176
|
pushDescription(currentNode, trimmed);
|
|
@@ -17117,7 +17181,7 @@ function parseInfra(content) {
|
|
|
17117
17181
|
if (EDGE_ONLY_KEYS.has(key) && !currentNode.isEdge) {
|
|
17118
17182
|
warn(
|
|
17119
17183
|
lineNumber,
|
|
17120
|
-
`Property '${key}'
|
|
17184
|
+
`Property '${key}' belongs on the entry point \u2014 declare it indented under an 'internet' or 'edge' node, not on '${currentNode.label}'.`
|
|
17121
17185
|
);
|
|
17122
17186
|
}
|
|
17123
17187
|
const value = parsePropertyValue(rawVal);
|
|
@@ -17224,7 +17288,7 @@ function parseInfra(content) {
|
|
|
17224
17288
|
}
|
|
17225
17289
|
warn(
|
|
17226
17290
|
lineNumber,
|
|
17227
|
-
currentGroup ? `Unexpected line: '${trimmed}'.
|
|
17291
|
+
currentGroup ? `Unexpected line: '${trimmed}'. Inside a group, indent a component name under the '[Group]'.` : `Unexpected line: '${trimmed}'. Expected a node ('Api Gateway'), a group ('[Backend]'), a tag group ('tag Tier as t'), or an option ('default-rps 100'); node properties go indented under a node as 'key: value'.`
|
|
17228
17292
|
);
|
|
17229
17293
|
}
|
|
17230
17294
|
finishCurrentNode();
|
|
@@ -17600,7 +17664,10 @@ function parseGantt(content, palette) {
|
|
|
17600
17664
|
continue;
|
|
17601
17665
|
}
|
|
17602
17666
|
if (COMMENT_RE.test(line11)) continue;
|
|
17603
|
-
warn(
|
|
17667
|
+
warn(
|
|
17668
|
+
lineNumber,
|
|
17669
|
+
`Unrecognized holiday entry: "${line11}". Use a date '2024-02-19 Presidents Day' or a range '2024-05-27 -> 2024-05-29 Memorial Weekend'. (\xA713.3)`
|
|
17670
|
+
);
|
|
17604
17671
|
continue;
|
|
17605
17672
|
}
|
|
17606
17673
|
}
|
|
@@ -17626,7 +17693,10 @@ function parseGantt(content, palette) {
|
|
|
17626
17693
|
lineNumber
|
|
17627
17694
|
});
|
|
17628
17695
|
} else {
|
|
17629
|
-
warn(
|
|
17696
|
+
warn(
|
|
17697
|
+
lineNumber,
|
|
17698
|
+
`Unrecognized era entry: "${line11}". Use 'YYYY-MM-DD -> YYYY-MM-DD Label [color]' (e.g. '2026-04-06 -> 2026-04-10 Conference purple'). (\xA713.5)`
|
|
17699
|
+
);
|
|
17630
17700
|
}
|
|
17631
17701
|
continue;
|
|
17632
17702
|
}
|
|
@@ -17652,7 +17722,10 @@ function parseGantt(content, palette) {
|
|
|
17652
17722
|
lineNumber
|
|
17653
17723
|
});
|
|
17654
17724
|
} else {
|
|
17655
|
-
warn(
|
|
17725
|
+
warn(
|
|
17726
|
+
lineNumber,
|
|
17727
|
+
`Unrecognized marker entry: "${line11}". Use 'YYYY-MM-DD Label [color]' (e.g. '2026-03-27 Board Review' or '2026-06-15 Release green'). (\xA713.6)`
|
|
17728
|
+
);
|
|
17656
17729
|
}
|
|
17657
17730
|
continue;
|
|
17658
17731
|
}
|
|
@@ -17818,7 +17891,7 @@ function parseGantt(content, palette) {
|
|
|
17818
17891
|
} else {
|
|
17819
17892
|
softError(
|
|
17820
17893
|
lineNumber,
|
|
17821
|
-
`Arrow
|
|
17894
|
+
`Arrow '-> ${content2.name}' has no source task \u2014 indent it under the task it follows (e.g. 'Design 5bd' then indented '-> ${content2.name} 3bd'). (\xA713)`
|
|
17822
17895
|
);
|
|
17823
17896
|
}
|
|
17824
17897
|
}
|
|
@@ -19038,7 +19111,10 @@ function parseMap(content, palette) {
|
|
|
19038
19111
|
function handleTag(trimmed, line11) {
|
|
19039
19112
|
const m = matchTagBlockHeading(trimmed);
|
|
19040
19113
|
if (!m) {
|
|
19041
|
-
pushError(
|
|
19114
|
+
pushError(
|
|
19115
|
+
line11,
|
|
19116
|
+
`Malformed tag declaration: "${trimmed}" \u2014 write 'tag <Group>' (optionally 'tag <Group> as <alias>'), e.g. 'tag Market as m', with indented 'Value color' entries below.`
|
|
19117
|
+
);
|
|
19042
19118
|
return;
|
|
19043
19119
|
}
|
|
19044
19120
|
emitTagLegacyDiagnostic(m, line11, diagnostics);
|
|
@@ -19150,7 +19226,7 @@ function parseMap(content, palette) {
|
|
|
19150
19226
|
if (!pos || pos.kind === "name" && !pos.name) {
|
|
19151
19227
|
pushError(
|
|
19152
19228
|
line11,
|
|
19153
|
-
"route
|
|
19229
|
+
"route needs an origin place \u2014 `route <origin>` then indented legs (`-> dest`); origin may be a city name, IATA code, or `<lat> <lon>`. (\xA724B)"
|
|
19154
19230
|
);
|
|
19155
19231
|
return;
|
|
19156
19232
|
}
|
|
@@ -19213,7 +19289,10 @@ function parseMap(content, palette) {
|
|
|
19213
19289
|
function handleEdges(trimmed, line11) {
|
|
19214
19290
|
const parts = trimmed.split(ARROW_SPLIT);
|
|
19215
19291
|
if (parts.length < 3) {
|
|
19216
|
-
pushError(
|
|
19292
|
+
pushError(
|
|
19293
|
+
line11,
|
|
19294
|
+
`Malformed edge: "${trimmed}" \u2014 an edge is 'A -> B' (or 'A -label-> B', '~>' for arc, '--' undirected), both endpoints non-empty. (\xA724B)`
|
|
19295
|
+
);
|
|
19217
19296
|
return;
|
|
19218
19297
|
}
|
|
19219
19298
|
const endpoints = [];
|
|
@@ -19236,7 +19315,10 @@ function parseMap(content, palette) {
|
|
|
19236
19315
|
const from = endpoints[k];
|
|
19237
19316
|
const to = endpoints[k + 1];
|
|
19238
19317
|
if (!from || !to) {
|
|
19239
|
-
pushError(
|
|
19318
|
+
pushError(
|
|
19319
|
+
line11,
|
|
19320
|
+
`Edge has an empty endpoint: "${trimmed}" \u2014 both sides of the arrow need a place, e.g. 'Paris -> Berlin'. (\xA724B)`
|
|
19321
|
+
);
|
|
19240
19322
|
continue;
|
|
19241
19323
|
}
|
|
19242
19324
|
const isLast = k === links.length - 1;
|
|
@@ -21355,7 +21437,10 @@ function parseTechRadar(content) {
|
|
|
21355
21437
|
}
|
|
21356
21438
|
if (indent === 0 && trimmed.toLowerCase() === "rings") {
|
|
21357
21439
|
if (result.rings.length > 0) {
|
|
21358
|
-
warn(
|
|
21440
|
+
warn(
|
|
21441
|
+
lineNumber,
|
|
21442
|
+
'Duplicate "rings" block \u2014 only the last is kept; merge all ring names into one "rings" block.'
|
|
21443
|
+
);
|
|
21359
21444
|
result.rings = [];
|
|
21360
21445
|
}
|
|
21361
21446
|
inRingsBlock = true;
|
|
@@ -21574,7 +21659,7 @@ function parseTechRadar(content) {
|
|
|
21574
21659
|
result.diagnostics.push(
|
|
21575
21660
|
makeDgmoError(
|
|
21576
21661
|
lineNumber,
|
|
21577
|
-
`Blip "${trimmed}" has no ring
|
|
21662
|
+
`Blip "${trimmed}" has no ring. Put it under a ring section header, or add a colon-keyed ring \u2014 '${trimmed} ring: RingName' (per \xA720).`
|
|
21578
21663
|
)
|
|
21579
21664
|
);
|
|
21580
21665
|
continue;
|
|
@@ -21583,7 +21668,7 @@ function parseTechRadar(content) {
|
|
|
21583
21668
|
if (!trimmed.includes("|") && headerParsed && result.rings.length > 0) {
|
|
21584
21669
|
warn(
|
|
21585
21670
|
lineNumber,
|
|
21586
|
-
`Unrecognized line "${trimmed}".
|
|
21671
|
+
`Unrecognized line "${trimmed}". A quadrant header is 'Name quadrant: <top-left|top-right|bottom-left|bottom-right>' (per \xA720).`
|
|
21587
21672
|
);
|
|
21588
21673
|
}
|
|
21589
21674
|
}
|
|
@@ -21876,7 +21961,10 @@ function parseCycle(content) {
|
|
|
21876
21961
|
currentNode.description.push(descLine);
|
|
21877
21962
|
continue;
|
|
21878
21963
|
}
|
|
21879
|
-
warn(
|
|
21964
|
+
warn(
|
|
21965
|
+
lineNum,
|
|
21966
|
+
`Indented line "${trimmed}" has no step above it \u2014 add a step on a non-indented line first, then indent its details. (\xA721)`
|
|
21967
|
+
);
|
|
21880
21968
|
continue;
|
|
21881
21969
|
}
|
|
21882
21970
|
}
|
|
@@ -22179,7 +22267,7 @@ function parseJourneyMap(content, palette) {
|
|
|
22179
22267
|
if (trimmed.includes("|") || !PHASE_RE.test(trimmed)) {
|
|
22180
22268
|
warn(
|
|
22181
22269
|
lineNumber,
|
|
22182
|
-
"
|
|
22270
|
+
`Step "${trimmed}" sits outside any phase and is ignored \u2014 indent it under a '[Phase]' header (per \xA722).`
|
|
22183
22271
|
);
|
|
22184
22272
|
continue;
|
|
22185
22273
|
}
|
|
@@ -22236,7 +22324,10 @@ function parseJourneyMap(content, palette) {
|
|
|
22236
22324
|
continue;
|
|
22237
22325
|
}
|
|
22238
22326
|
if (indent > 0 && !currentPhase && hasPhases) {
|
|
22239
|
-
warn(
|
|
22327
|
+
warn(
|
|
22328
|
+
lineNumber,
|
|
22329
|
+
`Indented line outside any phase \u2014 add a '[Phase]' header above it, or unindent it to a top-level step. (\xA722)`
|
|
22330
|
+
);
|
|
22240
22331
|
}
|
|
22241
22332
|
}
|
|
22242
22333
|
if (currentStep) {
|
|
@@ -22582,7 +22673,10 @@ function parsePyramid(content) {
|
|
|
22582
22673
|
continue;
|
|
22583
22674
|
}
|
|
22584
22675
|
if (!currentLayer) {
|
|
22585
|
-
warn(
|
|
22676
|
+
warn(
|
|
22677
|
+
lineNum,
|
|
22678
|
+
`Indented description "${trimmed}" has no layer above it \u2014 add a layer name on a non-indented line first. (\xA723)`
|
|
22679
|
+
);
|
|
22586
22680
|
continue;
|
|
22587
22681
|
}
|
|
22588
22682
|
const descLine = trimmed.startsWith("- ") ? `\u2022 ${trimmed.substring(2)}` : trimmed;
|
|
@@ -22756,7 +22850,10 @@ function parseRing(content) {
|
|
|
22756
22850
|
continue;
|
|
22757
22851
|
}
|
|
22758
22852
|
if (!currentLayer) {
|
|
22759
|
-
warn(
|
|
22853
|
+
warn(
|
|
22854
|
+
lineNum,
|
|
22855
|
+
`Indented description "${trimmed}" has no layer above it \u2014 add a layer name on a non-indented line first. (\xA724)`
|
|
22856
|
+
);
|
|
22760
22857
|
continue;
|
|
22761
22858
|
}
|
|
22762
22859
|
const descLine = trimmed.startsWith("- ") ? `\u2022 ${trimmed.substring(2)}` : trimmed;
|
|
@@ -23482,7 +23579,10 @@ function parseRaci(content, palette) {
|
|
|
23482
23579
|
continue;
|
|
23483
23580
|
}
|
|
23484
23581
|
if (bodyStarted) {
|
|
23485
|
-
errorAt(
|
|
23582
|
+
errorAt(
|
|
23583
|
+
lineNumber,
|
|
23584
|
+
`Unexpected line: '${trimmed}'. In the body expect a '[Phase]' header, an indented task name, or an assignment 'Role: A R C I' under a task. (\xA724A)`
|
|
23585
|
+
);
|
|
23486
23586
|
} else {
|
|
23487
23587
|
warn(lineNumber, `Unrecognized directive: '${trimmed}'.`);
|
|
23488
23588
|
}
|
|
@@ -24029,6 +24129,13 @@ function getAllChartTypes() {
|
|
|
24029
24129
|
return chartTypes.map((c) => c.id);
|
|
24030
24130
|
}
|
|
24031
24131
|
function parseDgmo(content) {
|
|
24132
|
+
const result = parseDgmoUndeduped(content);
|
|
24133
|
+
return {
|
|
24134
|
+
diagnostics: dedupeDiagnostics(result.diagnostics),
|
|
24135
|
+
chartType: result.chartType
|
|
24136
|
+
};
|
|
24137
|
+
}
|
|
24138
|
+
function parseDgmoUndeduped(content) {
|
|
24032
24139
|
const chartType = parseDgmoChartType(content);
|
|
24033
24140
|
if (!chartType) {
|
|
24034
24141
|
const colonDiag = detectColonChartType(content);
|
|
@@ -29183,63 +29290,6 @@ function ensureArrowMarkers(defs, colors) {
|
|
|
29183
29290
|
).attr("fill", color);
|
|
29184
29291
|
}
|
|
29185
29292
|
}
|
|
29186
|
-
function edgePolylineMidpoint(points) {
|
|
29187
|
-
if (points.length === 0) return { x: 0, y: 0 };
|
|
29188
|
-
if (points.length === 1) return { x: points[0].x, y: points[0].y };
|
|
29189
|
-
let total = 0;
|
|
29190
|
-
const segLen = [];
|
|
29191
|
-
for (let k = 1; k < points.length; k++) {
|
|
29192
|
-
const len = Math.hypot(
|
|
29193
|
-
points[k].x - points[k - 1].x,
|
|
29194
|
-
points[k].y - points[k - 1].y
|
|
29195
|
-
);
|
|
29196
|
-
segLen.push(len);
|
|
29197
|
-
total += len;
|
|
29198
|
-
}
|
|
29199
|
-
let half = total / 2;
|
|
29200
|
-
for (let k = 1; k < points.length; k++) {
|
|
29201
|
-
const len = segLen[k - 1];
|
|
29202
|
-
if (half <= len || k === points.length - 1) {
|
|
29203
|
-
const t = len === 0 ? 0 : Math.min(1, half / len);
|
|
29204
|
-
return {
|
|
29205
|
-
x: points[k - 1].x + (points[k].x - points[k - 1].x) * t,
|
|
29206
|
-
y: points[k - 1].y + (points[k].y - points[k - 1].y) * t
|
|
29207
|
-
};
|
|
29208
|
-
}
|
|
29209
|
-
half -= len;
|
|
29210
|
-
}
|
|
29211
|
-
const last = points[points.length - 1];
|
|
29212
|
-
return { x: last.x, y: last.y };
|
|
29213
|
-
}
|
|
29214
|
-
function resolveEdgeLabelOverlaps(labels) {
|
|
29215
|
-
const MAX_PASSES = 8;
|
|
29216
|
-
const PAD = 4;
|
|
29217
|
-
for (let pass = 0; pass < MAX_PASSES; pass++) {
|
|
29218
|
-
let moved = false;
|
|
29219
|
-
for (let i = 0; i < labels.length; i++) {
|
|
29220
|
-
for (let j = i + 1; j < labels.length; j++) {
|
|
29221
|
-
const a = labels[i];
|
|
29222
|
-
const b = labels[j];
|
|
29223
|
-
const dx = Math.abs(a.x - b.x);
|
|
29224
|
-
const dy = Math.abs(a.y - b.y);
|
|
29225
|
-
const overlapX = (a.width + b.width) / 2 + PAD - dx;
|
|
29226
|
-
const overlapY = (a.height + b.height) / 2 + PAD - dy;
|
|
29227
|
-
if (overlapX > 0 && overlapY > 0) {
|
|
29228
|
-
const shift = overlapY / 2 + 1;
|
|
29229
|
-
if (a.y < b.y) {
|
|
29230
|
-
a.y -= shift;
|
|
29231
|
-
b.y += shift;
|
|
29232
|
-
} else {
|
|
29233
|
-
a.y += shift;
|
|
29234
|
-
b.y -= shift;
|
|
29235
|
-
}
|
|
29236
|
-
moved = true;
|
|
29237
|
-
}
|
|
29238
|
-
}
|
|
29239
|
-
}
|
|
29240
|
-
if (!moved) break;
|
|
29241
|
-
}
|
|
29242
|
-
}
|
|
29243
29293
|
function renderBoxesAndLines(container, parsed, layout, palette, isDark, options) {
|
|
29244
29294
|
const {
|
|
29245
29295
|
onClickItem,
|
|
@@ -29446,8 +29496,6 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
29446
29496
|
groupG.append("text").attr("class", "bl-group-label").attr("x", gx + group.width / 2).attr("y", gy + 18).attr("text-anchor", "middle").attr("font-family", FONT_FAMILY).attr("font-size", sGroupLabelFontSize).attr("font-weight", "600").attr("fill", palette.text).text(group.label);
|
|
29447
29497
|
}
|
|
29448
29498
|
}
|
|
29449
|
-
const labelPositions = [];
|
|
29450
|
-
const edgeGroups = /* @__PURE__ */ new Map();
|
|
29451
29499
|
for (let i = 0; i < layout.edges.length; i++) {
|
|
29452
29500
|
const le = layout.edges[i];
|
|
29453
29501
|
const color = edgeColorMap.get(i) ?? palette.textMuted;
|
|
@@ -29466,7 +29514,6 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
29466
29514
|
const nodeLayout = layoutNodeMap.get(le.source);
|
|
29467
29515
|
if (nodeLayout) {
|
|
29468
29516
|
const edgeG2 = diagramG.append("g").attr("class", "bl-edge-group").attr("data-line-number", String(le.lineNumber));
|
|
29469
|
-
edgeGroups.set(i, edgeG2);
|
|
29470
29517
|
const markerId2 = `bl-arrow-${color.replace("#", "")}`;
|
|
29471
29518
|
const cx = nodeLayout.x;
|
|
29472
29519
|
const cy = nodeLayout.y;
|
|
@@ -29515,7 +29562,6 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
29515
29562
|
}
|
|
29516
29563
|
if (points.length < 2) continue;
|
|
29517
29564
|
const edgeG = diagramG.append("g").attr("class", "bl-edge-group").attr("data-line-number", String(le.lineNumber));
|
|
29518
|
-
edgeGroups.set(i, edgeG);
|
|
29519
29565
|
const markerId = `bl-arrow-${color.replace("#", "")}`;
|
|
29520
29566
|
const gen = le.straight ? lineGeneratorStraight : parsed.direction === "TB" ? lineGeneratorTB : lineGeneratorLR;
|
|
29521
29567
|
const path = edgeG.append("path").attr("class", "bl-edge").attr("d", gen(points) ?? "").attr("fill", "none").attr("stroke", color).attr("stroke-width", sEdgeStrokeWidth).attr("marker-end", `url(#${markerId})`);
|
|
@@ -29523,31 +29569,6 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
29523
29569
|
const revId = `bl-arrow-rev-${color.replace("#", "")}`;
|
|
29524
29570
|
path.attr("marker-start", `url(#${revId})`);
|
|
29525
29571
|
}
|
|
29526
|
-
if (le.label && le.points.length > 0) {
|
|
29527
|
-
const lw = measureText(le.label, sEdgeLabelFontSize);
|
|
29528
|
-
const labelH = sEdgeLabelFontSize + 6;
|
|
29529
|
-
const mid = edgePolylineMidpoint(le.points);
|
|
29530
|
-
let ly = mid.y;
|
|
29531
|
-
if (le.parallelCount > 1 && le.yOffset !== 0) {
|
|
29532
|
-
ly += (le.yOffset < 0 ? -labelH : labelH) * 0.5;
|
|
29533
|
-
}
|
|
29534
|
-
labelPositions.push({
|
|
29535
|
-
x: mid.x,
|
|
29536
|
-
y: ly,
|
|
29537
|
-
width: lw + 8,
|
|
29538
|
-
height: labelH,
|
|
29539
|
-
idx: i
|
|
29540
|
-
});
|
|
29541
|
-
}
|
|
29542
|
-
}
|
|
29543
|
-
resolveEdgeLabelOverlaps(labelPositions);
|
|
29544
|
-
for (const lp of labelPositions) {
|
|
29545
|
-
const le = layout.edges[lp.idx];
|
|
29546
|
-
if (!le.label) continue;
|
|
29547
|
-
const edgeG = edgeGroups.get(lp.idx);
|
|
29548
|
-
const target = edgeG ?? diagramG;
|
|
29549
|
-
target.append("rect").attr("x", lp.x - lp.width / 2).attr("y", lp.y - lp.height / 2).attr("width", lp.width).attr("height", lp.height).attr("rx", 3).attr("fill", palette.bg).attr("opacity", 0.85);
|
|
29550
|
-
target.append("text").attr("x", lp.x).attr("y", lp.y + sEdgeLabelFontSize / 3).attr("text-anchor", "middle").attr("font-size", sEdgeLabelFontSize).attr("fill", palette.textMuted).text(le.label);
|
|
29551
29572
|
}
|
|
29552
29573
|
for (const ln of layout.nodes) {
|
|
29553
29574
|
const node = nodeMap.get(ln.label);
|
|
@@ -29598,8 +29619,8 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
29598
29619
|
nodeG.append("rect").attr("x", x).attr("y", y).attr("width", ln.width).attr("height", ln.height).attr("rx", NODE_RX).attr("ry", NODE_RX).attr("fill", colors.fill).attr("stroke", colors.stroke).attr("stroke-width", sNodeStrokeWidth);
|
|
29599
29620
|
const desc = node.description;
|
|
29600
29621
|
if (desc && desc.length > 0 && !hideDescriptions) {
|
|
29601
|
-
const
|
|
29602
|
-
const fitted = fitLabelToHeader(node.label, ln.width,
|
|
29622
|
+
const MAX_LABEL_LINES4 = 3;
|
|
29623
|
+
const fitted = fitLabelToHeader(node.label, ln.width, MAX_LABEL_LINES4);
|
|
29603
29624
|
const labelLines = fitted.lines;
|
|
29604
29625
|
const labelLineH = fitted.fontSize * 1.3;
|
|
29605
29626
|
const labelTotalH = labelLines.length * labelLineH;
|
|
@@ -29733,6 +29754,35 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
29733
29754
|
}
|
|
29734
29755
|
}
|
|
29735
29756
|
}
|
|
29757
|
+
const labelLayer = diagramG.append("g").attr("class", "bl-edge-labels");
|
|
29758
|
+
const labelLineHeight = sEdgeLabelFontSize * 1.3;
|
|
29759
|
+
for (const le of layout.edges) {
|
|
29760
|
+
if (!le.labelLines || le.labelLines.length === 0) continue;
|
|
29761
|
+
if (le.labelX === void 0 || le.labelY === void 0) continue;
|
|
29762
|
+
const lx = le.labelX;
|
|
29763
|
+
const ly = le.labelY;
|
|
29764
|
+
if (hidden.size > 0) {
|
|
29765
|
+
let isHidden = false;
|
|
29766
|
+
for (const [groupKey2, hiddenVals] of hidden) {
|
|
29767
|
+
const val = le.metadata[groupKey2];
|
|
29768
|
+
if (val && hiddenVals.has(val.toLowerCase())) {
|
|
29769
|
+
isHidden = true;
|
|
29770
|
+
break;
|
|
29771
|
+
}
|
|
29772
|
+
}
|
|
29773
|
+
if (isHidden) continue;
|
|
29774
|
+
}
|
|
29775
|
+
const lw = le.labelWidth ?? 0;
|
|
29776
|
+
const lh = le.labelHeight ?? sEdgeLabelFontSize + 6;
|
|
29777
|
+
const lines = le.labelLines;
|
|
29778
|
+
const labelG = labelLayer.append("g").attr("class", "bl-edge-label").attr("data-line-number", String(le.lineNumber));
|
|
29779
|
+
labelG.append("rect").attr("x", lx - lw / 2).attr("y", ly - lh / 2).attr("width", lw).attr("height", lh).attr("rx", 3).attr("fill", palette.bg).attr("opacity", 0.72);
|
|
29780
|
+
const text = labelG.append("text").attr("x", lx).attr("text-anchor", "middle").attr("font-family", FONT_FAMILY).attr("font-size", sEdgeLabelFontSize).attr("fill", palette.textMuted);
|
|
29781
|
+
const firstY = ly - (lines.length - 1) / 2 * labelLineHeight + sEdgeLabelFontSize / 3;
|
|
29782
|
+
lines.forEach((line11, k) => {
|
|
29783
|
+
text.append("tspan").attr("x", lx).attr("y", firstY + k * labelLineHeight).text(line11);
|
|
29784
|
+
});
|
|
29785
|
+
}
|
|
29736
29786
|
const hasDescriptions = parsed.nodes.some(
|
|
29737
29787
|
(n) => n.description && n.description.length > 0
|
|
29738
29788
|
);
|
|
@@ -29849,6 +29899,222 @@ var init_renderer6 = __esm({
|
|
|
29849
29899
|
}
|
|
29850
29900
|
});
|
|
29851
29901
|
|
|
29902
|
+
// src/boxes-and-lines/label-placement.ts
|
|
29903
|
+
function measureEdgeLabel(label, fontSize = EDGE_LABEL_FONT_SIZE6, maxWidth = LABEL_MAX_WIDTH) {
|
|
29904
|
+
let lines = wrapTextToWidth(label, fontSize, maxWidth, { hardBreak: true });
|
|
29905
|
+
if (lines.length > MAX_LABEL_LINES) {
|
|
29906
|
+
const kept = lines.slice(0, MAX_LABEL_LINES - 1);
|
|
29907
|
+
const rest = lines.slice(MAX_LABEL_LINES - 1).join(" ");
|
|
29908
|
+
kept.push(truncateText(rest, fontSize, maxWidth));
|
|
29909
|
+
lines = kept;
|
|
29910
|
+
}
|
|
29911
|
+
let textW = 0;
|
|
29912
|
+
for (const ln of lines) {
|
|
29913
|
+
const w = measureText(ln, fontSize);
|
|
29914
|
+
if (w > textW) textW = w;
|
|
29915
|
+
}
|
|
29916
|
+
return {
|
|
29917
|
+
lines,
|
|
29918
|
+
width: textW + 2 * H_PAD,
|
|
29919
|
+
height: lines.length * fontSize * LABEL_LINE_HEIGHT + 2 * V_PAD
|
|
29920
|
+
};
|
|
29921
|
+
}
|
|
29922
|
+
function edgePolylineMidpoint(points) {
|
|
29923
|
+
return pointAtArcFraction(points, 0.5).p;
|
|
29924
|
+
}
|
|
29925
|
+
function pointAtArcFraction(points, t) {
|
|
29926
|
+
if (points.length === 0) return { p: { x: 0, y: 0 }, nx: 0, ny: 1 };
|
|
29927
|
+
if (points.length === 1)
|
|
29928
|
+
return { p: { x: points[0].x, y: points[0].y }, nx: 0, ny: 1 };
|
|
29929
|
+
const segLen = [];
|
|
29930
|
+
let total = 0;
|
|
29931
|
+
for (let k = 1; k < points.length; k++) {
|
|
29932
|
+
const len = Math.hypot(
|
|
29933
|
+
points[k].x - points[k - 1].x,
|
|
29934
|
+
points[k].y - points[k - 1].y
|
|
29935
|
+
);
|
|
29936
|
+
segLen.push(len);
|
|
29937
|
+
total += len;
|
|
29938
|
+
}
|
|
29939
|
+
let want = total * Math.max(0, Math.min(1, t));
|
|
29940
|
+
for (let k = 1; k < points.length; k++) {
|
|
29941
|
+
const len = segLen[k - 1];
|
|
29942
|
+
if (want <= len || k === points.length - 1) {
|
|
29943
|
+
const f = len === 0 ? 0 : Math.min(1, want / len);
|
|
29944
|
+
const ax = points[k - 1].x;
|
|
29945
|
+
const ay = points[k - 1].y;
|
|
29946
|
+
const bx = points[k].x;
|
|
29947
|
+
const by = points[k].y;
|
|
29948
|
+
const dx = bx - ax;
|
|
29949
|
+
const dy = by - ay;
|
|
29950
|
+
const dlen = Math.hypot(dx, dy) || 1;
|
|
29951
|
+
return {
|
|
29952
|
+
p: { x: ax + dx * f, y: ay + dy * f },
|
|
29953
|
+
nx: -dy / dlen,
|
|
29954
|
+
ny: dx / dlen
|
|
29955
|
+
};
|
|
29956
|
+
}
|
|
29957
|
+
want -= len;
|
|
29958
|
+
}
|
|
29959
|
+
const last = points[points.length - 1];
|
|
29960
|
+
return { p: { x: last.x, y: last.y }, nx: 0, ny: 1 };
|
|
29961
|
+
}
|
|
29962
|
+
function rectFromCenter(cx, cy, w, h) {
|
|
29963
|
+
return {
|
|
29964
|
+
minX: cx - w / 2,
|
|
29965
|
+
minY: cy - h / 2,
|
|
29966
|
+
maxX: cx + w / 2,
|
|
29967
|
+
maxY: cy + h / 2
|
|
29968
|
+
};
|
|
29969
|
+
}
|
|
29970
|
+
function overlapsAny(cx, cy, w, h, obstacles, pad2) {
|
|
29971
|
+
const minX = cx - w / 2 - pad2;
|
|
29972
|
+
const minY = cy - h / 2 - pad2;
|
|
29973
|
+
const maxX = cx + w / 2 + pad2;
|
|
29974
|
+
const maxY = cy + h / 2 + pad2;
|
|
29975
|
+
for (const o of obstacles) {
|
|
29976
|
+
if (minX < o.maxX && maxX > o.minX && minY < o.maxY && maxY > o.minY)
|
|
29977
|
+
return true;
|
|
29978
|
+
}
|
|
29979
|
+
return false;
|
|
29980
|
+
}
|
|
29981
|
+
function slideFractions() {
|
|
29982
|
+
const out = [0.5];
|
|
29983
|
+
for (let k = 1; k <= SLIDE_SAMPLES; k++) {
|
|
29984
|
+
const off = k * 0.08;
|
|
29985
|
+
if (0.5 - off >= 0.12) out.push(0.5 - off);
|
|
29986
|
+
if (0.5 + off <= 0.88) out.push(0.5 + off);
|
|
29987
|
+
}
|
|
29988
|
+
return out;
|
|
29989
|
+
}
|
|
29990
|
+
function findClearPosition(w, h, points, obstacles) {
|
|
29991
|
+
const ts = slideFractions();
|
|
29992
|
+
for (const t of ts) {
|
|
29993
|
+
const { p } = pointAtArcFraction(points, t);
|
|
29994
|
+
if (!overlapsAny(p.x, p.y, w, h, obstacles, BOX_CLEAR_PAD)) return p;
|
|
29995
|
+
}
|
|
29996
|
+
for (let mag = PERP_STEP; mag <= PERP_MAX; mag += PERP_STEP) {
|
|
29997
|
+
for (const t of ts) {
|
|
29998
|
+
const { p, nx, ny } = pointAtArcFraction(points, t);
|
|
29999
|
+
for (const sign of [-1, 1]) {
|
|
30000
|
+
const x = p.x + nx * mag * sign;
|
|
30001
|
+
const y = p.y + ny * mag * sign;
|
|
30002
|
+
if (!overlapsAny(x, y, w, h, obstacles, BOX_CLEAR_PAD)) return { x, y };
|
|
30003
|
+
}
|
|
30004
|
+
}
|
|
30005
|
+
}
|
|
30006
|
+
return null;
|
|
30007
|
+
}
|
|
30008
|
+
function resolveLabelOverlaps(boxes) {
|
|
30009
|
+
const MAX_PASSES = 8;
|
|
30010
|
+
const PAD = 4;
|
|
30011
|
+
for (let pass = 0; pass < MAX_PASSES; pass++) {
|
|
30012
|
+
let moved = false;
|
|
30013
|
+
for (let i = 0; i < boxes.length; i++) {
|
|
30014
|
+
for (let j = i + 1; j < boxes.length; j++) {
|
|
30015
|
+
const a = boxes[i];
|
|
30016
|
+
const b = boxes[j];
|
|
30017
|
+
const dx = Math.abs(a.cx - b.cx);
|
|
30018
|
+
const dy = Math.abs(a.cy - b.cy);
|
|
30019
|
+
const overlapX = (a.w + b.w) / 2 + PAD - dx;
|
|
30020
|
+
const overlapY = (a.h + b.h) / 2 + PAD - dy;
|
|
30021
|
+
if (overlapX > 0 && overlapY > 0) {
|
|
30022
|
+
const shift = overlapY / 2 + 1;
|
|
30023
|
+
if (a.cy < b.cy) {
|
|
30024
|
+
a.cy -= shift;
|
|
30025
|
+
b.cy += shift;
|
|
30026
|
+
} else {
|
|
30027
|
+
a.cy += shift;
|
|
30028
|
+
b.cy -= shift;
|
|
30029
|
+
}
|
|
30030
|
+
moved = true;
|
|
30031
|
+
}
|
|
30032
|
+
}
|
|
30033
|
+
}
|
|
30034
|
+
if (!moved) break;
|
|
30035
|
+
}
|
|
30036
|
+
}
|
|
30037
|
+
function placeEdgeLabels(layout, opts) {
|
|
30038
|
+
const fontSize = opts?.fontSize ?? EDGE_LABEL_FONT_SIZE6;
|
|
30039
|
+
const maxWidth = opts?.maxWidth ?? LABEL_MAX_WIDTH;
|
|
30040
|
+
const obstacles = [];
|
|
30041
|
+
for (const n of layout.nodes)
|
|
30042
|
+
obstacles.push(rectFromCenter(n.x, n.y, n.width, n.height));
|
|
30043
|
+
for (const g of layout.groups)
|
|
30044
|
+
if (g.collapsed)
|
|
30045
|
+
obstacles.push(rectFromCenter(g.x, g.y, g.width, g.height));
|
|
30046
|
+
const boxes = [];
|
|
30047
|
+
layout.edges.forEach((e, idx) => {
|
|
30048
|
+
if (!e.label || e.points.length < 2) return;
|
|
30049
|
+
const m = measureEdgeLabel(e.label, fontSize, maxWidth);
|
|
30050
|
+
const mid = edgePolylineMidpoint(e.points);
|
|
30051
|
+
let cy = mid.y;
|
|
30052
|
+
if (e.parallelCount > 1 && e.yOffset !== 0)
|
|
30053
|
+
cy += (e.yOffset < 0 ? -1 : 1) * (m.height / 2);
|
|
30054
|
+
boxes.push({
|
|
30055
|
+
edgeIdx: idx,
|
|
30056
|
+
cx: mid.x,
|
|
30057
|
+
cy,
|
|
30058
|
+
w: m.width,
|
|
30059
|
+
h: m.height,
|
|
30060
|
+
lines: m.lines,
|
|
30061
|
+
resolved: true
|
|
30062
|
+
});
|
|
30063
|
+
});
|
|
30064
|
+
for (const box of boxes) {
|
|
30065
|
+
if (!overlapsAny(box.cx, box.cy, box.w, box.h, obstacles, BOX_CLEAR_PAD))
|
|
30066
|
+
continue;
|
|
30067
|
+
const e = layout.edges[box.edgeIdx];
|
|
30068
|
+
const clear = findClearPosition(box.w, box.h, e.points, obstacles);
|
|
30069
|
+
if (clear) {
|
|
30070
|
+
box.cx = clear.x;
|
|
30071
|
+
box.cy = clear.y;
|
|
30072
|
+
} else {
|
|
30073
|
+
box.resolved = false;
|
|
30074
|
+
}
|
|
30075
|
+
}
|
|
30076
|
+
resolveLabelOverlaps(boxes);
|
|
30077
|
+
for (const box of boxes) {
|
|
30078
|
+
if (overlapsAny(box.cx, box.cy, box.w, box.h, obstacles, BOX_CLEAR_PAD))
|
|
30079
|
+
box.resolved = false;
|
|
30080
|
+
}
|
|
30081
|
+
const boxByIdx = /* @__PURE__ */ new Map();
|
|
30082
|
+
for (const b of boxes) boxByIdx.set(b.edgeIdx, b);
|
|
30083
|
+
const edges = layout.edges.map((e, idx) => {
|
|
30084
|
+
const b = boxByIdx.get(idx);
|
|
30085
|
+
if (!b) return e;
|
|
30086
|
+
return {
|
|
30087
|
+
...e,
|
|
30088
|
+
labelX: b.cx,
|
|
30089
|
+
labelY: b.cy,
|
|
30090
|
+
labelWidth: b.w,
|
|
30091
|
+
labelHeight: b.h,
|
|
30092
|
+
labelLines: b.lines
|
|
30093
|
+
};
|
|
30094
|
+
});
|
|
30095
|
+
return {
|
|
30096
|
+
layout: { ...layout, edges },
|
|
30097
|
+
unresolved: boxes.filter((b) => !b.resolved).map((b) => b.edgeIdx)
|
|
30098
|
+
};
|
|
30099
|
+
}
|
|
30100
|
+
var EDGE_LABEL_FONT_SIZE6, LABEL_MAX_WIDTH, MAX_LABEL_LINES, LABEL_LINE_HEIGHT, H_PAD, V_PAD, BOX_CLEAR_PAD, PERP_STEP, PERP_MAX, SLIDE_SAMPLES;
|
|
30101
|
+
var init_label_placement = __esm({
|
|
30102
|
+
"src/boxes-and-lines/label-placement.ts"() {
|
|
30103
|
+
"use strict";
|
|
30104
|
+
init_text_measure();
|
|
30105
|
+
EDGE_LABEL_FONT_SIZE6 = 11;
|
|
30106
|
+
LABEL_MAX_WIDTH = 160;
|
|
30107
|
+
MAX_LABEL_LINES = 3;
|
|
30108
|
+
LABEL_LINE_HEIGHT = 1.3;
|
|
30109
|
+
H_PAD = 6;
|
|
30110
|
+
V_PAD = 3;
|
|
30111
|
+
BOX_CLEAR_PAD = 4;
|
|
30112
|
+
PERP_STEP = 8;
|
|
30113
|
+
PERP_MAX = 40;
|
|
30114
|
+
SLIDE_SAMPLES = 9;
|
|
30115
|
+
}
|
|
30116
|
+
});
|
|
30117
|
+
|
|
29852
30118
|
// src/boxes-and-lines/layout-layered.ts
|
|
29853
30119
|
function rng(s) {
|
|
29854
30120
|
return () => {
|
|
@@ -31636,6 +31902,7 @@ function edgeLength(layout) {
|
|
|
31636
31902
|
}
|
|
31637
31903
|
async function layoutBoxesAndLinesSearch(parsed, collapseInfo, opts) {
|
|
31638
31904
|
const hideDescriptions = opts?.hideDescriptions ?? false;
|
|
31905
|
+
const reserveEdgeLabels = opts?.reserveEdgeLabels ?? false;
|
|
31639
31906
|
const onProgress = opts?.onProgress;
|
|
31640
31907
|
const tick = onProgress ? () => new Promise((r) => setTimeout(r)) : () => void 0;
|
|
31641
31908
|
const collapsedGroupLabels = /* @__PURE__ */ new Set();
|
|
@@ -31928,8 +32195,14 @@ async function layoutBoxesAndLinesSearch(parsed, collapseInfo, opts) {
|
|
|
31928
32195
|
for (const e of ord(parsed.edges)) {
|
|
31929
32196
|
const s = srcRep(e.source);
|
|
31930
32197
|
const t = tgtRep(e.target);
|
|
31931
|
-
if (s !== t && g.hasNode(s) && g.hasNode(t))
|
|
31932
|
-
|
|
32198
|
+
if (s !== t && g.hasNode(s) && g.hasNode(t)) {
|
|
32199
|
+
let edgeLabel = {};
|
|
32200
|
+
if (reserveEdgeLabels && e.label) {
|
|
32201
|
+
const m = measureEdgeLabel(e.label, EDGE_LABEL_FONT_SIZE6);
|
|
32202
|
+
edgeLabel = { width: m.width, height: m.height, labelpos: "c" };
|
|
32203
|
+
}
|
|
32204
|
+
g.setEdge(s, t, edgeLabel, edgeKey(e));
|
|
32205
|
+
}
|
|
31933
32206
|
}
|
|
31934
32207
|
import_dagre4.default.layout(g);
|
|
31935
32208
|
const nodes = parsed.nodes.map((n2) => {
|
|
@@ -32160,6 +32433,7 @@ var init_layout_search = __esm({
|
|
|
32160
32433
|
init_layout5();
|
|
32161
32434
|
init_layout_layered();
|
|
32162
32435
|
init_layout_grouped();
|
|
32436
|
+
init_label_placement();
|
|
32163
32437
|
DEFAULT_LAMBDA = 4;
|
|
32164
32438
|
ESCALATE_THRESHOLD = 4;
|
|
32165
32439
|
ESCALATE_MAX_N = 45;
|
|
@@ -32218,9 +32492,9 @@ function estimateLabelLines(label, nodeWidth = NODE_WIDTH) {
|
|
|
32218
32492
|
current = word;
|
|
32219
32493
|
}
|
|
32220
32494
|
}
|
|
32221
|
-
if (lines <=
|
|
32495
|
+
if (lines <= MAX_LABEL_LINES2) return Math.min(lines, MAX_LABEL_LINES2);
|
|
32222
32496
|
}
|
|
32223
|
-
return
|
|
32497
|
+
return MAX_LABEL_LINES2;
|
|
32224
32498
|
}
|
|
32225
32499
|
function computeNodeSize(node, reserveValueRow) {
|
|
32226
32500
|
if (!node.description || node.description.length === 0) {
|
|
@@ -32228,7 +32502,7 @@ function computeNodeSize(node, reserveValueRow) {
|
|
|
32228
32502
|
}
|
|
32229
32503
|
const w = DESC_NODE_WIDTH;
|
|
32230
32504
|
const labelLines = estimateLabelLines(node.label, w);
|
|
32231
|
-
const labelHeight = labelLines * 13 *
|
|
32505
|
+
const labelHeight = labelLines * 13 * LABEL_LINE_HEIGHT2 + LABEL_PAD;
|
|
32232
32506
|
const maxTextWidth = w - 24;
|
|
32233
32507
|
let totalRenderedLines = 0;
|
|
32234
32508
|
for (const line11 of node.description) {
|
|
@@ -32252,7 +32526,7 @@ function computeNodeSize(node, reserveValueRow) {
|
|
|
32252
32526
|
}
|
|
32253
32527
|
async function layoutBoxesAndLines(parsed, collapseInfo, layoutOptions) {
|
|
32254
32528
|
const { layoutBoxesAndLinesSearch: layoutBoxesAndLinesSearch2 } = await Promise.resolve().then(() => (init_layout_search(), layout_search_exports));
|
|
32255
|
-
const
|
|
32529
|
+
const searchOpts = {
|
|
32256
32530
|
...layoutOptions?.hideDescriptions !== void 0 && {
|
|
32257
32531
|
hideDescriptions: layoutOptions.hideDescriptions
|
|
32258
32532
|
},
|
|
@@ -32262,12 +32536,23 @@ async function layoutBoxesAndLines(parsed, collapseInfo, layoutOptions) {
|
|
|
32262
32536
|
...layoutOptions?.onProgress !== void 0 && {
|
|
32263
32537
|
onProgress: layoutOptions.onProgress
|
|
32264
32538
|
}
|
|
32265
|
-
}
|
|
32266
|
-
|
|
32267
|
-
applyParallelEdgeOffsets(searched),
|
|
32539
|
+
};
|
|
32540
|
+
const searched = await layoutBoxesAndLinesSearch2(
|
|
32268
32541
|
parsed,
|
|
32269
|
-
|
|
32542
|
+
collapseInfo,
|
|
32543
|
+
searchOpts
|
|
32270
32544
|
);
|
|
32545
|
+
let placed = placeEdgeLabels(applyParallelEdgeOffsets(searched));
|
|
32546
|
+
if (placed.unresolved.length > 0) {
|
|
32547
|
+
const relaid = await layoutBoxesAndLinesSearch2(parsed, collapseInfo, {
|
|
32548
|
+
...searchOpts,
|
|
32549
|
+
reserveEdgeLabels: true
|
|
32550
|
+
});
|
|
32551
|
+
const relaidPlaced = placeEdgeLabels(applyParallelEdgeOffsets(relaid));
|
|
32552
|
+
if (relaidPlaced.unresolved.length < placed.unresolved.length)
|
|
32553
|
+
placed = relaidPlaced;
|
|
32554
|
+
}
|
|
32555
|
+
return attachNotes(placed.layout, parsed, layoutOptions?.collapsedNotes);
|
|
32271
32556
|
}
|
|
32272
32557
|
function attachNotes(layout, parsed, collapsedNotes) {
|
|
32273
32558
|
const notesSuppressed = parsed.options?.["no-notes"] === "on";
|
|
@@ -32335,6 +32620,7 @@ function attachNotes(layout, parsed, collapsedNotes) {
|
|
|
32335
32620
|
points: e.points.map((pt) => ({ x: pt.x + shiftX, y: pt.y + shiftY })),
|
|
32336
32621
|
...e.labelX !== void 0 && { labelX: e.labelX + shiftX },
|
|
32337
32622
|
...e.labelY !== void 0 && { labelY: e.labelY + shiftY }
|
|
32623
|
+
// labelWidth/labelHeight/labelLines are shift-invariant — carried via spread.
|
|
32338
32624
|
})) : layout.edges;
|
|
32339
32625
|
const finalGroups = shifted ? layout.groups.map((grp) => ({
|
|
32340
32626
|
...grp,
|
|
@@ -32379,11 +32665,12 @@ function applyParallelEdgeOffsets(layout) {
|
|
|
32379
32665
|
}))
|
|
32380
32666
|
};
|
|
32381
32667
|
}
|
|
32382
|
-
var MARGIN5, MAX_PARALLEL_EDGES, PARALLEL_SPACING, PHI, NODE_HEIGHT, NODE_WIDTH, DESC_NODE_WIDTH, DESC_FONT_SIZE2, DESC_LINE_HEIGHT2, DESC_PADDING, SEPARATOR_GAP4, MAX_DESC_LINES2,
|
|
32668
|
+
var MARGIN5, MAX_PARALLEL_EDGES, PARALLEL_SPACING, PHI, NODE_HEIGHT, NODE_WIDTH, DESC_NODE_WIDTH, DESC_FONT_SIZE2, DESC_LINE_HEIGHT2, DESC_PADDING, SEPARATOR_GAP4, MAX_DESC_LINES2, MAX_LABEL_LINES2, LABEL_LINE_HEIGHT2, LABEL_PAD, VALUE_ROW_FONT, VALUE_ROW_H;
|
|
32383
32669
|
var init_layout5 = __esm({
|
|
32384
32670
|
"src/boxes-and-lines/layout.ts"() {
|
|
32385
32671
|
"use strict";
|
|
32386
32672
|
init_text_measure();
|
|
32673
|
+
init_label_placement();
|
|
32387
32674
|
init_notes();
|
|
32388
32675
|
MARGIN5 = 40;
|
|
32389
32676
|
MAX_PARALLEL_EDGES = 5;
|
|
@@ -32397,8 +32684,8 @@ var init_layout5 = __esm({
|
|
|
32397
32684
|
DESC_PADDING = 8;
|
|
32398
32685
|
SEPARATOR_GAP4 = 4;
|
|
32399
32686
|
MAX_DESC_LINES2 = 6;
|
|
32400
|
-
|
|
32401
|
-
|
|
32687
|
+
MAX_LABEL_LINES2 = 3;
|
|
32688
|
+
LABEL_LINE_HEIGHT2 = 1.3;
|
|
32402
32689
|
LABEL_PAD = 12;
|
|
32403
32690
|
VALUE_ROW_FONT = 11;
|
|
32404
32691
|
VALUE_ROW_H = SEPARATOR_GAP4 + VALUE_ROW_FONT * DESC_LINE_HEIGHT2 + DESC_PADDING;
|
|
@@ -32417,7 +32704,7 @@ function tokenize(text) {
|
|
|
32417
32704
|
return tokens;
|
|
32418
32705
|
}
|
|
32419
32706
|
function tryWrap(tokens, maxWidth, fontSize, maxLines) {
|
|
32420
|
-
const availWidth = maxWidth -
|
|
32707
|
+
const availWidth = maxWidth - H_PAD2;
|
|
32421
32708
|
const lines = [];
|
|
32422
32709
|
let currentLine = "";
|
|
32423
32710
|
for (const token of tokens) {
|
|
@@ -32442,7 +32729,7 @@ function tryWrap(tokens, maxWidth, fontSize, maxLines) {
|
|
|
32442
32729
|
return lines;
|
|
32443
32730
|
}
|
|
32444
32731
|
function truncateLastLine(lines, maxWidth, fontSize) {
|
|
32445
|
-
const availWidth = maxWidth -
|
|
32732
|
+
const availWidth = maxWidth - H_PAD2;
|
|
32446
32733
|
const result = [...lines];
|
|
32447
32734
|
const last = result[result.length - 1];
|
|
32448
32735
|
if (measureText(last, fontSize) > availWidth) {
|
|
@@ -32450,7 +32737,7 @@ function truncateLastLine(lines, maxWidth, fontSize) {
|
|
|
32450
32737
|
}
|
|
32451
32738
|
return result;
|
|
32452
32739
|
}
|
|
32453
|
-
function wrapText(text, maxWidth, baseFontSize, minFontSize, maxLines =
|
|
32740
|
+
function wrapText(text, maxWidth, baseFontSize, minFontSize, maxLines = MAX_LABEL_LINES3) {
|
|
32454
32741
|
if (!text) return { lines: [""], fontSize: baseFontSize };
|
|
32455
32742
|
const tokens = tokenize(text);
|
|
32456
32743
|
for (let fs = baseFontSize; fs >= minFontSize; fs--) {
|
|
@@ -32465,7 +32752,7 @@ function wrapText(text, maxWidth, baseFontSize, minFontSize, maxLines = MAX_LABE
|
|
|
32465
32752
|
if (allLines.length > maxLines) {
|
|
32466
32753
|
const last = truncated[truncated.length - 1];
|
|
32467
32754
|
if (!last.endsWith("\u2026")) {
|
|
32468
|
-
const availWidth = maxWidth -
|
|
32755
|
+
const availWidth = maxWidth - H_PAD2;
|
|
32469
32756
|
if (measureText(last + "\u2026", minFontSize) > availWidth) {
|
|
32470
32757
|
truncated[truncated.length - 1] = truncateText(
|
|
32471
32758
|
last,
|
|
@@ -32492,7 +32779,7 @@ function computeNodeText(label, description, depth, nodeWidth, hideDescriptions)
|
|
|
32492
32779
|
nodeWidth,
|
|
32493
32780
|
baseFontSize,
|
|
32494
32781
|
MIN_FONT_SIZE,
|
|
32495
|
-
|
|
32782
|
+
MAX_LABEL_LINES3
|
|
32496
32783
|
);
|
|
32497
32784
|
const descLines = [];
|
|
32498
32785
|
let descFontSize = DESC_FONT_SIZE3;
|
|
@@ -32520,14 +32807,14 @@ function computeNodeText(label, description, depth, nodeWidth, hideDescriptions)
|
|
|
32520
32807
|
descFontSize
|
|
32521
32808
|
};
|
|
32522
32809
|
}
|
|
32523
|
-
var
|
|
32810
|
+
var H_PAD2, MAX_LABEL_LINES3, MAX_DESC_LINES3, ROOT_FONT_SIZE, MIN_FONT_SIZE, FONT_STEP, DESC_FONT_SIZE3;
|
|
32524
32811
|
var init_text_wrap = __esm({
|
|
32525
32812
|
"src/mindmap/text-wrap.ts"() {
|
|
32526
32813
|
"use strict";
|
|
32527
32814
|
init_description_helpers();
|
|
32528
32815
|
init_text_measure();
|
|
32529
|
-
|
|
32530
|
-
|
|
32816
|
+
H_PAD2 = 16;
|
|
32817
|
+
MAX_LABEL_LINES3 = 3;
|
|
32531
32818
|
MAX_DESC_LINES3 = 2;
|
|
32532
32819
|
ROOT_FONT_SIZE = 17;
|
|
32533
32820
|
MIN_FONT_SIZE = 9;
|
|
@@ -32914,7 +33201,7 @@ function nodeHeightS(node, hideDescriptions, sc) {
|
|
|
32914
33201
|
hideDescriptions
|
|
32915
33202
|
);
|
|
32916
33203
|
const labelLineCount = text.labelLines.length;
|
|
32917
|
-
const labelH = labelLineCount <= 1 ? SINGLE_LABEL_HEIGHT :
|
|
33204
|
+
const labelH = labelLineCount <= 1 ? SINGLE_LABEL_HEIGHT : LABEL_LINE_HEIGHT3 * labelLineCount;
|
|
32918
33205
|
let h = labelH + NODE_V_PAD;
|
|
32919
33206
|
if (text.descLines.length > 0) {
|
|
32920
33207
|
h += DESC_LINE_HEIGHT3 * text.descLines.length + 4;
|
|
@@ -32934,7 +33221,7 @@ function populateDepthCache(roots) {
|
|
|
32934
33221
|
};
|
|
32935
33222
|
walk(roots, 0);
|
|
32936
33223
|
}
|
|
32937
|
-
var ROOT_WIDTH, DEPTH1_WIDTH, LEAF_WIDTH, SINGLE_LABEL_HEIGHT,
|
|
33224
|
+
var ROOT_WIDTH, DEPTH1_WIDTH, LEAF_WIDTH, SINGLE_LABEL_HEIGHT, LABEL_LINE_HEIGHT3, DESC_LINE_HEIGHT3, NODE_V_PAD, H_GAP2, V_GAP2, MARGIN6, MULTI_ROOT_GAP, nodeDepthCache;
|
|
32938
33225
|
var init_layout6 = __esm({
|
|
32939
33226
|
"src/mindmap/layout.ts"() {
|
|
32940
33227
|
"use strict";
|
|
@@ -32945,7 +33232,7 @@ var init_layout6 = __esm({
|
|
|
32945
33232
|
DEPTH1_WIDTH = 150;
|
|
32946
33233
|
LEAF_WIDTH = 120;
|
|
32947
33234
|
SINGLE_LABEL_HEIGHT = 28;
|
|
32948
|
-
|
|
33235
|
+
LABEL_LINE_HEIGHT3 = 18;
|
|
32949
33236
|
DESC_LINE_HEIGHT3 = 14;
|
|
32950
33237
|
NODE_V_PAD = 10;
|
|
32951
33238
|
H_GAP2 = 40;
|
|
@@ -33236,18 +33523,18 @@ function renderMindmap(container, parsed, layout, palette, isDark, onClickItem,
|
|
|
33236
33523
|
descFontSize
|
|
33237
33524
|
} = textLayout;
|
|
33238
33525
|
const labelLineCount = labelLines.length;
|
|
33239
|
-
const labelZoneH = labelLineCount <= 1 ? SINGLE_LABEL_HEIGHT2 :
|
|
33526
|
+
const labelZoneH = labelLineCount <= 1 ? SINGLE_LABEL_HEIGHT2 : LABEL_LINE_HEIGHT4 * labelLineCount;
|
|
33240
33527
|
const labelZoneHeight = showDesc ? labelZoneH : node.height;
|
|
33241
33528
|
const centerX = node.x + node.width / 2;
|
|
33242
33529
|
if (labelLineCount <= 1) {
|
|
33243
33530
|
const labelY = node.y + labelZoneHeight / 2 + fontSize * 0.35;
|
|
33244
33531
|
nodeG.append("text").attr("x", centerX).attr("y", labelY).attr("text-anchor", "middle").attr("font-size", fontSize).attr("font-weight", isRoot ? "bold" : "normal").attr("fill", onFillText).text(labelLines[0]);
|
|
33245
33532
|
} else {
|
|
33246
|
-
const blockH =
|
|
33533
|
+
const blockH = LABEL_LINE_HEIGHT4 * (labelLineCount - 1);
|
|
33247
33534
|
const firstBaselineY = node.y + labelZoneHeight / 2 - blockH / 2 + fontSize * 0.35;
|
|
33248
33535
|
const textEl = nodeG.append("text").attr("x", centerX).attr("text-anchor", "middle").attr("font-size", fontSize).attr("font-weight", isRoot ? "bold" : "normal").attr("fill", onFillText);
|
|
33249
33536
|
for (let i = 0; i < labelLines.length; i++) {
|
|
33250
|
-
textEl.append("tspan").attr("x", centerX).attr("y", firstBaselineY + i *
|
|
33537
|
+
textEl.append("tspan").attr("x", centerX).attr("y", firstBaselineY + i * LABEL_LINE_HEIGHT4).text(labelLines[i]);
|
|
33251
33538
|
}
|
|
33252
33539
|
}
|
|
33253
33540
|
if (labelLines.length > 1 || labelLines[0] !== node.label) {
|
|
@@ -33322,7 +33609,7 @@ function renderMindmapForExport(content, theme, palette) {
|
|
|
33322
33609
|
return extractExportSvg(container, theme);
|
|
33323
33610
|
});
|
|
33324
33611
|
}
|
|
33325
|
-
var d3Selection12, DIAGRAM_PADDING7, TITLE_HEIGHT4, SINGLE_LABEL_HEIGHT2,
|
|
33612
|
+
var d3Selection12, DIAGRAM_PADDING7, TITLE_HEIGHT4, SINGLE_LABEL_HEIGHT2, LABEL_LINE_HEIGHT4, DESC_LINE_HEIGHT4, NODE_RADIUS, ROOT_STROKE_WIDTH, DEPTH_COLOR_KEYS;
|
|
33326
33613
|
var init_renderer7 = __esm({
|
|
33327
33614
|
"src/mindmap/renderer.ts"() {
|
|
33328
33615
|
"use strict";
|
|
@@ -33345,7 +33632,7 @@ var init_renderer7 = __esm({
|
|
|
33345
33632
|
DIAGRAM_PADDING7 = 20;
|
|
33346
33633
|
TITLE_HEIGHT4 = 30;
|
|
33347
33634
|
SINGLE_LABEL_HEIGHT2 = 28;
|
|
33348
|
-
|
|
33635
|
+
LABEL_LINE_HEIGHT4 = 18;
|
|
33349
33636
|
DESC_LINE_HEIGHT4 = 14;
|
|
33350
33637
|
NODE_RADIUS = 6;
|
|
33351
33638
|
ROOT_STROKE_WIDTH = 2.5;
|
|
@@ -36012,7 +36299,7 @@ function renderC4Context(container, parsed, layout, palette, isDark, onClickItem
|
|
|
36012
36299
|
const labelText = edge.label ?? "";
|
|
36013
36300
|
const techText = edge.technology ? `[${edge.technology}]` : "";
|
|
36014
36301
|
const textW = Math.max(
|
|
36015
|
-
measureText(labelText,
|
|
36302
|
+
measureText(labelText, EDGE_LABEL_FONT_SIZE7),
|
|
36016
36303
|
measureText(techText, TECH_FONT_SIZE)
|
|
36017
36304
|
);
|
|
36018
36305
|
const bgW = textW + 12;
|
|
@@ -36023,7 +36310,7 @@ function renderC4Context(container, parsed, layout, palette, isDark, onClickItem
|
|
|
36023
36310
|
textY = midPt.y - 4;
|
|
36024
36311
|
}
|
|
36025
36312
|
if (labelText) {
|
|
36026
|
-
edgeG.append("text").attr("x", midPt.x).attr("y", textY + 4).attr("text-anchor", "middle").attr("fill", edgeColor3).attr("font-size",
|
|
36313
|
+
edgeG.append("text").attr("x", midPt.x).attr("y", textY + 4).attr("text-anchor", "middle").attr("fill", edgeColor3).attr("font-size", EDGE_LABEL_FONT_SIZE7).attr("class", "c4-edge-label").text(labelText);
|
|
36027
36314
|
}
|
|
36028
36315
|
if (techText) {
|
|
36029
36316
|
edgeG.append("text").attr("x", midPt.x).attr("y", labelText ? textY + 18 : textY + 4).attr("text-anchor", "middle").attr("fill", edgeColor3).attr("font-size", TECH_FONT_SIZE).attr("font-style", "italic").attr("class", "c4-edge-tech").text(techText);
|
|
@@ -36207,7 +36494,7 @@ function renderEdges(contentG, edges, palette, onClickItem, obstacleRects) {
|
|
|
36207
36494
|
const labelText = edge.label ?? "";
|
|
36208
36495
|
const techText = edge.technology ? `[${edge.technology}]` : "";
|
|
36209
36496
|
const textW = Math.max(
|
|
36210
|
-
measureText(labelText,
|
|
36497
|
+
measureText(labelText, EDGE_LABEL_FONT_SIZE7),
|
|
36211
36498
|
measureText(techText, TECH_FONT_SIZE)
|
|
36212
36499
|
);
|
|
36213
36500
|
const bgW = textW + 12;
|
|
@@ -36225,7 +36512,7 @@ function renderEdges(contentG, edges, palette, onClickItem, obstacleRects) {
|
|
|
36225
36512
|
});
|
|
36226
36513
|
}
|
|
36227
36514
|
}
|
|
36228
|
-
|
|
36515
|
+
placeEdgeLabels2(pendingLabels, edges, obstacleRects);
|
|
36229
36516
|
for (const lbl of pendingLabels) {
|
|
36230
36517
|
lbl.edgeG.append("rect").attr("x", lbl.x - lbl.bgW / 2).attr("y", lbl.y - lbl.bgH / 2).attr("width", lbl.bgW).attr("height", lbl.bgH).attr("rx", 3).attr("fill", palette.bg).attr("opacity", 0.9).attr("class", "c4-edge-label-bg");
|
|
36231
36518
|
let textY = lbl.y;
|
|
@@ -36233,7 +36520,7 @@ function renderEdges(contentG, edges, palette, onClickItem, obstacleRects) {
|
|
|
36233
36520
|
textY = lbl.y - 4;
|
|
36234
36521
|
}
|
|
36235
36522
|
if (lbl.labelText) {
|
|
36236
|
-
lbl.edgeG.append("text").attr("x", lbl.x).attr("y", textY + 4).attr("text-anchor", "middle").attr("fill", lbl.edgeColor).attr("font-size",
|
|
36523
|
+
lbl.edgeG.append("text").attr("x", lbl.x).attr("y", textY + 4).attr("text-anchor", "middle").attr("fill", lbl.edgeColor).attr("font-size", EDGE_LABEL_FONT_SIZE7).attr("class", "c4-edge-label").text(lbl.labelText);
|
|
36237
36524
|
}
|
|
36238
36525
|
if (lbl.techText) {
|
|
36239
36526
|
lbl.edgeG.append("text").attr("x", lbl.x).attr("y", lbl.labelText ? textY + 18 : textY + 4).attr("text-anchor", "middle").attr("fill", lbl.edgeColor).attr("font-size", TECH_FONT_SIZE).attr("font-style", "italic").attr("class", "c4-edge-tech").text(lbl.techText);
|
|
@@ -36314,7 +36601,7 @@ function tangentAt(points, t) {
|
|
|
36314
36601
|
}
|
|
36315
36602
|
return { x: 0, y: 1 };
|
|
36316
36603
|
}
|
|
36317
|
-
function
|
|
36604
|
+
function placeEdgeLabels2(labels, edges, obstacleRects) {
|
|
36318
36605
|
if (labels.length === 0) return;
|
|
36319
36606
|
const allPaths = edges.map((e) => e.points);
|
|
36320
36607
|
const placedRects = [];
|
|
@@ -36852,7 +37139,7 @@ function renderC4DeploymentForExport(content, theme, palette) {
|
|
|
36852
37139
|
document.body.removeChild(el);
|
|
36853
37140
|
}
|
|
36854
37141
|
}
|
|
36855
|
-
var d3Selection14, d3Shape6, DIAGRAM_PADDING8, MAX_SCALE5, TITLE_HEIGHT6, TYPE_FONT_SIZE, NAME_FONT_SIZE2, DESC_FONT_SIZE5, DESC_LINE_HEIGHT6,
|
|
37142
|
+
var d3Selection14, d3Shape6, DIAGRAM_PADDING8, MAX_SCALE5, TITLE_HEIGHT6, TYPE_FONT_SIZE, NAME_FONT_SIZE2, DESC_FONT_SIZE5, DESC_LINE_HEIGHT6, EDGE_LABEL_FONT_SIZE7, TECH_FONT_SIZE, CARD_H_PAD4, CARD_V_PAD4, TYPE_LABEL_HEIGHT2, DIVIDER_GAP2, NAME_HEIGHT2, BOUNDARY_LABEL_FONT_SIZE, BOUNDARY_STROKE_WIDTH, BOUNDARY_RADIUS, DRILL_BAR_HEIGHT, CYLINDER_RY, PERSON_HEAD_R, PERSON_ARM_SPAN, PERSON_LEG_SPAN, PERSON_ICON_W, PERSON_SW, lineGenerator4;
|
|
36856
37143
|
var init_renderer9 = __esm({
|
|
36857
37144
|
"src/c4/renderer.ts"() {
|
|
36858
37145
|
"use strict";
|
|
@@ -36877,7 +37164,7 @@ var init_renderer9 = __esm({
|
|
|
36877
37164
|
NAME_FONT_SIZE2 = 14;
|
|
36878
37165
|
DESC_FONT_SIZE5 = 11;
|
|
36879
37166
|
DESC_LINE_HEIGHT6 = 16;
|
|
36880
|
-
|
|
37167
|
+
EDGE_LABEL_FONT_SIZE7 = 11;
|
|
36881
37168
|
TECH_FONT_SIZE = 10;
|
|
36882
37169
|
CARD_H_PAD4 = 20;
|
|
36883
37170
|
CARD_V_PAD4 = 14;
|
|
@@ -37501,7 +37788,7 @@ function renderFlowchart(container, graph, layout, palette, isDark, onClickItem,
|
|
|
37501
37788
|
const sTitleFontSize = ctx.text(TITLE_FONT_SIZE);
|
|
37502
37789
|
const sTitleY = ctx.structural(TITLE_Y);
|
|
37503
37790
|
const sNodeFontSize = ctx.text(NODE_FONT_SIZE2);
|
|
37504
|
-
const sEdgeLabelFontSize = ctx.text(
|
|
37791
|
+
const sEdgeLabelFontSize = ctx.text(EDGE_LABEL_FONT_SIZE8);
|
|
37505
37792
|
const sEdgeStrokeWidth = ctx.structural(EDGE_STROKE_WIDTH);
|
|
37506
37793
|
const sNodeStrokeWidth = ctx.structural(NODE_STROKE_WIDTH);
|
|
37507
37794
|
const sArrowheadW = ctx.structural(ARROWHEAD_W3);
|
|
@@ -37727,7 +38014,7 @@ function renderFlowchartForExport(content, theme, palette) {
|
|
|
37727
38014
|
document.body.removeChild(container);
|
|
37728
38015
|
}
|
|
37729
38016
|
}
|
|
37730
|
-
var d3Selection15, DIAGRAM_PADDING9, MAX_SCALE6, NODE_FONT_SIZE2,
|
|
38017
|
+
var d3Selection15, DIAGRAM_PADDING9, MAX_SCALE6, NODE_FONT_SIZE2, EDGE_LABEL_FONT_SIZE8, ARROWHEAD_W3, ARROWHEAD_H3, IO_SKEW, SUBROUTINE_INSET, DOC_WAVE_HEIGHT;
|
|
37731
38018
|
var init_flowchart_renderer = __esm({
|
|
37732
38019
|
"src/graph/flowchart-renderer.ts"() {
|
|
37733
38020
|
"use strict";
|
|
@@ -37747,7 +38034,7 @@ var init_flowchart_renderer = __esm({
|
|
|
37747
38034
|
DIAGRAM_PADDING9 = 20;
|
|
37748
38035
|
MAX_SCALE6 = 3;
|
|
37749
38036
|
NODE_FONT_SIZE2 = 13;
|
|
37750
|
-
|
|
38037
|
+
EDGE_LABEL_FONT_SIZE8 = 11;
|
|
37751
38038
|
ARROWHEAD_W3 = 10;
|
|
37752
38039
|
ARROWHEAD_H3 = 7;
|
|
37753
38040
|
IO_SKEW = 15;
|
|
@@ -39181,7 +39468,7 @@ function layoutInfra(computed, expandedNodeIds, collapsedNodes) {
|
|
|
39181
39468
|
const midIdx = Math.floor(edge.points.length / 2);
|
|
39182
39469
|
const midPt = edge.points[midIdx];
|
|
39183
39470
|
if (midPt) {
|
|
39184
|
-
const halfWidth = (measureText(edge.label,
|
|
39471
|
+
const halfWidth = (measureText(edge.label, EDGE_LABEL_FONT_SIZE9) + 8) / 2;
|
|
39185
39472
|
if (midPt.x - halfWidth < minX) minX = midPt.x - halfWidth;
|
|
39186
39473
|
if (midPt.x + halfWidth > maxX) maxX = midPt.x + halfWidth;
|
|
39187
39474
|
}
|
|
@@ -39215,7 +39502,7 @@ function layoutInfra(computed, expandedNodeIds, collapsedNodes) {
|
|
|
39215
39502
|
height: totalHeight
|
|
39216
39503
|
};
|
|
39217
39504
|
}
|
|
39218
|
-
var import_dagre7, MIN_NODE_WIDTH2, NODE_HEADER_HEIGHT, META_LINE_HEIGHT5, NODE_SEPARATOR_GAP, NODE_PAD_BOTTOM, ROLE_DOT_ROW, COLLAPSE_BAR_HEIGHT3, NODE_FONT_SIZE3, META_FONT_SIZE5,
|
|
39505
|
+
var import_dagre7, MIN_NODE_WIDTH2, NODE_HEADER_HEIGHT, META_LINE_HEIGHT5, NODE_SEPARATOR_GAP, NODE_PAD_BOTTOM, ROLE_DOT_ROW, COLLAPSE_BAR_HEIGHT3, NODE_FONT_SIZE3, META_FONT_SIZE5, EDGE_LABEL_FONT_SIZE9, PADDING_X3, GROUP_PADDING2, GROUP_HEADER_HEIGHT, EDGE_MARGIN, DISPLAY_KEYS, DISPLAY_NAMES, GROUP_GAP2;
|
|
39219
39506
|
var init_layout10 = __esm({
|
|
39220
39507
|
"src/infra/layout.ts"() {
|
|
39221
39508
|
"use strict";
|
|
@@ -39230,7 +39517,7 @@ var init_layout10 = __esm({
|
|
|
39230
39517
|
COLLAPSE_BAR_HEIGHT3 = 6;
|
|
39231
39518
|
NODE_FONT_SIZE3 = 13;
|
|
39232
39519
|
META_FONT_SIZE5 = 10;
|
|
39233
|
-
|
|
39520
|
+
EDGE_LABEL_FONT_SIZE9 = 11;
|
|
39234
39521
|
PADDING_X3 = 24;
|
|
39235
39522
|
GROUP_PADDING2 = 20;
|
|
39236
39523
|
GROUP_HEADER_HEIGHT = 24;
|
|
@@ -39335,7 +39622,7 @@ function buildScaledConstants(ctx) {
|
|
|
39335
39622
|
sNodeFontSize: ctx.text(NODE_FONT_SIZE4),
|
|
39336
39623
|
sMetaFontSize: ctx.text(META_FONT_SIZE6),
|
|
39337
39624
|
sMetaLineHeight: ctx.structural(META_LINE_HEIGHT6),
|
|
39338
|
-
sEdgeLabelFontSize: ctx.text(
|
|
39625
|
+
sEdgeLabelFontSize: ctx.text(EDGE_LABEL_FONT_SIZE10),
|
|
39339
39626
|
sGroupLabelFontSize: ctx.text(GROUP_LABEL_FONT_SIZE2),
|
|
39340
39627
|
sNodeBorderRadius: ctx.structural(NODE_BORDER_RADIUS),
|
|
39341
39628
|
sEdgeStrokeWidth: ctx.structural(EDGE_STROKE_WIDTH),
|
|
@@ -40064,7 +40351,7 @@ function renderEdgeLabels(svg, edges, nodes, groups, palette, _isDark, animate,
|
|
|
40064
40351
|
if (!midPt) continue;
|
|
40065
40352
|
const labelText = edge.label;
|
|
40066
40353
|
const g = svg.append("g").attr("class", animate ? "infra-edge-label" : "");
|
|
40067
|
-
const textWidth = measureText(labelText,
|
|
40354
|
+
const textWidth = measureText(labelText, EDGE_LABEL_FONT_SIZE10) + 8;
|
|
40068
40355
|
g.append("rect").attr("x", midPt.x - textWidth / 2).attr("y", midPt.y - 8).attr("width", textWidth).attr("height", 16).attr("rx", 3).attr("fill", palette.bg).attr("opacity", 0.9);
|
|
40069
40356
|
g.append("text").attr("x", midPt.x).attr("y", midPt.y + 4).attr("text-anchor", "middle").attr("font-family", FONT_FAMILY).attr("font-size", sc.sEdgeLabelFontSize).attr("fill", palette.textMuted).text(labelText);
|
|
40070
40357
|
if (animate) {
|
|
@@ -40674,7 +40961,7 @@ function parseAndLayoutInfra(content) {
|
|
|
40674
40961
|
const layout = layoutInfra(computed);
|
|
40675
40962
|
return { parsed, computed, layout };
|
|
40676
40963
|
}
|
|
40677
|
-
var d3Selection16, d3Shape8, NODE_FONT_SIZE4, META_FONT_SIZE6, META_LINE_HEIGHT6,
|
|
40964
|
+
var d3Selection16, d3Shape8, NODE_FONT_SIZE4, META_FONT_SIZE6, META_LINE_HEIGHT6, EDGE_LABEL_FONT_SIZE10, GROUP_LABEL_FONT_SIZE2, NODE_BORDER_RADIUS, OVERLOAD_STROKE_WIDTH, ROLE_DOT_RADIUS, NODE_HEADER_HEIGHT2, NODE_SEPARATOR_GAP2, NODE_PAD_BOTTOM2, LEGEND_FIXED_GAP3, SPEED_BADGE_H_PAD, SPEED_BADGE_V_PAD, SPEED_BADGE_GAP, COLOR_HEALTHY, COLOR_WARNING, COLOR_OVERLOADED, FLOW_SPEED_MIN, FLOW_SPEED_MAX, PARTICLE_R, PARTICLE_COUNT_MIN, PARTICLE_COUNT_MAX, NODE_PULSE_SPEED, NODE_PULSE_OVERLOAD, REJECT_DROP_DISTANCE, REJECT_DURATION_MIN, REJECT_DURATION_MAX, REJECT_COUNT_MIN, REJECT_COUNT_MAX, PROP_DISPLAY, DESC_MAX_CHARS, DESC_MAX_WIDTH, RPS_FORMAT_KEYS, MS_FORMAT_KEYS, PCT_FORMAT_KEYS;
|
|
40678
40965
|
var init_renderer10 = __esm({
|
|
40679
40966
|
"src/infra/renderer.ts"() {
|
|
40680
40967
|
"use strict";
|
|
@@ -40700,7 +40987,7 @@ var init_renderer10 = __esm({
|
|
|
40700
40987
|
NODE_FONT_SIZE4 = 13;
|
|
40701
40988
|
META_FONT_SIZE6 = 10;
|
|
40702
40989
|
META_LINE_HEIGHT6 = 14;
|
|
40703
|
-
|
|
40990
|
+
EDGE_LABEL_FONT_SIZE10 = 11;
|
|
40704
40991
|
GROUP_LABEL_FONT_SIZE2 = 14;
|
|
40705
40992
|
NODE_BORDER_RADIUS = 8;
|
|
40706
40993
|
OVERLOAD_STROKE_WIDTH = 3;
|
|
@@ -47091,7 +47378,7 @@ function renderState(container, graph, layout, palette, isDark, onClickItem, exp
|
|
|
47091
47378
|
const sTitleFontSize = ctx.text(TITLE_FONT_SIZE);
|
|
47092
47379
|
const sTitleY = ctx.structural(TITLE_Y);
|
|
47093
47380
|
const sNodeFontSize = ctx.text(NODE_FONT_SIZE6);
|
|
47094
|
-
const sEdgeLabelFontSize = ctx.text(
|
|
47381
|
+
const sEdgeLabelFontSize = ctx.text(EDGE_LABEL_FONT_SIZE11);
|
|
47095
47382
|
const sGroupLabelFontSize = ctx.text(GROUP_LABEL_FONT_SIZE3);
|
|
47096
47383
|
const sEdgeStrokeWidth = ctx.structural(EDGE_STROKE_WIDTH);
|
|
47097
47384
|
const sNodeStrokeWidth = ctx.structural(NODE_STROKE_WIDTH);
|
|
@@ -47371,7 +47658,7 @@ function renderStateForExport(content, theme, palette) {
|
|
|
47371
47658
|
document.body.removeChild(container);
|
|
47372
47659
|
}
|
|
47373
47660
|
}
|
|
47374
|
-
var d3Selection19, DIAGRAM_PADDING12, MAX_SCALE7, NODE_FONT_SIZE6,
|
|
47661
|
+
var d3Selection19, DIAGRAM_PADDING12, MAX_SCALE7, NODE_FONT_SIZE6, EDGE_LABEL_FONT_SIZE11, GROUP_LABEL_FONT_SIZE3, ARROWHEAD_W5, ARROWHEAD_H5, PSEUDOSTATE_RADIUS, STATE_CORNER_RADIUS, GROUP_EXTRA_PADDING;
|
|
47375
47662
|
var init_state_renderer = __esm({
|
|
47376
47663
|
"src/graph/state-renderer.ts"() {
|
|
47377
47664
|
"use strict";
|
|
@@ -47391,7 +47678,7 @@ var init_state_renderer = __esm({
|
|
|
47391
47678
|
DIAGRAM_PADDING12 = 20;
|
|
47392
47679
|
MAX_SCALE7 = 3;
|
|
47393
47680
|
NODE_FONT_SIZE6 = 13;
|
|
47394
|
-
|
|
47681
|
+
EDGE_LABEL_FONT_SIZE11 = 11;
|
|
47395
47682
|
GROUP_LABEL_FONT_SIZE3 = 11;
|
|
47396
47683
|
ARROWHEAD_W5 = 10;
|
|
47397
47684
|
ARROWHEAD_H5 = 7;
|
|
@@ -50433,10 +50720,10 @@ function renderedDescNodeHeight(numLines, scale) {
|
|
|
50433
50720
|
return headerH + textBlockH + bottomPad;
|
|
50434
50721
|
}
|
|
50435
50722
|
function wrapEdgeLabelText(label, description, maxWidth = EDGE_LABEL_MAX_WIDTH) {
|
|
50436
|
-
const labelLines = label ? wrapTextToWidth(label,
|
|
50723
|
+
const labelLines = label ? wrapTextToWidth(label, EDGE_LABEL_FONT_SIZE12, maxWidth) : [];
|
|
50437
50724
|
const descLines = [];
|
|
50438
50725
|
for (const d of description) {
|
|
50439
|
-
descLines.push(...wrapTextToWidth(d,
|
|
50726
|
+
descLines.push(...wrapTextToWidth(d, EDGE_LABEL_FONT_SIZE12, maxWidth));
|
|
50440
50727
|
}
|
|
50441
50728
|
return { labelLines, descLines };
|
|
50442
50729
|
}
|
|
@@ -50574,9 +50861,9 @@ function computeEdgePaths(layoutNodes, parsed, cx, cy, radius, isClockwise) {
|
|
|
50574
50861
|
const lineCount = labelLines.length + descLines.length;
|
|
50575
50862
|
let labelPxW = 0;
|
|
50576
50863
|
for (const l of labelLines)
|
|
50577
|
-
labelPxW = Math.max(labelPxW, measureText(l,
|
|
50864
|
+
labelPxW = Math.max(labelPxW, measureText(l, EDGE_LABEL_FONT_SIZE12));
|
|
50578
50865
|
for (const l of descLines)
|
|
50579
|
-
labelPxW = Math.max(labelPxW, measureText(l,
|
|
50866
|
+
labelPxW = Math.max(labelPxW, measureText(l, EDGE_LABEL_FONT_SIZE12));
|
|
50580
50867
|
const { labelX, labelY, labelAngle } = computeEdgeLabelPosition(
|
|
50581
50868
|
midAngle,
|
|
50582
50869
|
radius,
|
|
@@ -50678,9 +50965,9 @@ function fitToCanvas(nodes, edges, parsed, _cx, _cy, radius, width, height, _isC
|
|
|
50678
50965
|
);
|
|
50679
50966
|
let textWidth = 0;
|
|
50680
50967
|
for (const l of labelLines)
|
|
50681
|
-
textWidth = Math.max(textWidth, measureText(l,
|
|
50968
|
+
textWidth = Math.max(textWidth, measureText(l, EDGE_LABEL_FONT_SIZE12));
|
|
50682
50969
|
for (const l of descLines)
|
|
50683
|
-
textWidth = Math.max(textWidth, measureText(l,
|
|
50970
|
+
textWidth = Math.max(textWidth, measureText(l, EDGE_LABEL_FONT_SIZE12));
|
|
50684
50971
|
if (textWidth === 0) continue;
|
|
50685
50972
|
const normAngle = (le.labelAngle % (2 * Math.PI) + 2 * Math.PI) % (2 * Math.PI);
|
|
50686
50973
|
const isRight = normAngle < Math.PI * 0.4 || normAngle > Math.PI * 1.6;
|
|
@@ -50754,7 +51041,7 @@ function buildEdgeArc(src, tgt, cx, cy, radius, isClockwise, arrowLength = 0) {
|
|
|
50754
51041
|
const midAngle = srcExitAngle + dir * visibleSweep / 2;
|
|
50755
51042
|
return { path, midAngle };
|
|
50756
51043
|
}
|
|
50757
|
-
var MIN_ARC_ANGLE, LABEL_FONT_SIZE4, CIRCLE_LABEL_FONT_SIZE, DESC_FONT_SIZE6,
|
|
51044
|
+
var MIN_ARC_ANGLE, LABEL_FONT_SIZE4, CIRCLE_LABEL_FONT_SIZE, DESC_FONT_SIZE6, EDGE_LABEL_FONT_SIZE12, MIN_NODE_WIDTH4, MAX_NODE_WIDTH3, DESC_MIN_WIDTH, DESC_WIDTH_STEP, DESC_TARGET_RATIO, PLAIN_NODE_HEIGHT, HEADER_HEIGHT4, DESC_LINE_HEIGHT7, DESC_PAD_Y, NODE_PAD_X, MIN_CIRCLE_RADIUS, CIRCLE_PAD, RENDERER_DESC_FONT, RENDERER_DESC_FONT_MIN, RENDERER_DESC_LINE_H, RENDERER_DESC_LINE_H_MIN, EDGE_LABEL_MAX_WIDTH;
|
|
50758
51045
|
var init_layout14 = __esm({
|
|
50759
51046
|
"src/cycle/layout.ts"() {
|
|
50760
51047
|
"use strict";
|
|
@@ -50765,7 +51052,7 @@ var init_layout14 = __esm({
|
|
|
50765
51052
|
LABEL_FONT_SIZE4 = 13;
|
|
50766
51053
|
CIRCLE_LABEL_FONT_SIZE = 16;
|
|
50767
51054
|
DESC_FONT_SIZE6 = 11;
|
|
50768
|
-
|
|
51055
|
+
EDGE_LABEL_FONT_SIZE12 = 11;
|
|
50769
51056
|
MIN_NODE_WIDTH4 = 70;
|
|
50770
51057
|
MAX_NODE_WIDTH3 = 260;
|
|
50771
51058
|
DESC_MIN_WIDTH = 140;
|
|
@@ -50910,7 +51197,7 @@ function renderCycle(container, parsed, palette, isDark, onClickItem, exportDims
|
|
|
50910
51197
|
const scaledNodeFont = Math.max(6, Math.round(NODE_FONT_SIZE7 * layout.scale));
|
|
50911
51198
|
const scaledEdgeLabelFont = Math.max(
|
|
50912
51199
|
6,
|
|
50913
|
-
Math.round(
|
|
51200
|
+
Math.round(EDGE_LABEL_FONT_SIZE13 * layout.scale)
|
|
50914
51201
|
);
|
|
50915
51202
|
const CIRCLE_LABEL_FONT_SIZE2 = 16;
|
|
50916
51203
|
const scaledCircleLabelFont = Math.max(
|
|
@@ -51073,7 +51360,7 @@ function ensureArrowMarker(defs, color, strokeWidth) {
|
|
|
51073
51360
|
const mh = Math.max(1.5, mw * 0.5);
|
|
51074
51361
|
defs.append("marker").attr("id", id).attr("viewBox", `0 0 ${mw} ${mh}`).attr("refX", mw * 0.1).attr("refY", mh / 2).attr("markerWidth", mw).attr("markerHeight", mh).attr("orient", "auto").append("polygon").attr("points", `0,0 ${mw},${mh / 2} 0,${mh}`).attr("fill", color);
|
|
51075
51362
|
}
|
|
51076
|
-
var d3Selection22, NODE_FONT_SIZE7, DESC_FONT_SIZE7,
|
|
51363
|
+
var d3Selection22, NODE_FONT_SIZE7, DESC_FONT_SIZE7, EDGE_LABEL_FONT_SIZE13, DESC_LINE_HEIGHT8, TITLE_AREA_HEIGHT;
|
|
51077
51364
|
var init_renderer15 = __esm({
|
|
51078
51365
|
"src/cycle/renderer.ts"() {
|
|
51079
51366
|
"use strict";
|
|
@@ -51091,7 +51378,7 @@ var init_renderer15 = __esm({
|
|
|
51091
51378
|
init_text_measure();
|
|
51092
51379
|
NODE_FONT_SIZE7 = 13;
|
|
51093
51380
|
DESC_FONT_SIZE7 = 11;
|
|
51094
|
-
|
|
51381
|
+
EDGE_LABEL_FONT_SIZE13 = 11;
|
|
51095
51382
|
DESC_LINE_HEIGHT8 = 15;
|
|
51096
51383
|
TITLE_AREA_HEIGHT = 50;
|
|
51097
51384
|
}
|
|
@@ -51489,7 +51776,7 @@ function resolveMap(parsed, data) {
|
|
|
51489
51776
|
const hint = suggest(r.name, allNames);
|
|
51490
51777
|
err(
|
|
51491
51778
|
r.lineNumber,
|
|
51492
|
-
`Unknown
|
|
51779
|
+
`Unknown region "${r.name}" \u2014 not a known country or US state.${hint ? " " + hint : ""} Search the exact token with \`dgmo map-search "${r.name}"\` (or the lookup_map_location tool), use an ISO code (e.g. FR, US-CA), or coordinates.`,
|
|
51493
51780
|
"E_MAP_UNKNOWN_SUBDIVISION"
|
|
51494
51781
|
);
|
|
51495
51782
|
continue;
|
|
@@ -51569,7 +51856,7 @@ function resolveMap(parsed, data) {
|
|
|
51569
51856
|
const hint = suggest(name, cityNames);
|
|
51570
51857
|
err(
|
|
51571
51858
|
line11,
|
|
51572
|
-
`Unknown place "${name}"
|
|
51859
|
+
`Unknown place "${name}" \u2014 not in the gazetteer.${hint ? " " + hint : ""} Search the exact token with \`dgmo map-search "${name}"\` (or the lookup_map_location tool), or use coordinates \`poi <lat> <lon>\`.`,
|
|
51573
51860
|
"E_MAP_UNKNOWN_PLACE"
|
|
51574
51861
|
);
|
|
51575
51862
|
return { kind: "miss" };
|
|
@@ -52111,6 +52398,21 @@ function mapLegendBand(legend, opts) {
|
|
|
52111
52398
|
if (height <= 0) return 0;
|
|
52112
52399
|
return mapLegendTop(opts.hasTitle, opts.hasSubtitle) + height + LEGEND_BOTTOM_GAP2;
|
|
52113
52400
|
}
|
|
52401
|
+
function mapLegendBox(legend, opts) {
|
|
52402
|
+
if (!legend) return null;
|
|
52403
|
+
const groups = mapLegendGroups(legend);
|
|
52404
|
+
if (groups.length === 0) return null;
|
|
52405
|
+
const config = mapLegendConfig(groups, opts.mode);
|
|
52406
|
+
const state = { activeGroup: legend.activeGroup };
|
|
52407
|
+
const { width, height } = computeLegendLayout(config, state, opts.width);
|
|
52408
|
+
if (height <= 0 || width <= 0) return null;
|
|
52409
|
+
return {
|
|
52410
|
+
x: (opts.width - width) / 2,
|
|
52411
|
+
y: mapLegendTop(opts.hasTitle, opts.hasSubtitle),
|
|
52412
|
+
width,
|
|
52413
|
+
height
|
|
52414
|
+
};
|
|
52415
|
+
}
|
|
52114
52416
|
var LEGEND_TOP_GAP2, LEGEND_BOTTOM_GAP2;
|
|
52115
52417
|
var init_legend_band = __esm({
|
|
52116
52418
|
"src/map/legend-band.ts"() {
|
|
@@ -52235,6 +52537,8 @@ function placeContextLabels(args) {
|
|
|
52235
52537
|
waterBodies,
|
|
52236
52538
|
countries,
|
|
52237
52539
|
palette,
|
|
52540
|
+
countryTone,
|
|
52541
|
+
waterTone,
|
|
52238
52542
|
project,
|
|
52239
52543
|
collides,
|
|
52240
52544
|
contentPoints,
|
|
@@ -52244,8 +52548,8 @@ function placeContextLabels(args) {
|
|
|
52244
52548
|
const band = tierBand(Math.max(dLonSpan, dLatSpan));
|
|
52245
52549
|
const budget = labelBudget(width, height, band);
|
|
52246
52550
|
if (budget <= 0) return [];
|
|
52247
|
-
const waterColor = mix(palette.colors.blue, palette.textMuted, 50);
|
|
52248
|
-
const countryColor = palette.textMuted;
|
|
52551
|
+
const waterColor = waterTone ?? mix(palette.colors.blue, palette.textMuted, 50);
|
|
52552
|
+
const countryColor = countryTone ?? palette.textMuted;
|
|
52249
52553
|
const haloColor = palette.bg;
|
|
52250
52554
|
const candidates = [];
|
|
52251
52555
|
const center = [width / 2, height / 2];
|
|
@@ -52334,8 +52638,7 @@ function placeContextLabels(args) {
|
|
|
52334
52638
|
)
|
|
52335
52639
|
);
|
|
52336
52640
|
const fontSize = Math.round(FONT + t * (COUNTRY_FONT_MAX - FONT));
|
|
52337
|
-
const
|
|
52338
|
-
const color = fade > 0 ? mix(countryColor, palette.bg, 100 - fade) : countryColor;
|
|
52641
|
+
const color = countryColor;
|
|
52339
52642
|
const text = c.name;
|
|
52340
52643
|
const tw = labelWidth(text, 0, fontSize);
|
|
52341
52644
|
if (tw > w || fontSize + 2 * PADY > h) continue;
|
|
@@ -52429,7 +52732,7 @@ function placeContextLabels(args) {
|
|
|
52429
52732
|
}
|
|
52430
52733
|
return placed;
|
|
52431
52734
|
}
|
|
52432
|
-
var FONT, LINE_HEIGHT, PADX, PADY, WATER_LETTER_SPACING, CONTEXT_PAD, EDGE_CLAMP_MARGIN, EDGE_CLAMP_OVERSHOOT, COUNTRY_FONT_MAX, COUNTRY_SIZE_FRAC_MIN, COUNTRY_SIZE_FRAC_MAX,
|
|
52735
|
+
var FONT, LINE_HEIGHT, PADX, PADY, WATER_LETTER_SPACING, CONTEXT_PAD, EDGE_CLAMP_MARGIN, EDGE_CLAMP_OVERSHOOT, COUNTRY_FONT_MAX, COUNTRY_SIZE_FRAC_MIN, COUNTRY_SIZE_FRAC_MAX, MAX_COUNTRY_POSITIONS, COUNTRY_POS_GRID, COUNTRY_POS_TOPN_MARGIN, KIND_ORDER;
|
|
52433
52736
|
var init_context_labels = __esm({
|
|
52434
52737
|
"src/map/context-labels.ts"() {
|
|
52435
52738
|
"use strict";
|
|
@@ -52446,7 +52749,6 @@ var init_context_labels = __esm({
|
|
|
52446
52749
|
COUNTRY_FONT_MAX = 22;
|
|
52447
52750
|
COUNTRY_SIZE_FRAC_MIN = 0.06;
|
|
52448
52751
|
COUNTRY_SIZE_FRAC_MAX = 0.32;
|
|
52449
|
-
COUNTRY_FADE_MAX = 45;
|
|
52450
52752
|
MAX_COUNTRY_POSITIONS = 4;
|
|
52451
52753
|
COUNTRY_POS_GRID = 5;
|
|
52452
52754
|
COUNTRY_POS_TOPN_MARGIN = 3;
|
|
@@ -52573,36 +52875,23 @@ function countryLabelPositions(args) {
|
|
|
52573
52875
|
return n;
|
|
52574
52876
|
};
|
|
52575
52877
|
const dist2ToCentre = (c) => (c.sx - cx) ** 2 + (c.sy - cy) ** 2;
|
|
52576
|
-
const
|
|
52577
|
-
|
|
52578
|
-
|
|
52579
|
-
|
|
52580
|
-
|
|
52581
|
-
|
|
52582
|
-
|
|
52583
|
-
let bestIdx = 0;
|
|
52584
|
-
let bestMin = -1;
|
|
52585
|
-
for (let k = 0; k < pool.length; k++) {
|
|
52586
|
-
const c = pool[k];
|
|
52587
|
-
let minD = Infinity;
|
|
52588
|
-
for (const o of ordered) {
|
|
52589
|
-
const d = (c.sx - o.sx) ** 2 + (c.sy - o.sy) ** 2;
|
|
52590
|
-
if (d < minD) minD = d;
|
|
52591
|
-
}
|
|
52592
|
-
if (minD > bestMin) {
|
|
52593
|
-
bestMin = minD;
|
|
52594
|
-
bestIdx = k;
|
|
52595
|
-
}
|
|
52878
|
+
const centreLon = kept.reduce((s, c) => s + c.lon, 0) / kept.length;
|
|
52879
|
+
const centreLat = kept.reduce((s, c) => s + c.lat, 0) / kept.length;
|
|
52880
|
+
const centreScreen = project(centreLon, centreLat);
|
|
52881
|
+
const lead = pointInGeometry(geometry, centreLon, centreLat) && centreScreen && Number.isFinite(centreScreen[0]) && Number.isFinite(centreScreen[1]) && centreScreen[0] >= 0 && centreScreen[0] <= width && centreScreen[1] >= 0 && centreScreen[1] <= height ? [
|
|
52882
|
+
{
|
|
52883
|
+
lonLat: [centreLon, centreLat],
|
|
52884
|
+
screen: [centreScreen[0], centreScreen[1]]
|
|
52596
52885
|
}
|
|
52597
|
-
|
|
52598
|
-
|
|
52599
|
-
|
|
52886
|
+
] : [];
|
|
52887
|
+
const grid = [...kept].sort(
|
|
52888
|
+
(a, b) => interiorness(b) - interiorness(a) || dist2ToCentre(a) - dist2ToCentre(b)
|
|
52889
|
+
).map((c) => ({
|
|
52600
52890
|
lonLat: [c.lon, c.lat],
|
|
52601
52891
|
screen: [c.sx, c.sy]
|
|
52602
52892
|
}));
|
|
52603
52893
|
const curatedPos = curated ? mkCurated(curated, project) : [];
|
|
52604
|
-
|
|
52605
|
-
return out;
|
|
52894
|
+
return [...curatedPos, ...lead, ...grid].slice(0, MAX_COUNTRY_POSITIONS);
|
|
52606
52895
|
}
|
|
52607
52896
|
function mkCurated(curated, project) {
|
|
52608
52897
|
if (!curated) return [];
|
|
@@ -52868,6 +53157,25 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
52868
53157
|
palette.bg,
|
|
52869
53158
|
mutedBasemap ? isDark ? MUTED_FOREIGN_DARK : MUTED_FOREIGN_LIGHT : isDark ? FOREIGN_TINT_DARK : FOREIGN_TINT_LIGHT
|
|
52870
53159
|
);
|
|
53160
|
+
const contrastFloorTone = (tone, ...substrates) => {
|
|
53161
|
+
const clears = (t) => substrates.every((s) => contrastRatio(t, s) >= REGION_LABEL_HALO_RATIO);
|
|
53162
|
+
if (clears(tone)) return tone;
|
|
53163
|
+
for (let s = 10; s <= 100; s += 10) {
|
|
53164
|
+
const t = mix(palette.text, tone, s);
|
|
53165
|
+
if (clears(t)) return t;
|
|
53166
|
+
}
|
|
53167
|
+
return palette.text;
|
|
53168
|
+
};
|
|
53169
|
+
const backdropLandTone = contrastFloorTone(
|
|
53170
|
+
palette.textMuted,
|
|
53171
|
+
neutralFill,
|
|
53172
|
+
water
|
|
53173
|
+
);
|
|
53174
|
+
const backdropWaterTone = contrastFloorTone(
|
|
53175
|
+
mix(palette.colors.blue, palette.textMuted, 50),
|
|
53176
|
+
water,
|
|
53177
|
+
neutralFill
|
|
53178
|
+
);
|
|
52871
53179
|
const hasDirectColor = resolved.regions.some((r) => r.color !== void 0);
|
|
52872
53180
|
const colorizeActive = resolved.directives.noColorize !== true && !hasRamp && !hasDirectColor && fillGroupNames.size === 0;
|
|
52873
53181
|
const colorByIso = /* @__PURE__ */ new Map();
|
|
@@ -52982,6 +53290,33 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
52982
53290
|
hasSubtitle: Boolean(resolved.subtitle)
|
|
52983
53291
|
});
|
|
52984
53292
|
if (legendBand > topPad) topPad = legendBand;
|
|
53293
|
+
const topReserved = [];
|
|
53294
|
+
if (shownTitle) {
|
|
53295
|
+
const lines = resolved.subtitle ? 2 : 1;
|
|
53296
|
+
const tw = Math.max(
|
|
53297
|
+
measureLegendText(shownTitle, TITLE_FONT_SIZE),
|
|
53298
|
+
resolved.subtitle ? measureLegendText(resolved.subtitle, TITLE_FONT_SIZE) : 0
|
|
53299
|
+
) + 2 * TITLE_FONT_SIZE;
|
|
53300
|
+
topReserved.push({
|
|
53301
|
+
x: width / 2 - tw / 2,
|
|
53302
|
+
y: TITLE_Y - TITLE_FONT_SIZE,
|
|
53303
|
+
w: tw,
|
|
53304
|
+
h: TITLE_FONT_SIZE * (lines + 0.5)
|
|
53305
|
+
});
|
|
53306
|
+
}
|
|
53307
|
+
const legendBox = mapLegendBox(legend, {
|
|
53308
|
+
width,
|
|
53309
|
+
mode: opts.legendMode ?? "preview",
|
|
53310
|
+
hasTitle: Boolean(shownTitle),
|
|
53311
|
+
hasSubtitle: Boolean(resolved.subtitle)
|
|
53312
|
+
});
|
|
53313
|
+
if (legendBox)
|
|
53314
|
+
topReserved.push({
|
|
53315
|
+
x: legendBox.x,
|
|
53316
|
+
y: legendBox.y,
|
|
53317
|
+
w: legendBox.width,
|
|
53318
|
+
h: legendBox.height
|
|
53319
|
+
});
|
|
52985
53320
|
const reserve = opts._calloutReserve;
|
|
52986
53321
|
const fitLeft = FIT_PAD + (reserve?.left ?? 0);
|
|
52987
53322
|
const fitRight = width - FIT_PAD - (reserve?.right ?? 0);
|
|
@@ -53711,6 +54046,19 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
53711
54046
|
const by = b.cy - (b.cy - py) / tb * trimB;
|
|
53712
54047
|
return `M${ax},${ay}Q${px},${py} ${bx},${by}`;
|
|
53713
54048
|
};
|
|
54049
|
+
const legLabelPoint = (a, b, curved, offset) => {
|
|
54050
|
+
const mx = (a.cx + b.cx) / 2;
|
|
54051
|
+
const my = (a.cy + b.cy) / 2;
|
|
54052
|
+
if (!curved && offset === 0) return { x: mx, y: my - 4 };
|
|
54053
|
+
const dx = b.cx - a.cx;
|
|
54054
|
+
const dy = b.cy - a.cy;
|
|
54055
|
+
const len = Math.hypot(dx, dy) || 1;
|
|
54056
|
+
const nx = -dy / len;
|
|
54057
|
+
const ny = dx / len;
|
|
54058
|
+
const bow = offset !== 0 ? offset : len * ARC_CURVE_FRAC;
|
|
54059
|
+
const off = bow * 0.5 + Math.sign(bow || 1) * 8;
|
|
54060
|
+
return { x: mx + nx * off, y: my + ny * off };
|
|
54061
|
+
};
|
|
53714
54062
|
const routeLegVals = resolved.routes.flatMap((rt) => rt.legs).map((l) => Number(l.value)).filter((n) => Number.isFinite(n) && n > 0);
|
|
53715
54063
|
const rlMin = routeLegVals.length ? Math.min(...routeLegVals) : 0;
|
|
53716
54064
|
const rlMax = routeLegVals.length ? Math.max(...routeLegVals) : 0;
|
|
@@ -53724,13 +54072,12 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
53724
54072
|
const a = poiScreen.get(leg.fromId);
|
|
53725
54073
|
const b = poiScreen.get(leg.toId);
|
|
53726
54074
|
if (!a || !b) continue;
|
|
53727
|
-
const
|
|
53728
|
-
const my = (a.cy + b.cy) / 2;
|
|
54075
|
+
const lp = legLabelPoint(a, b, leg.style === "arc", 0);
|
|
53729
54076
|
const bow = {
|
|
53730
54077
|
curved: leg.style === "arc",
|
|
53731
54078
|
offset: 0,
|
|
53732
|
-
labelX:
|
|
53733
|
-
labelY:
|
|
54079
|
+
labelX: lp.x,
|
|
54080
|
+
labelY: lp.y
|
|
53734
54081
|
};
|
|
53735
54082
|
const routeLabelStyle = leg.label !== void 0 ? labelOnFill(fillAt(bow.labelX, bow.labelY)) : void 0;
|
|
53736
54083
|
legs.push({
|
|
@@ -53777,13 +54124,13 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
53777
54124
|
const b = poiScreen.get(e.toId);
|
|
53778
54125
|
if (!a || !b) return;
|
|
53779
54126
|
const fanOffset = n > 1 ? (i - (n - 1) / 2) * FAN_STEP : 0;
|
|
53780
|
-
const
|
|
53781
|
-
const
|
|
54127
|
+
const curved = e.style === "arc" || n > 1;
|
|
54128
|
+
const lp = legLabelPoint(a, b, curved, fanOffset);
|
|
53782
54129
|
const bow = {
|
|
53783
|
-
curved
|
|
54130
|
+
curved,
|
|
53784
54131
|
offset: fanOffset,
|
|
53785
|
-
labelX:
|
|
53786
|
-
labelY:
|
|
54132
|
+
labelX: lp.x,
|
|
54133
|
+
labelY: lp.y
|
|
53787
54134
|
};
|
|
53788
54135
|
const edgeLabelStyle = e.label !== void 0 ? labelOnFill(fillAt(bow.labelX, bow.labelY)) : void 0;
|
|
53789
54136
|
legs.push({
|
|
@@ -53807,7 +54154,7 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
53807
54154
|
});
|
|
53808
54155
|
}
|
|
53809
54156
|
const labels = [];
|
|
53810
|
-
const obstacles = [];
|
|
54157
|
+
const obstacles = [...topReserved];
|
|
53811
54158
|
const regionLabelGuards = [];
|
|
53812
54159
|
const markers = pois.map((p) => ({
|
|
53813
54160
|
cx: p.cx,
|
|
@@ -53845,6 +54192,7 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
53845
54192
|
}
|
|
53846
54193
|
const collides = (rect) => markers.some((m) => rectCircleOverlap(rect, m)) || obstacles.some((o) => rectsOverlap(rect, o)) || legSegments.some((s) => segmentRectOverlap(s[0], s[1], s[2], s[3], rect));
|
|
53847
54194
|
const showRegionLabels = resolved.directives.noRegionLabels !== true;
|
|
54195
|
+
const labeledRegionIds = /* @__PURE__ */ new Set();
|
|
53848
54196
|
const showRegionValues = resolved.directives.noRegionValue !== true && activeIsScore;
|
|
53849
54197
|
const regionValueStr = (value) => showRegionValues && value !== void 0 ? compactNumber(value) : void 0;
|
|
53850
54198
|
const isCompact = width < COMPACT_WIDTH_PX;
|
|
@@ -53865,7 +54213,9 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
53865
54213
|
const REGION_FONT_MAX_ORIENT = 22;
|
|
53866
54214
|
const REGION_SIZE_FRAC_MIN = 0.06;
|
|
53867
54215
|
const REGION_SIZE_FRAC_MAX = 0.32;
|
|
53868
|
-
const
|
|
54216
|
+
const SUBJECT_FONT_MAX = 18;
|
|
54217
|
+
const SUBJECT_MIN_PROMINENCE = 13;
|
|
54218
|
+
const SUBJECT_LEADER_FONT = 15;
|
|
53869
54219
|
const canvasLinear = Math.sqrt(Math.max(1, width * height));
|
|
53870
54220
|
const sizeT = (boxW, boxH) => {
|
|
53871
54221
|
const frac = Math.sqrt(Math.max(0, boxW * boxH)) / canvasLinear;
|
|
@@ -53877,9 +54227,9 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
53877
54227
|
)
|
|
53878
54228
|
);
|
|
53879
54229
|
};
|
|
53880
|
-
const pushRegionLabel = (x, y, text, fill2, lineNumber, valueLine, fontSize = FONT2,
|
|
54230
|
+
const pushRegionLabel = (x, y, text, fill2, lineNumber, valueLine, fontSize = FONT2, colorOverride) => {
|
|
53881
54231
|
const { color: baseColor, haloColor } = labelOnFill(fill2);
|
|
53882
|
-
const color =
|
|
54232
|
+
const color = colorOverride ?? baseColor;
|
|
53883
54233
|
const vf = Math.round(fontSize * 0.82);
|
|
53884
54234
|
const halfW = Math.max(
|
|
53885
54235
|
measureLegendText(text, fontSize),
|
|
@@ -53894,7 +54244,11 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
53894
54244
|
text,
|
|
53895
54245
|
anchor: "middle",
|
|
53896
54246
|
color,
|
|
53897
|
-
|
|
54247
|
+
// A backdrop label (colorOverride) NEVER haloes: the placement gate above
|
|
54248
|
+
// guarantees it sits on a floored-readable substrate (own fill, neutral
|
|
54249
|
+
// land, foreign land, or water), so a halo is pure noise. Data labels keep
|
|
54250
|
+
// the containment-gated halo until the role-tier pass (Phase 3).
|
|
54251
|
+
halo: colorOverride ? false : overflows,
|
|
53898
54252
|
haloColor,
|
|
53899
54253
|
...fontSize !== FONT2 && { fontSize },
|
|
53900
54254
|
...valueLine !== void 0 && { valueLine },
|
|
@@ -53930,7 +54284,7 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
53930
54284
|
if (!c || !Number.isFinite(c[0])) return null;
|
|
53931
54285
|
return { r, c, boxW, boxH, area: boxW * boxH, candidates };
|
|
53932
54286
|
}).filter((e) => e !== null).sort((a, b) => b.area - a.area || a.r.lineNumber - b.r.lineNumber);
|
|
53933
|
-
const placedRegionRects = [];
|
|
54287
|
+
const placedRegionRects = [...topReserved];
|
|
53934
54288
|
const placedLeaders = [];
|
|
53935
54289
|
const isEmptyFill = (f) => f === water || f === neutralFill || f === foreignFill;
|
|
53936
54290
|
const POI_LABEL_PAD = 14;
|
|
@@ -53943,9 +54297,9 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
53943
54297
|
const SHORT_HOP_MAX = Math.max(46, Math.min(width, height) * 0.11);
|
|
53944
54298
|
const STEP = 4;
|
|
53945
54299
|
const HOP_GAP = 9;
|
|
53946
|
-
const tryShortHopCallout = (cx, cy, fill2, name, value) => {
|
|
53947
|
-
const chipW = stackW(name, value);
|
|
53948
|
-
const chipH = stackH(value !== void 0);
|
|
54300
|
+
const tryShortHopCallout = (cx, cy, fill2, name, value, font = FONT2, gap = HOP_GAP, maxLen = SHORT_HOP_MAX) => {
|
|
54301
|
+
const chipW = stackW(name, value, font);
|
|
54302
|
+
const chipH = stackH(value !== void 0, font);
|
|
53949
54303
|
const dirs = [
|
|
53950
54304
|
[0, -1],
|
|
53951
54305
|
// north (over Canada)
|
|
@@ -53961,7 +54315,7 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
53961
54315
|
let ex = cx;
|
|
53962
54316
|
let ey = cy;
|
|
53963
54317
|
let steps = 0;
|
|
53964
|
-
const maxSteps = Math.ceil(
|
|
54318
|
+
const maxSteps = Math.ceil(maxLen / STEP) + 1;
|
|
53965
54319
|
while (steps < maxSteps && fillAt(ex, ey) === fill2) {
|
|
53966
54320
|
ex += dx * STEP;
|
|
53967
54321
|
ey += dy * STEP;
|
|
@@ -53969,8 +54323,8 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
53969
54323
|
}
|
|
53970
54324
|
if (fillAt(ex, ey) === fill2) continue;
|
|
53971
54325
|
const halfAlong = (Math.abs(dx) * chipW + Math.abs(dy) * chipH) / 2;
|
|
53972
|
-
const ccx = ex + dx * (
|
|
53973
|
-
const ccy = ey + dy * (
|
|
54326
|
+
const ccx = ex + dx * (gap + halfAlong);
|
|
54327
|
+
const ccy = ey + dy * (gap + halfAlong);
|
|
53974
54328
|
const rect = {
|
|
53975
54329
|
x: ccx - chipW / 2,
|
|
53976
54330
|
y: ccy - chipH / 2,
|
|
@@ -53995,7 +54349,7 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
53995
54349
|
const innerX = ccx - dx * (chipW / 2);
|
|
53996
54350
|
const innerY = ccy - dy * (chipH / 2);
|
|
53997
54351
|
const len = Math.hypot(innerX - cx, innerY - cy);
|
|
53998
|
-
if (len >
|
|
54352
|
+
if (len > maxLen) continue;
|
|
53999
54353
|
if (placedLeaders.some(
|
|
54000
54354
|
(l) => segmentsCross(cx, cy, innerX, innerY, l[0], l[1], l[2], l[3])
|
|
54001
54355
|
))
|
|
@@ -54019,6 +54373,78 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54019
54373
|
const valStr = regionValueStr(r.value);
|
|
54020
54374
|
const fitsRegions = (rect) => !placedRegionRects.some((p) => rectsOverlap(rect, p));
|
|
54021
54375
|
const fitsPois = (rect) => !poiObstacles.some((o) => rectsOverlap(rect, o));
|
|
54376
|
+
const isSubject = regionById.has(r.id);
|
|
54377
|
+
const extremesOnFill = (ax, ay, text) => {
|
|
54378
|
+
const halfW = measureLegendText(text, FONT2) / 2;
|
|
54379
|
+
return fillAt(ax - halfW, ay) === r.fill && fillAt(ax + halfW, ay) === r.fill;
|
|
54380
|
+
};
|
|
54381
|
+
if (isSubject && valStr === void 0 && r.label !== void 0) {
|
|
54382
|
+
const name = candidates[0];
|
|
54383
|
+
let best = -1;
|
|
54384
|
+
for (let f = SUBJECT_FONT_MAX; f >= FONT2; f--) {
|
|
54385
|
+
if (measureLegendText(name, f) > boxW || f + 2 * LABEL_PADY > boxH)
|
|
54386
|
+
continue;
|
|
54387
|
+
const rect = regionLabelRect(c[0], c[1], name, void 0, f);
|
|
54388
|
+
if (!fitsRegions(rect) || !fitsPois(rect) || collides(rect)) continue;
|
|
54389
|
+
const halfW = measureLegendText(name, f) / 2;
|
|
54390
|
+
if (fillAt(c[0] - halfW, c[1]) !== r.fill || fillAt(c[0] + halfW, c[1]) !== r.fill)
|
|
54391
|
+
continue;
|
|
54392
|
+
best = f;
|
|
54393
|
+
break;
|
|
54394
|
+
}
|
|
54395
|
+
if (best >= SUBJECT_MIN_PROMINENCE) {
|
|
54396
|
+
const rect = regionLabelRect(c[0], c[1], name, void 0, best);
|
|
54397
|
+
placedRegionRects.push(rect);
|
|
54398
|
+
pushRegionLabel(
|
|
54399
|
+
c[0],
|
|
54400
|
+
c[1],
|
|
54401
|
+
name,
|
|
54402
|
+
r.fill,
|
|
54403
|
+
r.lineNumber,
|
|
54404
|
+
void 0,
|
|
54405
|
+
best
|
|
54406
|
+
);
|
|
54407
|
+
labeledRegionIds.add(r.id);
|
|
54408
|
+
regionLabelGuards.push({ label: labels[labels.length - 1], rect });
|
|
54409
|
+
} else {
|
|
54410
|
+
const hop = tryShortHopCallout(
|
|
54411
|
+
c[0],
|
|
54412
|
+
c[1],
|
|
54413
|
+
r.fill,
|
|
54414
|
+
r.label,
|
|
54415
|
+
void 0,
|
|
54416
|
+
SUBJECT_LEADER_FONT,
|
|
54417
|
+
HOP_GAP + SUBJECT_LEADER_FONT,
|
|
54418
|
+
SHORT_HOP_MAX * 2.2
|
|
54419
|
+
);
|
|
54420
|
+
if (hop) {
|
|
54421
|
+
placedRegionRects.push(hop.rect);
|
|
54422
|
+
placedLeaders.push(hop.leader);
|
|
54423
|
+
const dark = mix(r.fill, palette.text, 60);
|
|
54424
|
+
labels.push({
|
|
54425
|
+
x: hop.x,
|
|
54426
|
+
y: hop.y,
|
|
54427
|
+
text: r.label,
|
|
54428
|
+
anchor: "middle",
|
|
54429
|
+
color: palette.text,
|
|
54430
|
+
halo: false,
|
|
54431
|
+
haloColor: palette.bg,
|
|
54432
|
+
fontSize: SUBJECT_LEADER_FONT,
|
|
54433
|
+
leader: {
|
|
54434
|
+
x1: hop.leader[0],
|
|
54435
|
+
y1: hop.leader[1],
|
|
54436
|
+
x2: hop.leader[2],
|
|
54437
|
+
y2: hop.leader[3]
|
|
54438
|
+
},
|
|
54439
|
+
leaderColor: dark,
|
|
54440
|
+
calloutDot: { x: c[0], y: c[1], color: dark },
|
|
54441
|
+
lineNumber: r.lineNumber
|
|
54442
|
+
});
|
|
54443
|
+
labeledRegionIds.add(r.id);
|
|
54444
|
+
}
|
|
54445
|
+
}
|
|
54446
|
+
continue;
|
|
54447
|
+
}
|
|
54022
54448
|
const seekAnchors = [
|
|
54023
54449
|
{ x: c[0], y: c[1], guard: false }
|
|
54024
54450
|
];
|
|
@@ -54041,13 +54467,13 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54041
54467
|
const nameRect = regionLabelRect(a.x, a.y, t);
|
|
54042
54468
|
if (valStr && stackW(t, valStr) <= boxW && stackH(true) <= boxH) {
|
|
54043
54469
|
const stackRect = regionLabelRect(a.x, a.y, t, valStr);
|
|
54044
|
-
if (fitsRegions(stackRect) && fitsPois(nameRect)) {
|
|
54470
|
+
if (fitsRegions(stackRect) && fitsPois(nameRect) && extremesOnFill(a.x, a.y, t)) {
|
|
54045
54471
|
chosen = { text: t, valueLine: valStr, ax: a.x, ay: a.y };
|
|
54046
54472
|
break;
|
|
54047
54473
|
}
|
|
54048
54474
|
}
|
|
54049
54475
|
if (labelW(t) <= boxW && labelH <= boxH) {
|
|
54050
|
-
if (fitsRegions(nameRect) && fitsPois(nameRect)) {
|
|
54476
|
+
if (fitsRegions(nameRect) && fitsPois(nameRect) && (valStr === void 0 || extremesOnFill(a.x, a.y, t))) {
|
|
54051
54477
|
chosen = { text: t, ax: a.x, ay: a.y };
|
|
54052
54478
|
break;
|
|
54053
54479
|
}
|
|
@@ -54055,7 +54481,7 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54055
54481
|
}
|
|
54056
54482
|
if (chosen) break;
|
|
54057
54483
|
}
|
|
54058
|
-
if (chosen === void 0 &&
|
|
54484
|
+
if (chosen === void 0 && r.label !== void 0 && isSubject) {
|
|
54059
54485
|
const hop = tryShortHopCallout(c[0], c[1], r.fill, r.label, valStr);
|
|
54060
54486
|
if (hop) {
|
|
54061
54487
|
placedRegionRects.push(hop.rect);
|
|
@@ -54067,9 +54493,9 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54067
54493
|
text: r.label,
|
|
54068
54494
|
anchor: "middle",
|
|
54069
54495
|
color: palette.text,
|
|
54070
|
-
halo:
|
|
54496
|
+
halo: false,
|
|
54071
54497
|
haloColor: palette.bg,
|
|
54072
|
-
valueLine: valStr,
|
|
54498
|
+
...valStr !== void 0 && { valueLine: valStr },
|
|
54073
54499
|
leader: {
|
|
54074
54500
|
x1: hop.leader[0],
|
|
54075
54501
|
y1: hop.leader[1],
|
|
@@ -54080,20 +54506,28 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54080
54506
|
calloutDot: { x: c[0], y: c[1], color: dark },
|
|
54081
54507
|
lineNumber: r.lineNumber
|
|
54082
54508
|
});
|
|
54509
|
+
labeledRegionIds.add(r.id);
|
|
54083
54510
|
}
|
|
54084
54511
|
continue;
|
|
54085
54512
|
}
|
|
54086
54513
|
if (chosen === void 0) continue;
|
|
54087
54514
|
const isOrient = r.value === void 0 && r.layer === "base";
|
|
54088
54515
|
let font = FONT2;
|
|
54089
|
-
let fade = 0;
|
|
54090
54516
|
if (isOrient) {
|
|
54091
54517
|
const growT = sizeT(boxW, boxH);
|
|
54092
54518
|
const desiredFont = Math.round(
|
|
54093
54519
|
FONT2 + growT * (REGION_FONT_MAX_ORIENT - FONT2)
|
|
54094
54520
|
);
|
|
54095
54521
|
const hasVal = chosen.valueLine !== void 0;
|
|
54096
|
-
|
|
54522
|
+
const extremesClean = (f) => {
|
|
54523
|
+
const halfW = measureLegendText(chosen.text, f) / 2;
|
|
54524
|
+
return [chosen.ax - halfW, chosen.ax + halfW].every((sx) => {
|
|
54525
|
+
const fAt = fillAt(sx, chosen.ay);
|
|
54526
|
+
return fAt === r.fill || isEmptyFill(fAt);
|
|
54527
|
+
});
|
|
54528
|
+
};
|
|
54529
|
+
let fit = -1;
|
|
54530
|
+
for (let f = desiredFont; f >= FONT2; f--) {
|
|
54097
54531
|
if (stackW(chosen.text, chosen.valueLine, f) > boxW || stackH(hasVal, f) > boxH)
|
|
54098
54532
|
continue;
|
|
54099
54533
|
const gRect = regionLabelRect(
|
|
@@ -54110,14 +54544,18 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54110
54544
|
void 0,
|
|
54111
54545
|
f
|
|
54112
54546
|
);
|
|
54113
|
-
if (!fitsRegions(gRect) || !fitsPois(gName))
|
|
54114
|
-
const halfW = measureLegendText(chosen.text, f) / 2;
|
|
54115
|
-
if (fillAt(chosen.ax - halfW, chosen.ay) !== r.fill || fillAt(chosen.ax + halfW, chosen.ay) !== r.fill)
|
|
54547
|
+
if (!fitsRegions(gRect) || !fitsPois(gName) || collides(gName))
|
|
54116
54548
|
continue;
|
|
54117
|
-
|
|
54549
|
+
if (!extremesClean(f)) continue;
|
|
54550
|
+
fit = f;
|
|
54118
54551
|
break;
|
|
54119
54552
|
}
|
|
54120
|
-
|
|
54553
|
+
if (fit < 0) {
|
|
54554
|
+
if (!frameContainers.has(r.id)) continue;
|
|
54555
|
+
font = FONT2;
|
|
54556
|
+
} else {
|
|
54557
|
+
font = fit;
|
|
54558
|
+
}
|
|
54121
54559
|
}
|
|
54122
54560
|
const rRect = regionLabelRect(
|
|
54123
54561
|
chosen.ax,
|
|
@@ -54135,8 +54573,9 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54135
54573
|
r.lineNumber,
|
|
54136
54574
|
chosen.valueLine,
|
|
54137
54575
|
font,
|
|
54138
|
-
|
|
54576
|
+
isOrient ? backdropLandTone : void 0
|
|
54139
54577
|
);
|
|
54578
|
+
labeledRegionIds.add(r.id);
|
|
54140
54579
|
regionLabelGuards.push({
|
|
54141
54580
|
label: labels[labels.length - 1],
|
|
54142
54581
|
rect: rRect
|
|
@@ -54154,6 +54593,7 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54154
54593
|
seed.lineNumber,
|
|
54155
54594
|
valStr
|
|
54156
54595
|
);
|
|
54596
|
+
labeledRegionIds.add(seed.iso);
|
|
54157
54597
|
regionLabelGuards.push({
|
|
54158
54598
|
label: labels[labels.length - 1],
|
|
54159
54599
|
rect: regionLabelRect(seed.x, seed.y, text, valStr)
|
|
@@ -54585,13 +55025,30 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54585
55025
|
const nx = -dy / len;
|
|
54586
55026
|
const ny = dx / len;
|
|
54587
55027
|
const perp = labelH + 2;
|
|
55028
|
+
const pm = /^M(-?[\d.]+),(-?[\d.]+)(?:L(-?[\d.]+),(-?[\d.]+)|Q(-?[\d.]+),(-?[\d.]+) (-?[\d.]+),(-?[\d.]+))$/.exec(
|
|
55029
|
+
lg.d
|
|
55030
|
+
);
|
|
55031
|
+
const pointAt = (t) => {
|
|
55032
|
+
if (pm?.[5] !== void 0) {
|
|
55033
|
+
const u = 1 - t;
|
|
55034
|
+
return [
|
|
55035
|
+
u * u * +pm[1] + 2 * u * t * +pm[5] + t * t * +pm[7],
|
|
55036
|
+
u * u * +pm[2] + 2 * u * t * +pm[6] + t * t * +pm[8]
|
|
55037
|
+
];
|
|
55038
|
+
}
|
|
55039
|
+
if (pm?.[3] !== void 0)
|
|
55040
|
+
return [
|
|
55041
|
+
+pm[1] + (+pm[3] - +pm[1]) * t,
|
|
55042
|
+
+pm[2] + (+pm[4] - +pm[2]) * t
|
|
55043
|
+
];
|
|
55044
|
+
return [a.cx + dx * t, a.cy + dy * t];
|
|
55045
|
+
};
|
|
54588
55046
|
const candidates = [];
|
|
54589
55047
|
for (const off of [0, perp, -perp, 2 * perp, -2 * perp])
|
|
54590
|
-
for (const t of T_LIST)
|
|
54591
|
-
|
|
54592
|
-
|
|
54593
|
-
|
|
54594
|
-
]);
|
|
55048
|
+
for (const t of T_LIST) {
|
|
55049
|
+
const [bx, by] = pointAt(t);
|
|
55050
|
+
candidates.push([bx + nx * off, by + ny * off - 4]);
|
|
55051
|
+
}
|
|
54595
55052
|
const clean = ([cx2, cy2]) => {
|
|
54596
55053
|
const rect2 = { x: cx2 - w / 2, y: cy2 - labelH / 2, w, h: labelH };
|
|
54597
55054
|
if (rect2.x < 0 || rect2.x + w > width || rect2.y < 0 || rect2.y + rect2.h > height)
|
|
@@ -54601,10 +55058,8 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54601
55058
|
if (placedEdge.some((o) => rectsOverlap(o, rect2))) return false;
|
|
54602
55059
|
return true;
|
|
54603
55060
|
};
|
|
54604
|
-
const
|
|
54605
|
-
|
|
54606
|
-
a.cy + dy * 0.5 - 4
|
|
54607
|
-
];
|
|
55061
|
+
const mid = pointAt(0.5);
|
|
55062
|
+
const [cx, cy] = candidates.find(clean) ?? [mid[0], mid[1] - 4];
|
|
54608
55063
|
const style = labelOnFill(fillAt(cx, cy));
|
|
54609
55064
|
legs[i] = {
|
|
54610
55065
|
...lg,
|
|
@@ -54632,7 +55087,7 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54632
55087
|
const rawCountries = [];
|
|
54633
55088
|
for (const f of worldLayer.values()) {
|
|
54634
55089
|
const iso = typeof f.id === "string" ? f.id : String(f.id ?? "");
|
|
54635
|
-
if (!iso || regionById.has(iso)) continue;
|
|
55090
|
+
if (!iso || regionById.has(iso) || labeledRegionIds.has(iso)) continue;
|
|
54636
55091
|
let hasReferencedSub = false;
|
|
54637
55092
|
for (const k of regionById.keys())
|
|
54638
55093
|
if (k.startsWith(iso + "-")) {
|
|
@@ -54706,7 +55161,7 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54706
55161
|
);
|
|
54707
55162
|
if (usLayer && framedStateContainers) {
|
|
54708
55163
|
for (const [iso, f] of usLayer) {
|
|
54709
|
-
if (regionById.has(iso)) continue;
|
|
55164
|
+
if (regionById.has(iso) || labeledRegionIds.has(iso)) continue;
|
|
54710
55165
|
const viewF = cullFeatureToView(f);
|
|
54711
55166
|
if (!viewF) continue;
|
|
54712
55167
|
const b = path.bounds(viewF);
|
|
@@ -54730,6 +55185,11 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54730
55185
|
waterBodies: data.waterBodies,
|
|
54731
55186
|
countries: countryCandidates,
|
|
54732
55187
|
palette,
|
|
55188
|
+
// One muted, contrast-floored tone shared with the orientation backdrop
|
|
55189
|
+
// (region pass) so a context country (Canada) and an orientation region
|
|
55190
|
+
// (Minnesota) read identically — never below the WCAG-AA floor, no fade.
|
|
55191
|
+
countryTone: backdropLandTone,
|
|
55192
|
+
waterTone: backdropWaterTone,
|
|
54733
55193
|
project,
|
|
54734
55194
|
collides,
|
|
54735
55195
|
contentPoints,
|
|
@@ -55284,19 +55744,60 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
55284
55744
|
sel.style("cursor", "pointer").on("click", () => onClickItem(lineNumber));
|
|
55285
55745
|
};
|
|
55286
55746
|
const gLegs = svg.append("g").attr("class", "dgmo-map-legs").attr("fill", "none");
|
|
55287
|
-
|
|
55288
|
-
const
|
|
55747
|
+
const legEnd = (d) => {
|
|
55748
|
+
const m = /^M(-?[\d.]+),(-?[\d.]+)(?:L(-?[\d.]+),(-?[\d.]+)|Q(-?[\d.]+),(-?[\d.]+) (-?[\d.]+),(-?[\d.]+))$/.exec(
|
|
55749
|
+
d
|
|
55750
|
+
);
|
|
55751
|
+
if (!m) return null;
|
|
55752
|
+
const x0 = +m[1];
|
|
55753
|
+
const y0 = +m[2];
|
|
55754
|
+
let ex;
|
|
55755
|
+
let ey;
|
|
55756
|
+
let fromX;
|
|
55757
|
+
let fromY;
|
|
55758
|
+
if (m[3] !== void 0) {
|
|
55759
|
+
ex = +m[3];
|
|
55760
|
+
ey = +m[4];
|
|
55761
|
+
fromX = x0;
|
|
55762
|
+
fromY = y0;
|
|
55763
|
+
} else {
|
|
55764
|
+
ex = +m[7];
|
|
55765
|
+
ey = +m[8];
|
|
55766
|
+
fromX = +m[5];
|
|
55767
|
+
fromY = +m[6];
|
|
55768
|
+
}
|
|
55769
|
+
const dx = ex - fromX;
|
|
55770
|
+
const dy = ey - fromY;
|
|
55771
|
+
const len = Math.hypot(dx, dy);
|
|
55772
|
+
if (!(len > 0)) return null;
|
|
55773
|
+
return { ex, ey, tx: dx / len, ty: dy / len };
|
|
55774
|
+
};
|
|
55775
|
+
layout.legs.forEach((leg) => {
|
|
55776
|
+
const end = leg.arrow ? legEnd(leg.d) : null;
|
|
55777
|
+
let drawD = leg.d;
|
|
55778
|
+
let arrowTri = null;
|
|
55779
|
+
if (end) {
|
|
55780
|
+
const aLen = arrowSize(leg.width);
|
|
55781
|
+
const aHalf = Math.max(aLen * 0.5, leg.width * 0.6 + 1);
|
|
55782
|
+
const bx = end.ex - end.tx * aLen;
|
|
55783
|
+
const by = end.ey - end.ty * aLen;
|
|
55784
|
+
const px = -end.ty;
|
|
55785
|
+
const py = end.tx;
|
|
55786
|
+
arrowTri = `M${bx + px * aHalf},${by + py * aHalf}L${end.ex},${end.ey}L${bx - px * aHalf},${by - py * aHalf}z`;
|
|
55787
|
+
drawD = leg.d.replace(
|
|
55788
|
+
/(-?[\d.]+),(-?[\d.]+)$/,
|
|
55789
|
+
`${bx.toFixed(2)},${by.toFixed(2)}`
|
|
55790
|
+
);
|
|
55791
|
+
}
|
|
55792
|
+
const p = gLegs.append("path").attr("d", drawD).attr("stroke", leg.color).attr("stroke-width", leg.width).attr("stroke-linecap", "round").attr("data-from-id", leg.fromId).attr("data-to-id", leg.toId);
|
|
55289
55793
|
if (leg.tags) {
|
|
55290
55794
|
for (const [group, value] of Object.entries(leg.tags)) {
|
|
55291
55795
|
p.attr(`data-tag-${group.toLowerCase()}`, value.toLowerCase());
|
|
55292
55796
|
}
|
|
55293
55797
|
}
|
|
55294
55798
|
wireSync(p, leg.lineNumber);
|
|
55295
|
-
if (
|
|
55296
|
-
|
|
55297
|
-
const s = arrowSize(leg.width);
|
|
55298
|
-
defs.append("marker").attr("id", id).attr("viewBox", "0 0 10 10").attr("refX", 10).attr("refY", 5).attr("markerUnits", "userSpaceOnUse").attr("markerWidth", s).attr("markerHeight", s).attr("orient", "auto-start-reverse").append("path").attr("d", "M0,0L10,5L0,10z").attr("fill", leg.color);
|
|
55299
|
-
p.attr("marker-end", `url(#${id})`);
|
|
55799
|
+
if (arrowTri) {
|
|
55800
|
+
gLegs.append("path").attr("d", arrowTri).attr("fill", leg.color).attr("stroke", leg.color).attr("stroke-width", 1).attr("stroke-linejoin", "round").attr("data-from-id", leg.fromId).attr("data-to-id", leg.toId);
|
|
55300
55801
|
}
|
|
55301
55802
|
if (leg.label !== void 0 && leg.labelX !== void 0) {
|
|
55302
55803
|
const lt = emitText(
|
|
@@ -58925,9 +59426,9 @@ var init_renderer20 = __esm({
|
|
|
58925
59426
|
}
|
|
58926
59427
|
});
|
|
58927
59428
|
|
|
58928
|
-
// node_modules/.pnpm/lz-string@1.5.0/node_modules/lz-string/libs/lz-string.js
|
|
59429
|
+
// ../../diagrammo/dgmo/node_modules/.pnpm/lz-string@1.5.0/node_modules/lz-string/libs/lz-string.js
|
|
58929
59430
|
var require_lz_string = __commonJS({
|
|
58930
|
-
"node_modules/.pnpm/lz-string@1.5.0/node_modules/lz-string/libs/lz-string.js"(exports2, module2) {
|
|
59431
|
+
"../../diagrammo/dgmo/node_modules/.pnpm/lz-string@1.5.0/node_modules/lz-string/libs/lz-string.js"(exports2, module2) {
|
|
58931
59432
|
"use strict";
|
|
58932
59433
|
var LZString = (function() {
|
|
58933
59434
|
var f = String.fromCharCode;
|
|
@@ -59452,12 +59953,10 @@ __export(advanced_exports, {
|
|
|
59452
59953
|
extractFlowchartSymbols: () => extractSymbols,
|
|
59453
59954
|
extractInfraSymbols: () => extractSymbols4,
|
|
59454
59955
|
extractPertSymbols: () => extractPertSymbols,
|
|
59455
|
-
findUnsafePipePositions: () => findUnsafePipePositions,
|
|
59456
59956
|
focusBoxesAndLines: () => focusBoxesAndLines,
|
|
59457
59957
|
focusOrgTree: () => focusOrgTree,
|
|
59458
59958
|
formatDateLabel: () => formatDateLabel,
|
|
59459
59959
|
formatDgmoError: () => formatDgmoError,
|
|
59460
|
-
formatLineDiff: () => formatLineDiff,
|
|
59461
59960
|
getAllChartTypes: () => getAllChartTypes,
|
|
59462
59961
|
getAvailablePalettes: () => getAvailablePalettes,
|
|
59463
59962
|
getExtendedChartLegendGroups: () => getExtendedChartLegendGroups,
|
|
@@ -59478,7 +59977,6 @@ __export(advanced_exports, {
|
|
|
59478
59977
|
isArchiveColumn: () => isArchiveColumn,
|
|
59479
59978
|
isExtendedChartType: () => isExtendedChartType,
|
|
59480
59979
|
isInvalidColorToken: () => isInvalidColorToken,
|
|
59481
|
-
isLegacyMetadataLine: () => isLegacyMetadataLine,
|
|
59482
59980
|
isRecognizedColorName: () => isRecognizedColorName,
|
|
59483
59981
|
isSequenceBlock: () => isSequenceBlock,
|
|
59484
59982
|
isSequenceNote: () => isSequenceNote,
|
|
@@ -59515,7 +60013,6 @@ __export(advanced_exports, {
|
|
|
59515
60013
|
mapExportDimensions: () => mapExportDimensions,
|
|
59516
60014
|
mapNeutralLandColor: () => mapNeutralLandColor,
|
|
59517
60015
|
measurePertAnalysisBlock: () => measurePertAnalysisBlock,
|
|
59518
|
-
migrateContent: () => migrateContent,
|
|
59519
60016
|
mix: () => mix,
|
|
59520
60017
|
mulberry32: () => mulberry32,
|
|
59521
60018
|
nearestNamedColor: () => nearestNamedColor,
|
|
@@ -59643,7 +60140,6 @@ __export(advanced_exports, {
|
|
|
59643
60140
|
tidewaterPalette: () => tidewaterPalette,
|
|
59644
60141
|
tint: () => tint,
|
|
59645
60142
|
tokyoNightPalette: () => tokyoNightPalette,
|
|
59646
|
-
transformLine: () => transformLine,
|
|
59647
60143
|
truncateBareUrl: () => truncateBareUrl,
|
|
59648
60144
|
validate: () => parseDgmo,
|
|
59649
60145
|
validateComputed: () => validateComputed,
|
|
@@ -65481,320 +65977,6 @@ var themes = {
|
|
|
65481
65977
|
|
|
65482
65978
|
// src/advanced.ts
|
|
65483
65979
|
init_dgmo_router();
|
|
65484
|
-
|
|
65485
|
-
// src/migrate/index.ts
|
|
65486
|
-
var import_node_fs = require("fs");
|
|
65487
|
-
var import_node_path = require("path");
|
|
65488
|
-
init_dgmo_router();
|
|
65489
|
-
|
|
65490
|
-
// src/migrate/line-classifier.ts
|
|
65491
|
-
function findUnsafePipePositions(line11) {
|
|
65492
|
-
const positions = [];
|
|
65493
|
-
let i = 0;
|
|
65494
|
-
let inDouble = false;
|
|
65495
|
-
let inSingle = false;
|
|
65496
|
-
let braceDepth = 0;
|
|
65497
|
-
let inArrow = false;
|
|
65498
|
-
let arrowOpenChar = null;
|
|
65499
|
-
while (i < line11.length) {
|
|
65500
|
-
const ch = line11[i];
|
|
65501
|
-
const ch2 = i + 1 < line11.length ? line11[i + 1] : "";
|
|
65502
|
-
if (inDouble) {
|
|
65503
|
-
if (ch === '"') inDouble = false;
|
|
65504
|
-
i++;
|
|
65505
|
-
continue;
|
|
65506
|
-
}
|
|
65507
|
-
if (inSingle) {
|
|
65508
|
-
if (ch === "'") inSingle = false;
|
|
65509
|
-
i++;
|
|
65510
|
-
continue;
|
|
65511
|
-
}
|
|
65512
|
-
if (inArrow) {
|
|
65513
|
-
if (arrowOpenChar === "-" && ch === "-" && ch2 === ">" || arrowOpenChar === "~" && ch === "~" && ch2 === ">") {
|
|
65514
|
-
inArrow = false;
|
|
65515
|
-
arrowOpenChar = null;
|
|
65516
|
-
i += 2;
|
|
65517
|
-
continue;
|
|
65518
|
-
}
|
|
65519
|
-
i++;
|
|
65520
|
-
continue;
|
|
65521
|
-
}
|
|
65522
|
-
if (ch === '"') {
|
|
65523
|
-
inDouble = true;
|
|
65524
|
-
i++;
|
|
65525
|
-
continue;
|
|
65526
|
-
}
|
|
65527
|
-
if (ch === "'") {
|
|
65528
|
-
inSingle = true;
|
|
65529
|
-
i++;
|
|
65530
|
-
continue;
|
|
65531
|
-
}
|
|
65532
|
-
if (ch === "{") {
|
|
65533
|
-
braceDepth++;
|
|
65534
|
-
i++;
|
|
65535
|
-
continue;
|
|
65536
|
-
}
|
|
65537
|
-
if (ch === "}") {
|
|
65538
|
-
if (braceDepth > 0) braceDepth--;
|
|
65539
|
-
i++;
|
|
65540
|
-
continue;
|
|
65541
|
-
}
|
|
65542
|
-
if ((ch === "-" || ch === "~") && i > 0) {
|
|
65543
|
-
const prev = line11[i - 1];
|
|
65544
|
-
const onBoundary = prev === " " || prev === " ";
|
|
65545
|
-
const nextIsLabelChar = ch2 !== "" && ch2 !== ch && ch2 !== ">" && ch2 !== " " && ch2 !== " ";
|
|
65546
|
-
if (onBoundary && nextIsLabelChar) {
|
|
65547
|
-
const closer = ch + ">";
|
|
65548
|
-
const closeIdx = line11.indexOf(closer, i + 1);
|
|
65549
|
-
if (closeIdx > i) {
|
|
65550
|
-
const labelRegion = line11.substring(i + 1, closeIdx);
|
|
65551
|
-
if (!labelRegion.includes("->") && !labelRegion.includes("~>")) {
|
|
65552
|
-
inArrow = true;
|
|
65553
|
-
arrowOpenChar = ch;
|
|
65554
|
-
i++;
|
|
65555
|
-
continue;
|
|
65556
|
-
}
|
|
65557
|
-
}
|
|
65558
|
-
}
|
|
65559
|
-
}
|
|
65560
|
-
if (ch === "|" && braceDepth === 0) {
|
|
65561
|
-
positions.push(i);
|
|
65562
|
-
}
|
|
65563
|
-
i++;
|
|
65564
|
-
}
|
|
65565
|
-
return positions;
|
|
65566
|
-
}
|
|
65567
|
-
function isLegacyMetadataLine(line11) {
|
|
65568
|
-
return findUnsafePipePositions(line11).length > 0;
|
|
65569
|
-
}
|
|
65570
|
-
|
|
65571
|
-
// src/migrate/line-transformer.ts
|
|
65572
|
-
function replaceUnsafePipesWithCommas(s) {
|
|
65573
|
-
const positions = findUnsafePipePositions(s);
|
|
65574
|
-
if (positions.length === 0) return s;
|
|
65575
|
-
const chars = s.split("");
|
|
65576
|
-
for (const pos of positions) {
|
|
65577
|
-
chars[pos] = ",";
|
|
65578
|
-
}
|
|
65579
|
-
return chars.join("");
|
|
65580
|
-
}
|
|
65581
|
-
var GANTT_PERCENT = {
|
|
65582
|
-
match: (t) => /^\d+(?:\.\d+)?\s*%$/.test(t.trim()),
|
|
65583
|
-
promote: (t) => `progress: ${t.trim().replace(/\s*%$/, "")}`
|
|
65584
|
-
};
|
|
65585
|
-
var JOURNEY_SCORE = {
|
|
65586
|
-
match: (t) => /^\d+(?:\s+[A-Za-z][A-Za-z0-9_-]*)?$/.test(t.trim()),
|
|
65587
|
-
promote: (t) => {
|
|
65588
|
-
const m = t.trim().match(/^(\d+)(?:\s+([A-Za-z][A-Za-z0-9_-]*))?$/);
|
|
65589
|
-
if (!m) return t;
|
|
65590
|
-
return m[2] ? `score: ${m[1]}, emotion: ${m[2]}` : `score: ${m[1]}`;
|
|
65591
|
-
}
|
|
65592
|
-
};
|
|
65593
|
-
var PROMOTIONS_BY_CHART = {
|
|
65594
|
-
gantt: [GANTT_PERCENT],
|
|
65595
|
-
"journey-map": [JOURNEY_SCORE]
|
|
65596
|
-
};
|
|
65597
|
-
var BARE_DESCRIPTION_CHARTS = /* @__PURE__ */ new Set(["pyramid", "ring"]);
|
|
65598
|
-
function tokenizeMetaRegion(region) {
|
|
65599
|
-
const tokens = [];
|
|
65600
|
-
let i = 0;
|
|
65601
|
-
let buf = "";
|
|
65602
|
-
let inQuote = null;
|
|
65603
|
-
while (i < region.length) {
|
|
65604
|
-
const ch = region[i];
|
|
65605
|
-
if (inQuote) {
|
|
65606
|
-
buf += ch;
|
|
65607
|
-
if (ch === inQuote) inQuote = null;
|
|
65608
|
-
i++;
|
|
65609
|
-
continue;
|
|
65610
|
-
}
|
|
65611
|
-
if (ch === '"' || ch === "'") {
|
|
65612
|
-
inQuote = ch;
|
|
65613
|
-
buf += ch;
|
|
65614
|
-
i++;
|
|
65615
|
-
continue;
|
|
65616
|
-
}
|
|
65617
|
-
if (ch === ",") {
|
|
65618
|
-
const t = buf.trim();
|
|
65619
|
-
if (t) tokens.push(t);
|
|
65620
|
-
buf = "";
|
|
65621
|
-
i++;
|
|
65622
|
-
continue;
|
|
65623
|
-
}
|
|
65624
|
-
buf += ch;
|
|
65625
|
-
i++;
|
|
65626
|
-
}
|
|
65627
|
-
const tail = buf.trim();
|
|
65628
|
-
if (tail) tokens.push(tail);
|
|
65629
|
-
return tokens;
|
|
65630
|
-
}
|
|
65631
|
-
function transformLine(line11, chartType) {
|
|
65632
|
-
const indentMatch = line11.match(/^[ \t]*/);
|
|
65633
|
-
const indent = indentMatch ? indentMatch[0] : "";
|
|
65634
|
-
const body = line11.substring(indent.length);
|
|
65635
|
-
const pipePositions = findUnsafePipePositions(body);
|
|
65636
|
-
if (pipePositions.length === 0) {
|
|
65637
|
-
return { line: line11, changed: false };
|
|
65638
|
-
}
|
|
65639
|
-
const cut = pipePositions[0];
|
|
65640
|
-
const nameRegion = body.substring(0, cut).trimEnd();
|
|
65641
|
-
let metaRegion = body.substring(cut + 1).trimStart();
|
|
65642
|
-
if (pipePositions.length > 1) {
|
|
65643
|
-
metaRegion = replaceUnsafePipesWithCommas(metaRegion);
|
|
65644
|
-
}
|
|
65645
|
-
if (chartType !== null && BARE_DESCRIPTION_CHARTS.has(chartType) && !metaRegion.includes(":")) {
|
|
65646
|
-
const text = metaRegion.trim();
|
|
65647
|
-
if (!text) {
|
|
65648
|
-
return {
|
|
65649
|
-
line: indent + nameRegion,
|
|
65650
|
-
changed: true
|
|
65651
|
-
};
|
|
65652
|
-
}
|
|
65653
|
-
const value = text.includes(",") ? `"${text}"` : text;
|
|
65654
|
-
return {
|
|
65655
|
-
line: `${indent}${nameRegion} description: ${value}`,
|
|
65656
|
-
changed: true
|
|
65657
|
-
};
|
|
65658
|
-
}
|
|
65659
|
-
const tokens = tokenizeMetaRegion(metaRegion);
|
|
65660
|
-
const promotions = chartType ? PROMOTIONS_BY_CHART[chartType] ?? [] : [];
|
|
65661
|
-
const emitted = [];
|
|
65662
|
-
for (const raw of tokens) {
|
|
65663
|
-
if (raw.includes(":")) {
|
|
65664
|
-
emitted.push(raw);
|
|
65665
|
-
continue;
|
|
65666
|
-
}
|
|
65667
|
-
const promo = promotions.find((p) => p.match(raw));
|
|
65668
|
-
if (promo) {
|
|
65669
|
-
emitted.push(promo.promote(raw));
|
|
65670
|
-
continue;
|
|
65671
|
-
}
|
|
65672
|
-
emitted.push(raw);
|
|
65673
|
-
}
|
|
65674
|
-
if (emitted.length === 0) {
|
|
65675
|
-
return {
|
|
65676
|
-
line: indent + nameRegion,
|
|
65677
|
-
changed: true
|
|
65678
|
-
};
|
|
65679
|
-
}
|
|
65680
|
-
return {
|
|
65681
|
-
line: `${indent}${nameRegion} ${emitted.join(", ")}`,
|
|
65682
|
-
changed: true
|
|
65683
|
-
};
|
|
65684
|
-
}
|
|
65685
|
-
|
|
65686
|
-
// src/migrate/data-comma.ts
|
|
65687
|
-
init_colors();
|
|
65688
|
-
var DATA_COMMA_CHART_TYPES = /* @__PURE__ */ new Set([
|
|
65689
|
-
// Simple charts (chart.ts)
|
|
65690
|
-
"bar",
|
|
65691
|
-
"line",
|
|
65692
|
-
"multi-line",
|
|
65693
|
-
"pie",
|
|
65694
|
-
"doughnut",
|
|
65695
|
-
"area",
|
|
65696
|
-
"polar-area",
|
|
65697
|
-
"radar",
|
|
65698
|
-
"bar-stacked",
|
|
65699
|
-
// Extended charts (echarts.ts)
|
|
65700
|
-
"scatter",
|
|
65701
|
-
"heatmap",
|
|
65702
|
-
"sankey",
|
|
65703
|
-
"chord",
|
|
65704
|
-
"funnel",
|
|
65705
|
-
// Visualizations (d3 / visualizations/parse.ts)
|
|
65706
|
-
"quadrant",
|
|
65707
|
-
"slope",
|
|
65708
|
-
"arc",
|
|
65709
|
-
"wordcloud"
|
|
65710
|
-
]);
|
|
65711
|
-
var COLOR_SET = new Set(RECOGNIZED_COLOR_NAMES);
|
|
65712
|
-
var NUMERIC_VALUE_RE = /^-?\d[\d,_]*(?:\.\d+)?,?$/;
|
|
65713
|
-
function isNumericValueToken(tok) {
|
|
65714
|
-
if (!NUMERIC_VALUE_RE.test(tok)) return false;
|
|
65715
|
-
return /\d/.test(tok);
|
|
65716
|
-
}
|
|
65717
|
-
function migrateDataRowCommaLine(line11) {
|
|
65718
|
-
const indentMatch = line11.match(/^[ \t]*/);
|
|
65719
|
-
const indent = indentMatch ? indentMatch[0] : "";
|
|
65720
|
-
const body = line11.substring(indent.length);
|
|
65721
|
-
if (!body || body.startsWith("//")) return { line: line11, changed: false };
|
|
65722
|
-
const tokens = body.split(/\s+/);
|
|
65723
|
-
if (tokens.length < 2) return { line: line11, changed: false };
|
|
65724
|
-
let i = tokens.length - 1;
|
|
65725
|
-
if (i >= 1 && COLOR_SET.has(tokens[i])) {
|
|
65726
|
-
i--;
|
|
65727
|
-
}
|
|
65728
|
-
const valueStart = (() => {
|
|
65729
|
-
let j = i;
|
|
65730
|
-
while (j >= 1 && isNumericValueToken(tokens[j])) j--;
|
|
65731
|
-
return j + 1;
|
|
65732
|
-
})();
|
|
65733
|
-
if (valueStart > i || valueStart < 1) return { line: line11, changed: false };
|
|
65734
|
-
const valueTokens = tokens.slice(valueStart, i + 1);
|
|
65735
|
-
const hasComma = valueTokens.some((t) => t.includes(","));
|
|
65736
|
-
if (!hasComma) return { line: line11, changed: false };
|
|
65737
|
-
const cleaned = valueTokens.map((t) => t.replace(/,/g, ""));
|
|
65738
|
-
const labelPart = tokens.slice(0, valueStart);
|
|
65739
|
-
const tail = tokens.slice(i + 1);
|
|
65740
|
-
const rebuiltBody = [...labelPart, ...cleaned, ...tail].join(" ");
|
|
65741
|
-
return { line: indent + rebuiltBody, changed: rebuiltBody !== body };
|
|
65742
|
-
}
|
|
65743
|
-
|
|
65744
|
-
// src/migrate/index.ts
|
|
65745
|
-
function migrateContent(source) {
|
|
65746
|
-
const chartType = parseDgmoChartType(source);
|
|
65747
|
-
const lines = source.split("\n");
|
|
65748
|
-
const out = [];
|
|
65749
|
-
const changedLines = [];
|
|
65750
|
-
let changed = false;
|
|
65751
|
-
const migrateDataCommas = chartType !== null && DATA_COMMA_CHART_TYPES.has(chartType);
|
|
65752
|
-
let firstContentSeen = false;
|
|
65753
|
-
for (let i = 0; i < lines.length; i++) {
|
|
65754
|
-
let line11 = lines[i];
|
|
65755
|
-
const trimmed = line11.trim();
|
|
65756
|
-
if (migrateDataCommas && firstContentSeen && trimmed && !trimmed.startsWith("//")) {
|
|
65757
|
-
const dc = migrateDataRowCommaLine(line11);
|
|
65758
|
-
if (dc.changed) {
|
|
65759
|
-
line11 = dc.line;
|
|
65760
|
-
changed = true;
|
|
65761
|
-
changedLines.push(i + 1);
|
|
65762
|
-
}
|
|
65763
|
-
}
|
|
65764
|
-
if (trimmed && !trimmed.startsWith("//")) firstContentSeen = true;
|
|
65765
|
-
if (!isLegacyMetadataLine(line11)) {
|
|
65766
|
-
out.push(line11);
|
|
65767
|
-
continue;
|
|
65768
|
-
}
|
|
65769
|
-
const result = transformLine(line11, chartType);
|
|
65770
|
-
if (result.changed) {
|
|
65771
|
-
changed = true;
|
|
65772
|
-
if (!changedLines.includes(i + 1)) changedLines.push(i + 1);
|
|
65773
|
-
}
|
|
65774
|
-
out.push(result.line);
|
|
65775
|
-
}
|
|
65776
|
-
return {
|
|
65777
|
-
migrated: out.join("\n"),
|
|
65778
|
-
changed,
|
|
65779
|
-
chartType,
|
|
65780
|
-
changedLines
|
|
65781
|
-
};
|
|
65782
|
-
}
|
|
65783
|
-
function formatLineDiff(path, original, migrated) {
|
|
65784
|
-
const origLines = original.split("\n");
|
|
65785
|
-
const newLines = migrated.split("\n");
|
|
65786
|
-
const lines = [`--- ${path}`, `+++ ${path}`];
|
|
65787
|
-
const max = Math.max(origLines.length, newLines.length);
|
|
65788
|
-
for (let i = 0; i < max; i++) {
|
|
65789
|
-
const a = origLines[i];
|
|
65790
|
-
const b = newLines[i];
|
|
65791
|
-
if (a === b) continue;
|
|
65792
|
-
if (a !== void 0) lines.push(`@@ line ${i + 1}
|
|
65793
|
-
- ${a}`);
|
|
65794
|
-
if (b !== void 0) lines.push(`+ ${b}`);
|
|
65795
|
-
}
|
|
65796
|
-
return lines.join("\n");
|
|
65797
|
-
}
|
|
65798
65980
|
// Annotate the CommonJS export names for ESM import in node:
|
|
65799
65981
|
0 && (module.exports = {
|
|
65800
65982
|
ALL_CHART_TYPES,
|
|
@@ -65864,12 +66046,10 @@ function formatLineDiff(path, original, migrated) {
|
|
|
65864
66046
|
extractFlowchartSymbols,
|
|
65865
66047
|
extractInfraSymbols,
|
|
65866
66048
|
extractPertSymbols,
|
|
65867
|
-
findUnsafePipePositions,
|
|
65868
66049
|
focusBoxesAndLines,
|
|
65869
66050
|
focusOrgTree,
|
|
65870
66051
|
formatDateLabel,
|
|
65871
66052
|
formatDgmoError,
|
|
65872
|
-
formatLineDiff,
|
|
65873
66053
|
getAllChartTypes,
|
|
65874
66054
|
getAvailablePalettes,
|
|
65875
66055
|
getExtendedChartLegendGroups,
|
|
@@ -65890,7 +66070,6 @@ function formatLineDiff(path, original, migrated) {
|
|
|
65890
66070
|
isArchiveColumn,
|
|
65891
66071
|
isExtendedChartType,
|
|
65892
66072
|
isInvalidColorToken,
|
|
65893
|
-
isLegacyMetadataLine,
|
|
65894
66073
|
isRecognizedColorName,
|
|
65895
66074
|
isSequenceBlock,
|
|
65896
66075
|
isSequenceNote,
|
|
@@ -65927,7 +66106,6 @@ function formatLineDiff(path, original, migrated) {
|
|
|
65927
66106
|
mapExportDimensions,
|
|
65928
66107
|
mapNeutralLandColor,
|
|
65929
66108
|
measurePertAnalysisBlock,
|
|
65930
|
-
migrateContent,
|
|
65931
66109
|
mix,
|
|
65932
66110
|
mulberry32,
|
|
65933
66111
|
nearestNamedColor,
|
|
@@ -66055,7 +66233,6 @@ function formatLineDiff(path, original, migrated) {
|
|
|
66055
66233
|
tidewaterPalette,
|
|
66056
66234
|
tint,
|
|
66057
66235
|
tokyoNightPalette,
|
|
66058
|
-
transformLine,
|
|
66059
66236
|
truncateBareUrl,
|
|
66060
66237
|
validate,
|
|
66061
66238
|
validateComputed,
|