@diagrammo/dgmo 0.34.0 → 0.36.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 +41 -43
- package/.github/copilot-instructions.md +1 -1
- package/README.md +7 -1
- package/SKILL.md +12 -7
- package/dist/advanced.cjs +460 -463
- package/dist/advanced.d.cts +2 -51
- package/dist/advanced.d.ts +2 -51
- package/dist/advanced.js +460 -464
- package/dist/auto.cjs +461 -140
- package/dist/auto.js +91 -91
- package/dist/auto.mjs +461 -140
- package/dist/cli.cjs +143 -326
- package/dist/index.cjs +460 -139
- package/dist/index.js +460 -139
- package/docs/ai-integration.md +47 -25
- package/docs/language-reference.md +2 -2
- package/package.json +2 -2
- package/src/advanced.ts +0 -12
- 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.js
CHANGED
|
@@ -35,6 +35,17 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
35
35
|
function makeDgmoError(line11, message, severity = "error", code) {
|
|
36
36
|
return code !== void 0 ? { line: line11, message, severity, code } : { line: line11, message, severity };
|
|
37
37
|
}
|
|
38
|
+
function dedupeDiagnostics(diagnostics) {
|
|
39
|
+
const seen = /* @__PURE__ */ new Set();
|
|
40
|
+
const out = [];
|
|
41
|
+
for (const d of diagnostics) {
|
|
42
|
+
const key = `${d.line}\0${d.column ?? ""}\0${d.severity}\0${d.code ?? ""}\0${d.message}`;
|
|
43
|
+
if (seen.has(key)) continue;
|
|
44
|
+
seen.add(key);
|
|
45
|
+
out.push(d);
|
|
46
|
+
}
|
|
47
|
+
return out;
|
|
48
|
+
}
|
|
38
49
|
function formatDgmoError(err) {
|
|
39
50
|
return err.line > 0 ? `Line ${err.line}: ${err.message}` : err.message;
|
|
40
51
|
}
|
|
@@ -92,7 +103,7 @@ function vennAliasKeywordRemovedMessage(args) {
|
|
|
92
103
|
return `Venn 'alias' keyword was removed. Use 'as' instead \u2014 '${args.name} as ${args.alias}'.`;
|
|
93
104
|
}
|
|
94
105
|
function pipeOperatorRemovedMessage() {
|
|
95
|
-
return `'|' removed \u2014 'Node | c: red' \u2192 'Node c: red'
|
|
106
|
+
return `'|' removed \u2014 'Node | c: red' \u2192 'Node c: red'`;
|
|
96
107
|
}
|
|
97
108
|
function ganttBarePercentRemovedMessage(percent) {
|
|
98
109
|
return `Bare-percent progress shorthand '| ${percent}' was removed. Use 'progress: ${percent.replace(/%$/, "")}' (integer 0\u2013100, no '%').`;
|
|
@@ -1245,7 +1256,7 @@ var init_parsing = __esm({
|
|
|
1245
1256
|
"no-title",
|
|
1246
1257
|
"no-notes"
|
|
1247
1258
|
]);
|
|
1248
|
-
MULTIPLE_PIPE_ERROR = '
|
|
1259
|
+
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.";
|
|
1249
1260
|
RESERVED_KEY_RE = /^[A-Za-z][A-Za-z0-9_-]*$/;
|
|
1250
1261
|
AS_ALIAS_RE = /\s+as\s+([A-Za-z][A-Za-z0-9_]{0,11})$/;
|
|
1251
1262
|
POTENTIAL_META_RE = /\b([\w-]+)\s*:/;
|
|
@@ -1426,12 +1437,10 @@ function validateTagValues(entities, tagGroups, pushWarning, suggestFn) {
|
|
|
1426
1437
|
);
|
|
1427
1438
|
if (!isPrefix) {
|
|
1428
1439
|
const defined = group.entries.map((e) => e.value);
|
|
1429
|
-
let msg = `Unknown value '${value}' for tag group '${group.name}'`;
|
|
1440
|
+
let msg = `Unknown value '${value}' for tag group '${group.name}' \u2014 use one of: ${defined.join(", ")}`;
|
|
1430
1441
|
const hint = suggestFn?.(value, defined);
|
|
1431
1442
|
if (hint) {
|
|
1432
1443
|
msg += `. ${hint}`;
|
|
1433
|
-
} else {
|
|
1434
|
-
msg += ` \u2014 defined values: ${defined.join(", ")}`;
|
|
1435
1444
|
}
|
|
1436
1445
|
pushWarning(entity.lineNumber, msg);
|
|
1437
1446
|
}
|
|
@@ -2207,7 +2216,10 @@ function parseVisualizationFull(content, palette) {
|
|
|
2207
2216
|
lineNumber
|
|
2208
2217
|
});
|
|
2209
2218
|
} else {
|
|
2210
|
-
warn(
|
|
2219
|
+
warn(
|
|
2220
|
+
lineNumber,
|
|
2221
|
+
`Unrecognized era entry: "${line11}" \u2014 use '<start> -> <end> Label [color]' (e.g. '1716 -> 1717 Reign').`
|
|
2222
|
+
);
|
|
2211
2223
|
}
|
|
2212
2224
|
continue;
|
|
2213
2225
|
}
|
|
@@ -2235,7 +2247,10 @@ function parseVisualizationFull(content, palette) {
|
|
|
2235
2247
|
lineNumber
|
|
2236
2248
|
});
|
|
2237
2249
|
} else {
|
|
2238
|
-
warn(
|
|
2250
|
+
warn(
|
|
2251
|
+
lineNumber,
|
|
2252
|
+
`Unrecognized marker entry: "${line11}" \u2014 use '<date> Label [color]' (e.g. '1776 Independence').`
|
|
2253
|
+
);
|
|
2239
2254
|
}
|
|
2240
2255
|
continue;
|
|
2241
2256
|
}
|
|
@@ -2913,7 +2928,7 @@ function parseVisualizationFull(content, palette) {
|
|
|
2913
2928
|
result.diagnostics.push(
|
|
2914
2929
|
makeDgmoError(
|
|
2915
2930
|
ov.lineNumber,
|
|
2916
|
-
`Intersection references unknown set or alias "${ref}"`
|
|
2931
|
+
`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)`
|
|
2917
2932
|
)
|
|
2918
2933
|
);
|
|
2919
2934
|
if (!result.error)
|
|
@@ -6296,10 +6311,10 @@ function parseSequenceDgmo(content, palette) {
|
|
|
6296
6311
|
const rawInside = fallbackMatch[1];
|
|
6297
6312
|
const pipeIdx = rawInside.indexOf("|");
|
|
6298
6313
|
const cleanName = rawInside.substring(0, pipeIdx).trim().replace(/\([^)]*\)$/, "").trim();
|
|
6299
|
-
const metaPart = rawInside.substring(pipeIdx).trim();
|
|
6314
|
+
const metaPart = rawInside.substring(pipeIdx).replace(/^\|\s*/, "").trim();
|
|
6300
6315
|
pushError(
|
|
6301
6316
|
lineNumber,
|
|
6302
|
-
`
|
|
6317
|
+
`Metadata goes after the bracket with no pipe \u2014 use '[${cleanName}] ${metaPart}' (e.g. '[Backend] t: Product'), not '[${rawInside.trim()}]'`
|
|
6303
6318
|
);
|
|
6304
6319
|
continue;
|
|
6305
6320
|
}
|
|
@@ -6909,7 +6924,7 @@ function parseSequenceDgmo(content, palette) {
|
|
|
6909
6924
|
}
|
|
6910
6925
|
pushWarning(
|
|
6911
6926
|
lineNumber,
|
|
6912
|
-
`Unexpected line: '${trimmed}'. Expected a message (A -> B), participant, section (== Name ==), or block
|
|
6927
|
+
`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>').`
|
|
6913
6928
|
);
|
|
6914
6929
|
}
|
|
6915
6930
|
if (!hasExplicitChart && result.messages.length === 0) {
|
|
@@ -8071,7 +8086,11 @@ function parseFlowchart(content, palette) {
|
|
|
8071
8086
|
const value = optMatch[2].trim();
|
|
8072
8087
|
if (key === "no-color") {
|
|
8073
8088
|
result.diagnostics.push(
|
|
8074
|
-
makeDgmoError(
|
|
8089
|
+
makeDgmoError(
|
|
8090
|
+
lineNumber,
|
|
8091
|
+
'"no-color" was removed \u2014 node colors are assigned automatically by shape; delete this line.',
|
|
8092
|
+
"warning"
|
|
8093
|
+
)
|
|
8075
8094
|
);
|
|
8076
8095
|
continue;
|
|
8077
8096
|
}
|
|
@@ -8400,7 +8419,11 @@ function parseState(content, palette) {
|
|
|
8400
8419
|
const value = optMatch[2].trim();
|
|
8401
8420
|
if (key === "no-color") {
|
|
8402
8421
|
result.diagnostics.push(
|
|
8403
|
-
makeDgmoError(
|
|
8422
|
+
makeDgmoError(
|
|
8423
|
+
lineNumber,
|
|
8424
|
+
'"no-color" was removed \u2014 state colors are assigned automatically; delete this line.',
|
|
8425
|
+
"warning"
|
|
8426
|
+
)
|
|
8404
8427
|
);
|
|
8405
8428
|
continue;
|
|
8406
8429
|
}
|
|
@@ -8715,7 +8738,7 @@ function parseClassDiagram(content, palette) {
|
|
|
8715
8738
|
result.diagnostics.push(
|
|
8716
8739
|
makeDgmoError(
|
|
8717
8740
|
lineNumber,
|
|
8718
|
-
'"no-auto-color"
|
|
8741
|
+
'"no-auto-color" was removed \u2014 colors are always auto-assigned from the palette; delete this line.',
|
|
8719
8742
|
"warning"
|
|
8720
8743
|
)
|
|
8721
8744
|
);
|
|
@@ -8830,7 +8853,11 @@ function parseClassDiagram(content, palette) {
|
|
|
8830
8853
|
continue;
|
|
8831
8854
|
}
|
|
8832
8855
|
result.diagnostics.push(
|
|
8833
|
-
makeDgmoError(
|
|
8856
|
+
makeDgmoError(
|
|
8857
|
+
lineNumber,
|
|
8858
|
+
`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)`,
|
|
8859
|
+
"warning"
|
|
8860
|
+
)
|
|
8834
8861
|
);
|
|
8835
8862
|
}
|
|
8836
8863
|
if (notes.length > 0) {
|
|
@@ -9308,7 +9335,11 @@ function parseERDiagram(content, palette) {
|
|
|
9308
9335
|
continue;
|
|
9309
9336
|
}
|
|
9310
9337
|
result.diagnostics.push(
|
|
9311
|
-
makeDgmoError(
|
|
9338
|
+
makeDgmoError(
|
|
9339
|
+
lineNumber,
|
|
9340
|
+
`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)`,
|
|
9341
|
+
"warning"
|
|
9342
|
+
)
|
|
9312
9343
|
);
|
|
9313
9344
|
}
|
|
9314
9345
|
if (result.tables.length === 0 && !result.error) {
|
|
@@ -9652,7 +9683,10 @@ function parseOrg(content, palette) {
|
|
|
9652
9683
|
const value = metadataMatch[2].trim();
|
|
9653
9684
|
const parent = findMetadataParent(indent, indentStack);
|
|
9654
9685
|
if (!parent) {
|
|
9655
|
-
pushError(
|
|
9686
|
+
pushError(
|
|
9687
|
+
lineNumber,
|
|
9688
|
+
"Metadata 'key: value' must be indented under a node \u2014 no node precedes it."
|
|
9689
|
+
);
|
|
9656
9690
|
} else {
|
|
9657
9691
|
parent.metadata = { ...parent.metadata, [key]: value };
|
|
9658
9692
|
}
|
|
@@ -9670,7 +9704,10 @@ function parseOrg(content, palette) {
|
|
|
9670
9704
|
);
|
|
9671
9705
|
attachNode(node, indent, indentStack, result);
|
|
9672
9706
|
} else {
|
|
9673
|
-
pushError(
|
|
9707
|
+
pushError(
|
|
9708
|
+
lineNumber,
|
|
9709
|
+
"Metadata 'key: value' must be indented under a node \u2014 no node precedes it."
|
|
9710
|
+
);
|
|
9674
9711
|
}
|
|
9675
9712
|
} else {
|
|
9676
9713
|
const node = parseNodeLabel(
|
|
@@ -10019,7 +10056,10 @@ function parseSitemap(content, palette) {
|
|
|
10019
10056
|
if (arrowInfo) {
|
|
10020
10057
|
const source = findParentNode(indent, indentStack);
|
|
10021
10058
|
if (!source) {
|
|
10022
|
-
pushError(
|
|
10059
|
+
pushError(
|
|
10060
|
+
lineNumber,
|
|
10061
|
+
"Arrow '-> target' must be indented under its source page \u2014 no page precedes it."
|
|
10062
|
+
);
|
|
10023
10063
|
} else {
|
|
10024
10064
|
deferredArrows.push({
|
|
10025
10065
|
sourceNode: source,
|
|
@@ -10089,7 +10129,10 @@ function parseSitemap(content, palette) {
|
|
|
10089
10129
|
const value = metadataMatch[2].trim();
|
|
10090
10130
|
const parent = findParentNode(indent, indentStack);
|
|
10091
10131
|
if (!parent) {
|
|
10092
|
-
pushError(
|
|
10132
|
+
pushError(
|
|
10133
|
+
lineNumber,
|
|
10134
|
+
"Metadata 'key: value' must be indented under a page \u2014 no page precedes it."
|
|
10135
|
+
);
|
|
10093
10136
|
} else {
|
|
10094
10137
|
parent.metadata = { ...parent.metadata, [key]: value };
|
|
10095
10138
|
}
|
|
@@ -10109,7 +10152,10 @@ function parseSitemap(content, palette) {
|
|
|
10109
10152
|
const key = normalizeName(node.label);
|
|
10110
10153
|
labelToNode.set(key, node);
|
|
10111
10154
|
} else {
|
|
10112
|
-
pushError(
|
|
10155
|
+
pushError(
|
|
10156
|
+
lineNumber,
|
|
10157
|
+
"Metadata 'key: value' must be indented under a page \u2014 no page precedes it."
|
|
10158
|
+
);
|
|
10113
10159
|
}
|
|
10114
10160
|
} else {
|
|
10115
10161
|
const descResult = tryStripDescriptionKeyword(trimmed);
|
|
@@ -11927,7 +11973,7 @@ function parseChart(content, palette) {
|
|
|
11927
11973
|
result.diagnostics.push(
|
|
11928
11974
|
makeDgmoError(
|
|
11929
11975
|
lineNumber,
|
|
11930
|
-
`'${trimmed}' \u2014 ##
|
|
11976
|
+
`'${trimmed}' removed \u2014 use a bracket container '[${trimmed.replace(/^#+\s*/, "")}]' instead (## headers are no longer supported).`
|
|
11931
11977
|
)
|
|
11932
11978
|
);
|
|
11933
11979
|
continue;
|
|
@@ -12919,7 +12965,11 @@ function parseExtendedChartFull(content, palette) {
|
|
|
12919
12965
|
continue;
|
|
12920
12966
|
}
|
|
12921
12967
|
result.diagnostics.push(
|
|
12922
|
-
makeDgmoError(
|
|
12968
|
+
makeDgmoError(
|
|
12969
|
+
lineNumber,
|
|
12970
|
+
`Unexpected line: '${trimmed}'. Expected a data row ('Label value', space-separated) or a known option.`,
|
|
12971
|
+
"warning"
|
|
12972
|
+
)
|
|
12923
12973
|
);
|
|
12924
12974
|
}
|
|
12925
12975
|
const warn = (line11, message) => {
|
|
@@ -15277,7 +15327,10 @@ function parseKanban(content, palette) {
|
|
|
15277
15327
|
continue;
|
|
15278
15328
|
}
|
|
15279
15329
|
if (!currentColumn) {
|
|
15280
|
-
warn(
|
|
15330
|
+
warn(
|
|
15331
|
+
lineNumber,
|
|
15332
|
+
"Card line found before any column. Declare a column first with '[Column Name]', then indent cards beneath it. (\xA711)"
|
|
15333
|
+
);
|
|
15281
15334
|
continue;
|
|
15282
15335
|
}
|
|
15283
15336
|
if (currentCard && indent > cardBaseIndent) {
|
|
@@ -15416,7 +15469,7 @@ var init_parser13 = __esm({
|
|
|
15416
15469
|
KNOWN_OPTIONS4 = /* @__PURE__ */ new Set(["hide", "active-tag"]);
|
|
15417
15470
|
KNOWN_BOOLEANS3 = /* @__PURE__ */ new Set(["solid-fill", "no-title"]);
|
|
15418
15471
|
REMOVED_BOOLEANS = {
|
|
15419
|
-
"no-auto-color": '"no-auto-color"
|
|
15472
|
+
"no-auto-color": '"no-auto-color" was removed \u2014 colors are always auto-assigned from the palette; delete this line.'
|
|
15420
15473
|
};
|
|
15421
15474
|
}
|
|
15422
15475
|
});
|
|
@@ -15653,7 +15706,7 @@ function parseC4(content, palette) {
|
|
|
15653
15706
|
} else {
|
|
15654
15707
|
pushError(
|
|
15655
15708
|
lineNumber,
|
|
15656
|
-
`"container ${refName}" must be
|
|
15709
|
+
`"container ${refName}" must be indented under a deployment node (e.g. under 'Prod is a deployment-node')`
|
|
15657
15710
|
);
|
|
15658
15711
|
}
|
|
15659
15712
|
continue;
|
|
@@ -15708,7 +15761,10 @@ function parseC4(content, palette) {
|
|
|
15708
15761
|
indent
|
|
15709
15762
|
});
|
|
15710
15763
|
} else {
|
|
15711
|
-
pushError(
|
|
15764
|
+
pushError(
|
|
15765
|
+
lineNumber,
|
|
15766
|
+
`"${sectionType}" must be indented under an element (e.g. under 'Web App is a container')`
|
|
15767
|
+
);
|
|
15712
15768
|
}
|
|
15713
15769
|
continue;
|
|
15714
15770
|
}
|
|
@@ -15735,7 +15791,10 @@ function parseC4(content, palette) {
|
|
|
15735
15791
|
indent
|
|
15736
15792
|
});
|
|
15737
15793
|
} else {
|
|
15738
|
-
pushError(
|
|
15794
|
+
pushError(
|
|
15795
|
+
lineNumber,
|
|
15796
|
+
`Group [${groupName}] must be indented under an element (e.g. under 'Web App is a container')`
|
|
15797
|
+
);
|
|
15739
15798
|
}
|
|
15740
15799
|
continue;
|
|
15741
15800
|
}
|
|
@@ -16065,7 +16124,10 @@ function parseC4(content, palette) {
|
|
|
16065
16124
|
}
|
|
16066
16125
|
desc.push(descResult.text);
|
|
16067
16126
|
} else {
|
|
16068
|
-
pushError(
|
|
16127
|
+
pushError(
|
|
16128
|
+
lineNumber,
|
|
16129
|
+
`Unexpected content: "${trimmed}". Expected an element ('Web App is a container'), a relationship ('-Uses-> Database'), indented metadata ('tech: React'), or a group ('[Backend]'). (\xA78)`
|
|
16130
|
+
);
|
|
16069
16131
|
}
|
|
16070
16132
|
}
|
|
16071
16133
|
finalizeAutoTagColors(result.tagGroups, palette);
|
|
@@ -16127,7 +16189,7 @@ function validateRelationshipTargets(result, knownNames, pushWarning) {
|
|
|
16127
16189
|
for (const el of elements) {
|
|
16128
16190
|
for (const rel of el.relationships) {
|
|
16129
16191
|
if (!knownNames.has(normalizeName(rel.target))) {
|
|
16130
|
-
let msg = `Relationship target "${rel.target}" not found`;
|
|
16192
|
+
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`;
|
|
16131
16193
|
const hint = suggest(normalizeName(rel.target), allNames);
|
|
16132
16194
|
if (hint) msg += `. ${hint}`;
|
|
16133
16195
|
pushWarning(rel.lineNumber, msg, "warning");
|
|
@@ -16155,7 +16217,7 @@ function validateDeploymentRefs(result, knownNames, pushWarning) {
|
|
|
16155
16217
|
for (const node of nodes) {
|
|
16156
16218
|
for (const ref of node.containerRefs) {
|
|
16157
16219
|
if (!knownNames.has(normalizeName(ref))) {
|
|
16158
|
-
let msg = `Deployment reference "container ${ref}" not found`;
|
|
16220
|
+
let msg = `Deployment reference "container ${ref}" not found \u2014 declare the container element first, then reference it under the deployment node`;
|
|
16159
16221
|
const hint = suggest(normalizeName(ref), allNames);
|
|
16160
16222
|
if (hint) msg += `. ${hint}`;
|
|
16161
16223
|
pushWarning(node.lineNumber, msg, "warning");
|
|
@@ -16874,7 +16936,7 @@ function parseInfra(content) {
|
|
|
16874
16936
|
}
|
|
16875
16937
|
warn(
|
|
16876
16938
|
lineNumber,
|
|
16877
|
-
`Invalid tag value '${trimmed}' in tag group '${currentTagGroup.name}'.`
|
|
16939
|
+
`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 '|'.`
|
|
16878
16940
|
);
|
|
16879
16941
|
continue;
|
|
16880
16942
|
}
|
|
@@ -16947,7 +17009,7 @@ function parseInfra(content) {
|
|
|
16947
17009
|
const n = deprecatedFanout[1];
|
|
16948
17010
|
setError(
|
|
16949
17011
|
lineNumber,
|
|
16950
|
-
`'x${n}' fanout syntax is no longer supported \u2014 use '
|
|
17012
|
+
`'x${n}' fanout syntax is no longer supported \u2014 use 'fanout: ${n}' instead`
|
|
16951
17013
|
);
|
|
16952
17014
|
continue;
|
|
16953
17015
|
}
|
|
@@ -17121,8 +17183,10 @@ function parseInfra(content) {
|
|
|
17121
17183
|
const hint = suggest(key, allKeys);
|
|
17122
17184
|
const valueLooksNumeric = /^[\d.]+%?$/.test(rawVal);
|
|
17123
17185
|
if (hint || valueLooksNumeric) {
|
|
17124
|
-
let msg = `Unknown property '${key}'.`;
|
|
17186
|
+
let msg = `Unknown infra property '${key}'.`;
|
|
17125
17187
|
if (hint) msg += ` ${hint}`;
|
|
17188
|
+
else
|
|
17189
|
+
msg += ` Properties are colon-keyed 'key: value' from the known schema (e.g. latency-ms, max-rps, cache-hit, instances, concurrency).`;
|
|
17126
17190
|
warn(lineNumber, msg);
|
|
17127
17191
|
} else if (!currentNode.isEdge) {
|
|
17128
17192
|
pushDescription(currentNode, trimmed);
|
|
@@ -17133,7 +17197,7 @@ function parseInfra(content) {
|
|
|
17133
17197
|
if (EDGE_ONLY_KEYS.has(key) && !currentNode.isEdge) {
|
|
17134
17198
|
warn(
|
|
17135
17199
|
lineNumber,
|
|
17136
|
-
`Property '${key}'
|
|
17200
|
+
`Property '${key}' belongs on the entry point \u2014 declare it indented under an 'internet' or 'edge' node, not on '${currentNode.label}'.`
|
|
17137
17201
|
);
|
|
17138
17202
|
}
|
|
17139
17203
|
const value = parsePropertyValue(rawVal);
|
|
@@ -17240,7 +17304,7 @@ function parseInfra(content) {
|
|
|
17240
17304
|
}
|
|
17241
17305
|
warn(
|
|
17242
17306
|
lineNumber,
|
|
17243
|
-
currentGroup ? `Unexpected line: '${trimmed}'.
|
|
17307
|
+
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'.`
|
|
17244
17308
|
);
|
|
17245
17309
|
}
|
|
17246
17310
|
finishCurrentNode();
|
|
@@ -17616,7 +17680,10 @@ function parseGantt(content, palette) {
|
|
|
17616
17680
|
continue;
|
|
17617
17681
|
}
|
|
17618
17682
|
if (COMMENT_RE.test(line11)) continue;
|
|
17619
|
-
warn(
|
|
17683
|
+
warn(
|
|
17684
|
+
lineNumber,
|
|
17685
|
+
`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)`
|
|
17686
|
+
);
|
|
17620
17687
|
continue;
|
|
17621
17688
|
}
|
|
17622
17689
|
}
|
|
@@ -17642,7 +17709,10 @@ function parseGantt(content, palette) {
|
|
|
17642
17709
|
lineNumber
|
|
17643
17710
|
});
|
|
17644
17711
|
} else {
|
|
17645
|
-
warn(
|
|
17712
|
+
warn(
|
|
17713
|
+
lineNumber,
|
|
17714
|
+
`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)`
|
|
17715
|
+
);
|
|
17646
17716
|
}
|
|
17647
17717
|
continue;
|
|
17648
17718
|
}
|
|
@@ -17668,7 +17738,10 @@ function parseGantt(content, palette) {
|
|
|
17668
17738
|
lineNumber
|
|
17669
17739
|
});
|
|
17670
17740
|
} else {
|
|
17671
|
-
warn(
|
|
17741
|
+
warn(
|
|
17742
|
+
lineNumber,
|
|
17743
|
+
`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)`
|
|
17744
|
+
);
|
|
17672
17745
|
}
|
|
17673
17746
|
continue;
|
|
17674
17747
|
}
|
|
@@ -17834,7 +17907,7 @@ function parseGantt(content, palette) {
|
|
|
17834
17907
|
} else {
|
|
17835
17908
|
softError(
|
|
17836
17909
|
lineNumber,
|
|
17837
|
-
`Arrow
|
|
17910
|
+
`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)`
|
|
17838
17911
|
);
|
|
17839
17912
|
}
|
|
17840
17913
|
}
|
|
@@ -19054,7 +19127,10 @@ function parseMap(content, palette) {
|
|
|
19054
19127
|
function handleTag(trimmed, line11) {
|
|
19055
19128
|
const m = matchTagBlockHeading(trimmed);
|
|
19056
19129
|
if (!m) {
|
|
19057
|
-
pushError(
|
|
19130
|
+
pushError(
|
|
19131
|
+
line11,
|
|
19132
|
+
`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.`
|
|
19133
|
+
);
|
|
19058
19134
|
return;
|
|
19059
19135
|
}
|
|
19060
19136
|
emitTagLegacyDiagnostic(m, line11, diagnostics);
|
|
@@ -19166,7 +19242,7 @@ function parseMap(content, palette) {
|
|
|
19166
19242
|
if (!pos || pos.kind === "name" && !pos.name) {
|
|
19167
19243
|
pushError(
|
|
19168
19244
|
line11,
|
|
19169
|
-
"route
|
|
19245
|
+
"route needs an origin place \u2014 `route <origin>` then indented legs (`-> dest`); origin may be a city name, IATA code, or `<lat> <lon>`. (\xA724B)"
|
|
19170
19246
|
);
|
|
19171
19247
|
return;
|
|
19172
19248
|
}
|
|
@@ -19229,7 +19305,10 @@ function parseMap(content, palette) {
|
|
|
19229
19305
|
function handleEdges(trimmed, line11) {
|
|
19230
19306
|
const parts = trimmed.split(ARROW_SPLIT);
|
|
19231
19307
|
if (parts.length < 3) {
|
|
19232
|
-
pushError(
|
|
19308
|
+
pushError(
|
|
19309
|
+
line11,
|
|
19310
|
+
`Malformed edge: "${trimmed}" \u2014 an edge is 'A -> B' (or 'A -label-> B', '~>' for arc, '--' undirected), both endpoints non-empty. (\xA724B)`
|
|
19311
|
+
);
|
|
19233
19312
|
return;
|
|
19234
19313
|
}
|
|
19235
19314
|
const endpoints = [];
|
|
@@ -19252,7 +19331,10 @@ function parseMap(content, palette) {
|
|
|
19252
19331
|
const from = endpoints[k];
|
|
19253
19332
|
const to = endpoints[k + 1];
|
|
19254
19333
|
if (!from || !to) {
|
|
19255
|
-
pushError(
|
|
19334
|
+
pushError(
|
|
19335
|
+
line11,
|
|
19336
|
+
`Edge has an empty endpoint: "${trimmed}" \u2014 both sides of the arrow need a place, e.g. 'Paris -> Berlin'. (\xA724B)`
|
|
19337
|
+
);
|
|
19256
19338
|
continue;
|
|
19257
19339
|
}
|
|
19258
19340
|
const isLast = k === links.length - 1;
|
|
@@ -21371,7 +21453,10 @@ function parseTechRadar(content) {
|
|
|
21371
21453
|
}
|
|
21372
21454
|
if (indent === 0 && trimmed.toLowerCase() === "rings") {
|
|
21373
21455
|
if (result.rings.length > 0) {
|
|
21374
|
-
warn(
|
|
21456
|
+
warn(
|
|
21457
|
+
lineNumber,
|
|
21458
|
+
'Duplicate "rings" block \u2014 only the last is kept; merge all ring names into one "rings" block.'
|
|
21459
|
+
);
|
|
21375
21460
|
result.rings = [];
|
|
21376
21461
|
}
|
|
21377
21462
|
inRingsBlock = true;
|
|
@@ -21590,7 +21675,7 @@ function parseTechRadar(content) {
|
|
|
21590
21675
|
result.diagnostics.push(
|
|
21591
21676
|
makeDgmoError(
|
|
21592
21677
|
lineNumber,
|
|
21593
|
-
`Blip "${trimmed}" has no ring
|
|
21678
|
+
`Blip "${trimmed}" has no ring. Put it under a ring section header, or add a colon-keyed ring \u2014 '${trimmed} ring: RingName' (per \xA720).`
|
|
21594
21679
|
)
|
|
21595
21680
|
);
|
|
21596
21681
|
continue;
|
|
@@ -21599,7 +21684,7 @@ function parseTechRadar(content) {
|
|
|
21599
21684
|
if (!trimmed.includes("|") && headerParsed && result.rings.length > 0) {
|
|
21600
21685
|
warn(
|
|
21601
21686
|
lineNumber,
|
|
21602
|
-
`Unrecognized line "${trimmed}".
|
|
21687
|
+
`Unrecognized line "${trimmed}". A quadrant header is 'Name quadrant: <top-left|top-right|bottom-left|bottom-right>' (per \xA720).`
|
|
21603
21688
|
);
|
|
21604
21689
|
}
|
|
21605
21690
|
}
|
|
@@ -21892,7 +21977,10 @@ function parseCycle(content) {
|
|
|
21892
21977
|
currentNode.description.push(descLine);
|
|
21893
21978
|
continue;
|
|
21894
21979
|
}
|
|
21895
|
-
warn(
|
|
21980
|
+
warn(
|
|
21981
|
+
lineNum,
|
|
21982
|
+
`Indented line "${trimmed}" has no step above it \u2014 add a step on a non-indented line first, then indent its details. (\xA721)`
|
|
21983
|
+
);
|
|
21896
21984
|
continue;
|
|
21897
21985
|
}
|
|
21898
21986
|
}
|
|
@@ -22195,7 +22283,7 @@ function parseJourneyMap(content, palette) {
|
|
|
22195
22283
|
if (trimmed.includes("|") || !PHASE_RE.test(trimmed)) {
|
|
22196
22284
|
warn(
|
|
22197
22285
|
lineNumber,
|
|
22198
|
-
"
|
|
22286
|
+
`Step "${trimmed}" sits outside any phase and is ignored \u2014 indent it under a '[Phase]' header (per \xA722).`
|
|
22199
22287
|
);
|
|
22200
22288
|
continue;
|
|
22201
22289
|
}
|
|
@@ -22252,7 +22340,10 @@ function parseJourneyMap(content, palette) {
|
|
|
22252
22340
|
continue;
|
|
22253
22341
|
}
|
|
22254
22342
|
if (indent > 0 && !currentPhase && hasPhases) {
|
|
22255
|
-
warn(
|
|
22343
|
+
warn(
|
|
22344
|
+
lineNumber,
|
|
22345
|
+
`Indented line outside any phase \u2014 add a '[Phase]' header above it, or unindent it to a top-level step. (\xA722)`
|
|
22346
|
+
);
|
|
22256
22347
|
}
|
|
22257
22348
|
}
|
|
22258
22349
|
if (currentStep) {
|
|
@@ -22598,7 +22689,10 @@ function parsePyramid(content) {
|
|
|
22598
22689
|
continue;
|
|
22599
22690
|
}
|
|
22600
22691
|
if (!currentLayer) {
|
|
22601
|
-
warn(
|
|
22692
|
+
warn(
|
|
22693
|
+
lineNum,
|
|
22694
|
+
`Indented description "${trimmed}" has no layer above it \u2014 add a layer name on a non-indented line first. (\xA723)`
|
|
22695
|
+
);
|
|
22602
22696
|
continue;
|
|
22603
22697
|
}
|
|
22604
22698
|
const descLine = trimmed.startsWith("- ") ? `\u2022 ${trimmed.substring(2)}` : trimmed;
|
|
@@ -22772,7 +22866,10 @@ function parseRing(content) {
|
|
|
22772
22866
|
continue;
|
|
22773
22867
|
}
|
|
22774
22868
|
if (!currentLayer) {
|
|
22775
|
-
warn(
|
|
22869
|
+
warn(
|
|
22870
|
+
lineNum,
|
|
22871
|
+
`Indented description "${trimmed}" has no layer above it \u2014 add a layer name on a non-indented line first. (\xA724)`
|
|
22872
|
+
);
|
|
22776
22873
|
continue;
|
|
22777
22874
|
}
|
|
22778
22875
|
const descLine = trimmed.startsWith("- ") ? `\u2022 ${trimmed.substring(2)}` : trimmed;
|
|
@@ -23498,7 +23595,10 @@ function parseRaci(content, palette) {
|
|
|
23498
23595
|
continue;
|
|
23499
23596
|
}
|
|
23500
23597
|
if (bodyStarted) {
|
|
23501
|
-
errorAt(
|
|
23598
|
+
errorAt(
|
|
23599
|
+
lineNumber,
|
|
23600
|
+
`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)`
|
|
23601
|
+
);
|
|
23502
23602
|
} else {
|
|
23503
23603
|
warn(lineNumber, `Unrecognized directive: '${trimmed}'.`);
|
|
23504
23604
|
}
|
|
@@ -24045,6 +24145,13 @@ function getAllChartTypes() {
|
|
|
24045
24145
|
return chartTypes.map((c) => c.id);
|
|
24046
24146
|
}
|
|
24047
24147
|
function parseDgmo(content) {
|
|
24148
|
+
const result = parseDgmoUndeduped(content);
|
|
24149
|
+
return {
|
|
24150
|
+
diagnostics: dedupeDiagnostics(result.diagnostics),
|
|
24151
|
+
chartType: result.chartType
|
|
24152
|
+
};
|
|
24153
|
+
}
|
|
24154
|
+
function parseDgmoUndeduped(content) {
|
|
24048
24155
|
const chartType = parseDgmoChartType(content);
|
|
24049
24156
|
if (!chartType) {
|
|
24050
24157
|
const colonDiag = detectColonChartType(content);
|
|
@@ -51685,7 +51792,7 @@ function resolveMap(parsed, data) {
|
|
|
51685
51792
|
const hint = suggest(r.name, allNames);
|
|
51686
51793
|
err(
|
|
51687
51794
|
r.lineNumber,
|
|
51688
|
-
`Unknown
|
|
51795
|
+
`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.`,
|
|
51689
51796
|
"E_MAP_UNKNOWN_SUBDIVISION"
|
|
51690
51797
|
);
|
|
51691
51798
|
continue;
|
|
@@ -51765,7 +51872,7 @@ function resolveMap(parsed, data) {
|
|
|
51765
51872
|
const hint = suggest(name, cityNames);
|
|
51766
51873
|
err(
|
|
51767
51874
|
line11,
|
|
51768
|
-
`Unknown place "${name}"
|
|
51875
|
+
`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>\`.`,
|
|
51769
51876
|
"E_MAP_UNKNOWN_PLACE"
|
|
51770
51877
|
);
|
|
51771
51878
|
return { kind: "miss" };
|
|
@@ -52307,6 +52414,21 @@ function mapLegendBand(legend, opts) {
|
|
|
52307
52414
|
if (height <= 0) return 0;
|
|
52308
52415
|
return mapLegendTop(opts.hasTitle, opts.hasSubtitle) + height + LEGEND_BOTTOM_GAP2;
|
|
52309
52416
|
}
|
|
52417
|
+
function mapLegendBox(legend, opts) {
|
|
52418
|
+
if (!legend) return null;
|
|
52419
|
+
const groups = mapLegendGroups(legend);
|
|
52420
|
+
if (groups.length === 0) return null;
|
|
52421
|
+
const config = mapLegendConfig(groups, opts.mode);
|
|
52422
|
+
const state = { activeGroup: legend.activeGroup };
|
|
52423
|
+
const { width, height } = computeLegendLayout(config, state, opts.width);
|
|
52424
|
+
if (height <= 0 || width <= 0) return null;
|
|
52425
|
+
return {
|
|
52426
|
+
x: (opts.width - width) / 2,
|
|
52427
|
+
y: mapLegendTop(opts.hasTitle, opts.hasSubtitle),
|
|
52428
|
+
width,
|
|
52429
|
+
height
|
|
52430
|
+
};
|
|
52431
|
+
}
|
|
52310
52432
|
var LEGEND_TOP_GAP2, LEGEND_BOTTOM_GAP2;
|
|
52311
52433
|
var init_legend_band = __esm({
|
|
52312
52434
|
"src/map/legend-band.ts"() {
|
|
@@ -52431,6 +52553,8 @@ function placeContextLabels(args) {
|
|
|
52431
52553
|
waterBodies,
|
|
52432
52554
|
countries,
|
|
52433
52555
|
palette,
|
|
52556
|
+
countryTone,
|
|
52557
|
+
waterTone,
|
|
52434
52558
|
project,
|
|
52435
52559
|
collides,
|
|
52436
52560
|
contentPoints,
|
|
@@ -52440,8 +52564,8 @@ function placeContextLabels(args) {
|
|
|
52440
52564
|
const band = tierBand(Math.max(dLonSpan, dLatSpan));
|
|
52441
52565
|
const budget = labelBudget(width, height, band);
|
|
52442
52566
|
if (budget <= 0) return [];
|
|
52443
|
-
const waterColor = mix(palette.colors.blue, palette.textMuted, 50);
|
|
52444
|
-
const countryColor = palette.textMuted;
|
|
52567
|
+
const waterColor = waterTone ?? mix(palette.colors.blue, palette.textMuted, 50);
|
|
52568
|
+
const countryColor = countryTone ?? palette.textMuted;
|
|
52445
52569
|
const haloColor = palette.bg;
|
|
52446
52570
|
const candidates = [];
|
|
52447
52571
|
const center = [width / 2, height / 2];
|
|
@@ -52530,8 +52654,7 @@ function placeContextLabels(args) {
|
|
|
52530
52654
|
)
|
|
52531
52655
|
);
|
|
52532
52656
|
const fontSize = Math.round(FONT + t * (COUNTRY_FONT_MAX - FONT));
|
|
52533
|
-
const
|
|
52534
|
-
const color = fade > 0 ? mix(countryColor, palette.bg, 100 - fade) : countryColor;
|
|
52657
|
+
const color = countryColor;
|
|
52535
52658
|
const text = c.name;
|
|
52536
52659
|
const tw = labelWidth(text, 0, fontSize);
|
|
52537
52660
|
if (tw > w || fontSize + 2 * PADY > h) continue;
|
|
@@ -52625,7 +52748,7 @@ function placeContextLabels(args) {
|
|
|
52625
52748
|
}
|
|
52626
52749
|
return placed;
|
|
52627
52750
|
}
|
|
52628
|
-
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,
|
|
52751
|
+
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;
|
|
52629
52752
|
var init_context_labels = __esm({
|
|
52630
52753
|
"src/map/context-labels.ts"() {
|
|
52631
52754
|
"use strict";
|
|
@@ -52642,7 +52765,6 @@ var init_context_labels = __esm({
|
|
|
52642
52765
|
COUNTRY_FONT_MAX = 22;
|
|
52643
52766
|
COUNTRY_SIZE_FRAC_MIN = 0.06;
|
|
52644
52767
|
COUNTRY_SIZE_FRAC_MAX = 0.32;
|
|
52645
|
-
COUNTRY_FADE_MAX = 45;
|
|
52646
52768
|
MAX_COUNTRY_POSITIONS = 4;
|
|
52647
52769
|
COUNTRY_POS_GRID = 5;
|
|
52648
52770
|
COUNTRY_POS_TOPN_MARGIN = 3;
|
|
@@ -52780,36 +52902,23 @@ function countryLabelPositions(args) {
|
|
|
52780
52902
|
return n;
|
|
52781
52903
|
};
|
|
52782
52904
|
const dist2ToCentre = (c) => (c.sx - cx) ** 2 + (c.sy - cy) ** 2;
|
|
52783
|
-
const
|
|
52784
|
-
|
|
52785
|
-
|
|
52786
|
-
|
|
52787
|
-
|
|
52788
|
-
|
|
52789
|
-
|
|
52790
|
-
let bestIdx = 0;
|
|
52791
|
-
let bestMin = -1;
|
|
52792
|
-
for (let k = 0; k < pool.length; k++) {
|
|
52793
|
-
const c = pool[k];
|
|
52794
|
-
let minD = Infinity;
|
|
52795
|
-
for (const o of ordered) {
|
|
52796
|
-
const d = (c.sx - o.sx) ** 2 + (c.sy - o.sy) ** 2;
|
|
52797
|
-
if (d < minD) minD = d;
|
|
52798
|
-
}
|
|
52799
|
-
if (minD > bestMin) {
|
|
52800
|
-
bestMin = minD;
|
|
52801
|
-
bestIdx = k;
|
|
52802
|
-
}
|
|
52905
|
+
const centreLon = kept.reduce((s, c) => s + c.lon, 0) / kept.length;
|
|
52906
|
+
const centreLat = kept.reduce((s, c) => s + c.lat, 0) / kept.length;
|
|
52907
|
+
const centreScreen = project(centreLon, centreLat);
|
|
52908
|
+
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 ? [
|
|
52909
|
+
{
|
|
52910
|
+
lonLat: [centreLon, centreLat],
|
|
52911
|
+
screen: [centreScreen[0], centreScreen[1]]
|
|
52803
52912
|
}
|
|
52804
|
-
|
|
52805
|
-
|
|
52806
|
-
|
|
52913
|
+
] : [];
|
|
52914
|
+
const grid = [...kept].sort(
|
|
52915
|
+
(a, b) => interiorness(b) - interiorness(a) || dist2ToCentre(a) - dist2ToCentre(b)
|
|
52916
|
+
).map((c) => ({
|
|
52807
52917
|
lonLat: [c.lon, c.lat],
|
|
52808
52918
|
screen: [c.sx, c.sy]
|
|
52809
52919
|
}));
|
|
52810
52920
|
const curatedPos = curated ? mkCurated(curated, project) : [];
|
|
52811
|
-
|
|
52812
|
-
return out;
|
|
52921
|
+
return [...curatedPos, ...lead, ...grid].slice(0, MAX_COUNTRY_POSITIONS);
|
|
52813
52922
|
}
|
|
52814
52923
|
function mkCurated(curated, project) {
|
|
52815
52924
|
if (!curated) return [];
|
|
@@ -53075,6 +53184,25 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
53075
53184
|
palette.bg,
|
|
53076
53185
|
mutedBasemap ? isDark ? MUTED_FOREIGN_DARK : MUTED_FOREIGN_LIGHT : isDark ? FOREIGN_TINT_DARK : FOREIGN_TINT_LIGHT
|
|
53077
53186
|
);
|
|
53187
|
+
const contrastFloorTone = (tone, ...substrates) => {
|
|
53188
|
+
const clears = (t) => substrates.every((s) => contrastRatio(t, s) >= REGION_LABEL_HALO_RATIO);
|
|
53189
|
+
if (clears(tone)) return tone;
|
|
53190
|
+
for (let s = 10; s <= 100; s += 10) {
|
|
53191
|
+
const t = mix(palette.text, tone, s);
|
|
53192
|
+
if (clears(t)) return t;
|
|
53193
|
+
}
|
|
53194
|
+
return palette.text;
|
|
53195
|
+
};
|
|
53196
|
+
const backdropLandTone = contrastFloorTone(
|
|
53197
|
+
palette.textMuted,
|
|
53198
|
+
neutralFill,
|
|
53199
|
+
water
|
|
53200
|
+
);
|
|
53201
|
+
const backdropWaterTone = contrastFloorTone(
|
|
53202
|
+
mix(palette.colors.blue, palette.textMuted, 50),
|
|
53203
|
+
water,
|
|
53204
|
+
neutralFill
|
|
53205
|
+
);
|
|
53078
53206
|
const hasDirectColor = resolved.regions.some((r) => r.color !== void 0);
|
|
53079
53207
|
const colorizeActive = resolved.directives.noColorize !== true && !hasRamp && !hasDirectColor && fillGroupNames.size === 0;
|
|
53080
53208
|
const colorByIso = /* @__PURE__ */ new Map();
|
|
@@ -53189,6 +53317,33 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
53189
53317
|
hasSubtitle: Boolean(resolved.subtitle)
|
|
53190
53318
|
});
|
|
53191
53319
|
if (legendBand > topPad) topPad = legendBand;
|
|
53320
|
+
const topReserved = [];
|
|
53321
|
+
if (shownTitle) {
|
|
53322
|
+
const lines = resolved.subtitle ? 2 : 1;
|
|
53323
|
+
const tw = Math.max(
|
|
53324
|
+
measureLegendText(shownTitle, TITLE_FONT_SIZE),
|
|
53325
|
+
resolved.subtitle ? measureLegendText(resolved.subtitle, TITLE_FONT_SIZE) : 0
|
|
53326
|
+
) + 2 * TITLE_FONT_SIZE;
|
|
53327
|
+
topReserved.push({
|
|
53328
|
+
x: width / 2 - tw / 2,
|
|
53329
|
+
y: TITLE_Y - TITLE_FONT_SIZE,
|
|
53330
|
+
w: tw,
|
|
53331
|
+
h: TITLE_FONT_SIZE * (lines + 0.5)
|
|
53332
|
+
});
|
|
53333
|
+
}
|
|
53334
|
+
const legendBox = mapLegendBox(legend, {
|
|
53335
|
+
width,
|
|
53336
|
+
mode: opts.legendMode ?? "preview",
|
|
53337
|
+
hasTitle: Boolean(shownTitle),
|
|
53338
|
+
hasSubtitle: Boolean(resolved.subtitle)
|
|
53339
|
+
});
|
|
53340
|
+
if (legendBox)
|
|
53341
|
+
topReserved.push({
|
|
53342
|
+
x: legendBox.x,
|
|
53343
|
+
y: legendBox.y,
|
|
53344
|
+
w: legendBox.width,
|
|
53345
|
+
h: legendBox.height
|
|
53346
|
+
});
|
|
53192
53347
|
const reserve = opts._calloutReserve;
|
|
53193
53348
|
const fitLeft = FIT_PAD + (reserve?.left ?? 0);
|
|
53194
53349
|
const fitRight = width - FIT_PAD - (reserve?.right ?? 0);
|
|
@@ -53918,6 +54073,19 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
53918
54073
|
const by = b.cy - (b.cy - py) / tb * trimB;
|
|
53919
54074
|
return `M${ax},${ay}Q${px},${py} ${bx},${by}`;
|
|
53920
54075
|
};
|
|
54076
|
+
const legLabelPoint = (a, b, curved, offset) => {
|
|
54077
|
+
const mx = (a.cx + b.cx) / 2;
|
|
54078
|
+
const my = (a.cy + b.cy) / 2;
|
|
54079
|
+
if (!curved && offset === 0) return { x: mx, y: my - 4 };
|
|
54080
|
+
const dx = b.cx - a.cx;
|
|
54081
|
+
const dy = b.cy - a.cy;
|
|
54082
|
+
const len = Math.hypot(dx, dy) || 1;
|
|
54083
|
+
const nx = -dy / len;
|
|
54084
|
+
const ny = dx / len;
|
|
54085
|
+
const bow = offset !== 0 ? offset : len * ARC_CURVE_FRAC;
|
|
54086
|
+
const off = bow * 0.5 + Math.sign(bow || 1) * 8;
|
|
54087
|
+
return { x: mx + nx * off, y: my + ny * off };
|
|
54088
|
+
};
|
|
53921
54089
|
const routeLegVals = resolved.routes.flatMap((rt) => rt.legs).map((l) => Number(l.value)).filter((n) => Number.isFinite(n) && n > 0);
|
|
53922
54090
|
const rlMin = routeLegVals.length ? Math.min(...routeLegVals) : 0;
|
|
53923
54091
|
const rlMax = routeLegVals.length ? Math.max(...routeLegVals) : 0;
|
|
@@ -53931,13 +54099,12 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
53931
54099
|
const a = poiScreen.get(leg.fromId);
|
|
53932
54100
|
const b = poiScreen.get(leg.toId);
|
|
53933
54101
|
if (!a || !b) continue;
|
|
53934
|
-
const
|
|
53935
|
-
const my = (a.cy + b.cy) / 2;
|
|
54102
|
+
const lp = legLabelPoint(a, b, leg.style === "arc", 0);
|
|
53936
54103
|
const bow = {
|
|
53937
54104
|
curved: leg.style === "arc",
|
|
53938
54105
|
offset: 0,
|
|
53939
|
-
labelX:
|
|
53940
|
-
labelY:
|
|
54106
|
+
labelX: lp.x,
|
|
54107
|
+
labelY: lp.y
|
|
53941
54108
|
};
|
|
53942
54109
|
const routeLabelStyle = leg.label !== void 0 ? labelOnFill(fillAt(bow.labelX, bow.labelY)) : void 0;
|
|
53943
54110
|
legs.push({
|
|
@@ -53984,13 +54151,13 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
53984
54151
|
const b = poiScreen.get(e.toId);
|
|
53985
54152
|
if (!a || !b) return;
|
|
53986
54153
|
const fanOffset = n > 1 ? (i - (n - 1) / 2) * FAN_STEP : 0;
|
|
53987
|
-
const
|
|
53988
|
-
const
|
|
54154
|
+
const curved = e.style === "arc" || n > 1;
|
|
54155
|
+
const lp = legLabelPoint(a, b, curved, fanOffset);
|
|
53989
54156
|
const bow = {
|
|
53990
|
-
curved
|
|
54157
|
+
curved,
|
|
53991
54158
|
offset: fanOffset,
|
|
53992
|
-
labelX:
|
|
53993
|
-
labelY:
|
|
54159
|
+
labelX: lp.x,
|
|
54160
|
+
labelY: lp.y
|
|
53994
54161
|
};
|
|
53995
54162
|
const edgeLabelStyle = e.label !== void 0 ? labelOnFill(fillAt(bow.labelX, bow.labelY)) : void 0;
|
|
53996
54163
|
legs.push({
|
|
@@ -54014,7 +54181,7 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54014
54181
|
});
|
|
54015
54182
|
}
|
|
54016
54183
|
const labels = [];
|
|
54017
|
-
const obstacles = [];
|
|
54184
|
+
const obstacles = [...topReserved];
|
|
54018
54185
|
const regionLabelGuards = [];
|
|
54019
54186
|
const markers = pois.map((p) => ({
|
|
54020
54187
|
cx: p.cx,
|
|
@@ -54052,6 +54219,7 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54052
54219
|
}
|
|
54053
54220
|
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));
|
|
54054
54221
|
const showRegionLabels = resolved.directives.noRegionLabels !== true;
|
|
54222
|
+
const labeledRegionIds = /* @__PURE__ */ new Set();
|
|
54055
54223
|
const showRegionValues = resolved.directives.noRegionValue !== true && activeIsScore;
|
|
54056
54224
|
const regionValueStr = (value) => showRegionValues && value !== void 0 ? compactNumber(value) : void 0;
|
|
54057
54225
|
const isCompact = width < COMPACT_WIDTH_PX;
|
|
@@ -54072,7 +54240,9 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54072
54240
|
const REGION_FONT_MAX_ORIENT = 22;
|
|
54073
54241
|
const REGION_SIZE_FRAC_MIN = 0.06;
|
|
54074
54242
|
const REGION_SIZE_FRAC_MAX = 0.32;
|
|
54075
|
-
const
|
|
54243
|
+
const SUBJECT_FONT_MAX = 18;
|
|
54244
|
+
const SUBJECT_MIN_PROMINENCE = 13;
|
|
54245
|
+
const SUBJECT_LEADER_FONT = 15;
|
|
54076
54246
|
const canvasLinear = Math.sqrt(Math.max(1, width * height));
|
|
54077
54247
|
const sizeT = (boxW, boxH) => {
|
|
54078
54248
|
const frac = Math.sqrt(Math.max(0, boxW * boxH)) / canvasLinear;
|
|
@@ -54084,9 +54254,9 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54084
54254
|
)
|
|
54085
54255
|
);
|
|
54086
54256
|
};
|
|
54087
|
-
const pushRegionLabel = (x, y, text, fill2, lineNumber, valueLine, fontSize = FONT2,
|
|
54257
|
+
const pushRegionLabel = (x, y, text, fill2, lineNumber, valueLine, fontSize = FONT2, colorOverride) => {
|
|
54088
54258
|
const { color: baseColor, haloColor } = labelOnFill(fill2);
|
|
54089
|
-
const color =
|
|
54259
|
+
const color = colorOverride ?? baseColor;
|
|
54090
54260
|
const vf = Math.round(fontSize * 0.82);
|
|
54091
54261
|
const halfW = Math.max(
|
|
54092
54262
|
measureLegendText(text, fontSize),
|
|
@@ -54101,7 +54271,11 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54101
54271
|
text,
|
|
54102
54272
|
anchor: "middle",
|
|
54103
54273
|
color,
|
|
54104
|
-
|
|
54274
|
+
// A backdrop label (colorOverride) NEVER haloes: the placement gate above
|
|
54275
|
+
// guarantees it sits on a floored-readable substrate (own fill, neutral
|
|
54276
|
+
// land, foreign land, or water), so a halo is pure noise. Data labels keep
|
|
54277
|
+
// the containment-gated halo until the role-tier pass (Phase 3).
|
|
54278
|
+
halo: colorOverride ? false : overflows,
|
|
54105
54279
|
haloColor,
|
|
54106
54280
|
...fontSize !== FONT2 && { fontSize },
|
|
54107
54281
|
...valueLine !== void 0 && { valueLine },
|
|
@@ -54137,7 +54311,7 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54137
54311
|
if (!c || !Number.isFinite(c[0])) return null;
|
|
54138
54312
|
return { r, c, boxW, boxH, area: boxW * boxH, candidates };
|
|
54139
54313
|
}).filter((e) => e !== null).sort((a, b) => b.area - a.area || a.r.lineNumber - b.r.lineNumber);
|
|
54140
|
-
const placedRegionRects = [];
|
|
54314
|
+
const placedRegionRects = [...topReserved];
|
|
54141
54315
|
const placedLeaders = [];
|
|
54142
54316
|
const isEmptyFill = (f) => f === water || f === neutralFill || f === foreignFill;
|
|
54143
54317
|
const POI_LABEL_PAD = 14;
|
|
@@ -54150,9 +54324,9 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54150
54324
|
const SHORT_HOP_MAX = Math.max(46, Math.min(width, height) * 0.11);
|
|
54151
54325
|
const STEP = 4;
|
|
54152
54326
|
const HOP_GAP = 9;
|
|
54153
|
-
const tryShortHopCallout = (cx, cy, fill2, name, value) => {
|
|
54154
|
-
const chipW = stackW(name, value);
|
|
54155
|
-
const chipH = stackH(value !== void 0);
|
|
54327
|
+
const tryShortHopCallout = (cx, cy, fill2, name, value, font = FONT2, gap = HOP_GAP, maxLen = SHORT_HOP_MAX) => {
|
|
54328
|
+
const chipW = stackW(name, value, font);
|
|
54329
|
+
const chipH = stackH(value !== void 0, font);
|
|
54156
54330
|
const dirs = [
|
|
54157
54331
|
[0, -1],
|
|
54158
54332
|
// north (over Canada)
|
|
@@ -54168,7 +54342,7 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54168
54342
|
let ex = cx;
|
|
54169
54343
|
let ey = cy;
|
|
54170
54344
|
let steps = 0;
|
|
54171
|
-
const maxSteps = Math.ceil(
|
|
54345
|
+
const maxSteps = Math.ceil(maxLen / STEP) + 1;
|
|
54172
54346
|
while (steps < maxSteps && fillAt(ex, ey) === fill2) {
|
|
54173
54347
|
ex += dx * STEP;
|
|
54174
54348
|
ey += dy * STEP;
|
|
@@ -54176,8 +54350,8 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54176
54350
|
}
|
|
54177
54351
|
if (fillAt(ex, ey) === fill2) continue;
|
|
54178
54352
|
const halfAlong = (Math.abs(dx) * chipW + Math.abs(dy) * chipH) / 2;
|
|
54179
|
-
const ccx = ex + dx * (
|
|
54180
|
-
const ccy = ey + dy * (
|
|
54353
|
+
const ccx = ex + dx * (gap + halfAlong);
|
|
54354
|
+
const ccy = ey + dy * (gap + halfAlong);
|
|
54181
54355
|
const rect = {
|
|
54182
54356
|
x: ccx - chipW / 2,
|
|
54183
54357
|
y: ccy - chipH / 2,
|
|
@@ -54202,7 +54376,7 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54202
54376
|
const innerX = ccx - dx * (chipW / 2);
|
|
54203
54377
|
const innerY = ccy - dy * (chipH / 2);
|
|
54204
54378
|
const len = Math.hypot(innerX - cx, innerY - cy);
|
|
54205
|
-
if (len >
|
|
54379
|
+
if (len > maxLen) continue;
|
|
54206
54380
|
if (placedLeaders.some(
|
|
54207
54381
|
(l) => segmentsCross(cx, cy, innerX, innerY, l[0], l[1], l[2], l[3])
|
|
54208
54382
|
))
|
|
@@ -54226,6 +54400,78 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54226
54400
|
const valStr = regionValueStr(r.value);
|
|
54227
54401
|
const fitsRegions = (rect) => !placedRegionRects.some((p) => rectsOverlap(rect, p));
|
|
54228
54402
|
const fitsPois = (rect) => !poiObstacles.some((o) => rectsOverlap(rect, o));
|
|
54403
|
+
const isSubject = regionById.has(r.id);
|
|
54404
|
+
const extremesOnFill = (ax, ay, text) => {
|
|
54405
|
+
const halfW = measureLegendText(text, FONT2) / 2;
|
|
54406
|
+
return fillAt(ax - halfW, ay) === r.fill && fillAt(ax + halfW, ay) === r.fill;
|
|
54407
|
+
};
|
|
54408
|
+
if (isSubject && valStr === void 0 && r.label !== void 0) {
|
|
54409
|
+
const name = candidates[0];
|
|
54410
|
+
let best = -1;
|
|
54411
|
+
for (let f = SUBJECT_FONT_MAX; f >= FONT2; f--) {
|
|
54412
|
+
if (measureLegendText(name, f) > boxW || f + 2 * LABEL_PADY > boxH)
|
|
54413
|
+
continue;
|
|
54414
|
+
const rect = regionLabelRect(c[0], c[1], name, void 0, f);
|
|
54415
|
+
if (!fitsRegions(rect) || !fitsPois(rect) || collides(rect)) continue;
|
|
54416
|
+
const halfW = measureLegendText(name, f) / 2;
|
|
54417
|
+
if (fillAt(c[0] - halfW, c[1]) !== r.fill || fillAt(c[0] + halfW, c[1]) !== r.fill)
|
|
54418
|
+
continue;
|
|
54419
|
+
best = f;
|
|
54420
|
+
break;
|
|
54421
|
+
}
|
|
54422
|
+
if (best >= SUBJECT_MIN_PROMINENCE) {
|
|
54423
|
+
const rect = regionLabelRect(c[0], c[1], name, void 0, best);
|
|
54424
|
+
placedRegionRects.push(rect);
|
|
54425
|
+
pushRegionLabel(
|
|
54426
|
+
c[0],
|
|
54427
|
+
c[1],
|
|
54428
|
+
name,
|
|
54429
|
+
r.fill,
|
|
54430
|
+
r.lineNumber,
|
|
54431
|
+
void 0,
|
|
54432
|
+
best
|
|
54433
|
+
);
|
|
54434
|
+
labeledRegionIds.add(r.id);
|
|
54435
|
+
regionLabelGuards.push({ label: labels[labels.length - 1], rect });
|
|
54436
|
+
} else {
|
|
54437
|
+
const hop = tryShortHopCallout(
|
|
54438
|
+
c[0],
|
|
54439
|
+
c[1],
|
|
54440
|
+
r.fill,
|
|
54441
|
+
r.label,
|
|
54442
|
+
void 0,
|
|
54443
|
+
SUBJECT_LEADER_FONT,
|
|
54444
|
+
HOP_GAP + SUBJECT_LEADER_FONT,
|
|
54445
|
+
SHORT_HOP_MAX * 2.2
|
|
54446
|
+
);
|
|
54447
|
+
if (hop) {
|
|
54448
|
+
placedRegionRects.push(hop.rect);
|
|
54449
|
+
placedLeaders.push(hop.leader);
|
|
54450
|
+
const dark = mix(r.fill, palette.text, 60);
|
|
54451
|
+
labels.push({
|
|
54452
|
+
x: hop.x,
|
|
54453
|
+
y: hop.y,
|
|
54454
|
+
text: r.label,
|
|
54455
|
+
anchor: "middle",
|
|
54456
|
+
color: palette.text,
|
|
54457
|
+
halo: false,
|
|
54458
|
+
haloColor: palette.bg,
|
|
54459
|
+
fontSize: SUBJECT_LEADER_FONT,
|
|
54460
|
+
leader: {
|
|
54461
|
+
x1: hop.leader[0],
|
|
54462
|
+
y1: hop.leader[1],
|
|
54463
|
+
x2: hop.leader[2],
|
|
54464
|
+
y2: hop.leader[3]
|
|
54465
|
+
},
|
|
54466
|
+
leaderColor: dark,
|
|
54467
|
+
calloutDot: { x: c[0], y: c[1], color: dark },
|
|
54468
|
+
lineNumber: r.lineNumber
|
|
54469
|
+
});
|
|
54470
|
+
labeledRegionIds.add(r.id);
|
|
54471
|
+
}
|
|
54472
|
+
}
|
|
54473
|
+
continue;
|
|
54474
|
+
}
|
|
54229
54475
|
const seekAnchors = [
|
|
54230
54476
|
{ x: c[0], y: c[1], guard: false }
|
|
54231
54477
|
];
|
|
@@ -54248,13 +54494,13 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54248
54494
|
const nameRect = regionLabelRect(a.x, a.y, t);
|
|
54249
54495
|
if (valStr && stackW(t, valStr) <= boxW && stackH(true) <= boxH) {
|
|
54250
54496
|
const stackRect = regionLabelRect(a.x, a.y, t, valStr);
|
|
54251
|
-
if (fitsRegions(stackRect) && fitsPois(nameRect)) {
|
|
54497
|
+
if (fitsRegions(stackRect) && fitsPois(nameRect) && extremesOnFill(a.x, a.y, t)) {
|
|
54252
54498
|
chosen = { text: t, valueLine: valStr, ax: a.x, ay: a.y };
|
|
54253
54499
|
break;
|
|
54254
54500
|
}
|
|
54255
54501
|
}
|
|
54256
54502
|
if (labelW(t) <= boxW && labelH <= boxH) {
|
|
54257
|
-
if (fitsRegions(nameRect) && fitsPois(nameRect)) {
|
|
54503
|
+
if (fitsRegions(nameRect) && fitsPois(nameRect) && (valStr === void 0 || extremesOnFill(a.x, a.y, t))) {
|
|
54258
54504
|
chosen = { text: t, ax: a.x, ay: a.y };
|
|
54259
54505
|
break;
|
|
54260
54506
|
}
|
|
@@ -54262,7 +54508,7 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54262
54508
|
}
|
|
54263
54509
|
if (chosen) break;
|
|
54264
54510
|
}
|
|
54265
|
-
if (chosen === void 0 &&
|
|
54511
|
+
if (chosen === void 0 && r.label !== void 0 && isSubject) {
|
|
54266
54512
|
const hop = tryShortHopCallout(c[0], c[1], r.fill, r.label, valStr);
|
|
54267
54513
|
if (hop) {
|
|
54268
54514
|
placedRegionRects.push(hop.rect);
|
|
@@ -54274,9 +54520,9 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54274
54520
|
text: r.label,
|
|
54275
54521
|
anchor: "middle",
|
|
54276
54522
|
color: palette.text,
|
|
54277
|
-
halo:
|
|
54523
|
+
halo: false,
|
|
54278
54524
|
haloColor: palette.bg,
|
|
54279
|
-
valueLine: valStr,
|
|
54525
|
+
...valStr !== void 0 && { valueLine: valStr },
|
|
54280
54526
|
leader: {
|
|
54281
54527
|
x1: hop.leader[0],
|
|
54282
54528
|
y1: hop.leader[1],
|
|
@@ -54287,20 +54533,28 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54287
54533
|
calloutDot: { x: c[0], y: c[1], color: dark },
|
|
54288
54534
|
lineNumber: r.lineNumber
|
|
54289
54535
|
});
|
|
54536
|
+
labeledRegionIds.add(r.id);
|
|
54290
54537
|
}
|
|
54291
54538
|
continue;
|
|
54292
54539
|
}
|
|
54293
54540
|
if (chosen === void 0) continue;
|
|
54294
54541
|
const isOrient = r.value === void 0 && r.layer === "base";
|
|
54295
54542
|
let font = FONT2;
|
|
54296
|
-
let fade = 0;
|
|
54297
54543
|
if (isOrient) {
|
|
54298
54544
|
const growT = sizeT(boxW, boxH);
|
|
54299
54545
|
const desiredFont = Math.round(
|
|
54300
54546
|
FONT2 + growT * (REGION_FONT_MAX_ORIENT - FONT2)
|
|
54301
54547
|
);
|
|
54302
54548
|
const hasVal = chosen.valueLine !== void 0;
|
|
54303
|
-
|
|
54549
|
+
const extremesClean = (f) => {
|
|
54550
|
+
const halfW = measureLegendText(chosen.text, f) / 2;
|
|
54551
|
+
return [chosen.ax - halfW, chosen.ax + halfW].every((sx) => {
|
|
54552
|
+
const fAt = fillAt(sx, chosen.ay);
|
|
54553
|
+
return fAt === r.fill || isEmptyFill(fAt);
|
|
54554
|
+
});
|
|
54555
|
+
};
|
|
54556
|
+
let fit = -1;
|
|
54557
|
+
for (let f = desiredFont; f >= FONT2; f--) {
|
|
54304
54558
|
if (stackW(chosen.text, chosen.valueLine, f) > boxW || stackH(hasVal, f) > boxH)
|
|
54305
54559
|
continue;
|
|
54306
54560
|
const gRect = regionLabelRect(
|
|
@@ -54317,14 +54571,18 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54317
54571
|
void 0,
|
|
54318
54572
|
f
|
|
54319
54573
|
);
|
|
54320
|
-
if (!fitsRegions(gRect) || !fitsPois(gName))
|
|
54321
|
-
const halfW = measureLegendText(chosen.text, f) / 2;
|
|
54322
|
-
if (fillAt(chosen.ax - halfW, chosen.ay) !== r.fill || fillAt(chosen.ax + halfW, chosen.ay) !== r.fill)
|
|
54574
|
+
if (!fitsRegions(gRect) || !fitsPois(gName) || collides(gName))
|
|
54323
54575
|
continue;
|
|
54324
|
-
|
|
54576
|
+
if (!extremesClean(f)) continue;
|
|
54577
|
+
fit = f;
|
|
54325
54578
|
break;
|
|
54326
54579
|
}
|
|
54327
|
-
|
|
54580
|
+
if (fit < 0) {
|
|
54581
|
+
if (!frameContainers.has(r.id)) continue;
|
|
54582
|
+
font = FONT2;
|
|
54583
|
+
} else {
|
|
54584
|
+
font = fit;
|
|
54585
|
+
}
|
|
54328
54586
|
}
|
|
54329
54587
|
const rRect = regionLabelRect(
|
|
54330
54588
|
chosen.ax,
|
|
@@ -54342,8 +54600,9 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54342
54600
|
r.lineNumber,
|
|
54343
54601
|
chosen.valueLine,
|
|
54344
54602
|
font,
|
|
54345
|
-
|
|
54603
|
+
isOrient ? backdropLandTone : void 0
|
|
54346
54604
|
);
|
|
54605
|
+
labeledRegionIds.add(r.id);
|
|
54347
54606
|
regionLabelGuards.push({
|
|
54348
54607
|
label: labels[labels.length - 1],
|
|
54349
54608
|
rect: rRect
|
|
@@ -54361,6 +54620,7 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54361
54620
|
seed.lineNumber,
|
|
54362
54621
|
valStr
|
|
54363
54622
|
);
|
|
54623
|
+
labeledRegionIds.add(seed.iso);
|
|
54364
54624
|
regionLabelGuards.push({
|
|
54365
54625
|
label: labels[labels.length - 1],
|
|
54366
54626
|
rect: regionLabelRect(seed.x, seed.y, text, valStr)
|
|
@@ -54792,13 +55052,30 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54792
55052
|
const nx = -dy / len;
|
|
54793
55053
|
const ny = dx / len;
|
|
54794
55054
|
const perp = labelH + 2;
|
|
55055
|
+
const pm = /^M(-?[\d.]+),(-?[\d.]+)(?:L(-?[\d.]+),(-?[\d.]+)|Q(-?[\d.]+),(-?[\d.]+) (-?[\d.]+),(-?[\d.]+))$/.exec(
|
|
55056
|
+
lg.d
|
|
55057
|
+
);
|
|
55058
|
+
const pointAt = (t) => {
|
|
55059
|
+
if (pm?.[5] !== void 0) {
|
|
55060
|
+
const u = 1 - t;
|
|
55061
|
+
return [
|
|
55062
|
+
u * u * +pm[1] + 2 * u * t * +pm[5] + t * t * +pm[7],
|
|
55063
|
+
u * u * +pm[2] + 2 * u * t * +pm[6] + t * t * +pm[8]
|
|
55064
|
+
];
|
|
55065
|
+
}
|
|
55066
|
+
if (pm?.[3] !== void 0)
|
|
55067
|
+
return [
|
|
55068
|
+
+pm[1] + (+pm[3] - +pm[1]) * t,
|
|
55069
|
+
+pm[2] + (+pm[4] - +pm[2]) * t
|
|
55070
|
+
];
|
|
55071
|
+
return [a.cx + dx * t, a.cy + dy * t];
|
|
55072
|
+
};
|
|
54795
55073
|
const candidates = [];
|
|
54796
55074
|
for (const off of [0, perp, -perp, 2 * perp, -2 * perp])
|
|
54797
|
-
for (const t of T_LIST)
|
|
54798
|
-
|
|
54799
|
-
|
|
54800
|
-
|
|
54801
|
-
]);
|
|
55075
|
+
for (const t of T_LIST) {
|
|
55076
|
+
const [bx, by] = pointAt(t);
|
|
55077
|
+
candidates.push([bx + nx * off, by + ny * off - 4]);
|
|
55078
|
+
}
|
|
54802
55079
|
const clean = ([cx2, cy2]) => {
|
|
54803
55080
|
const rect2 = { x: cx2 - w / 2, y: cy2 - labelH / 2, w, h: labelH };
|
|
54804
55081
|
if (rect2.x < 0 || rect2.x + w > width || rect2.y < 0 || rect2.y + rect2.h > height)
|
|
@@ -54808,10 +55085,8 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54808
55085
|
if (placedEdge.some((o) => rectsOverlap(o, rect2))) return false;
|
|
54809
55086
|
return true;
|
|
54810
55087
|
};
|
|
54811
|
-
const
|
|
54812
|
-
|
|
54813
|
-
a.cy + dy * 0.5 - 4
|
|
54814
|
-
];
|
|
55088
|
+
const mid = pointAt(0.5);
|
|
55089
|
+
const [cx, cy] = candidates.find(clean) ?? [mid[0], mid[1] - 4];
|
|
54815
55090
|
const style = labelOnFill(fillAt(cx, cy));
|
|
54816
55091
|
legs[i] = {
|
|
54817
55092
|
...lg,
|
|
@@ -54839,7 +55114,7 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54839
55114
|
const rawCountries = [];
|
|
54840
55115
|
for (const f of worldLayer.values()) {
|
|
54841
55116
|
const iso = typeof f.id === "string" ? f.id : String(f.id ?? "");
|
|
54842
|
-
if (!iso || regionById.has(iso)) continue;
|
|
55117
|
+
if (!iso || regionById.has(iso) || labeledRegionIds.has(iso)) continue;
|
|
54843
55118
|
let hasReferencedSub = false;
|
|
54844
55119
|
for (const k of regionById.keys())
|
|
54845
55120
|
if (k.startsWith(iso + "-")) {
|
|
@@ -54913,7 +55188,7 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54913
55188
|
);
|
|
54914
55189
|
if (usLayer && framedStateContainers) {
|
|
54915
55190
|
for (const [iso, f] of usLayer) {
|
|
54916
|
-
if (regionById.has(iso)) continue;
|
|
55191
|
+
if (regionById.has(iso) || labeledRegionIds.has(iso)) continue;
|
|
54917
55192
|
const viewF = cullFeatureToView(f);
|
|
54918
55193
|
if (!viewF) continue;
|
|
54919
55194
|
const b = path.bounds(viewF);
|
|
@@ -54937,6 +55212,11 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54937
55212
|
waterBodies: data.waterBodies,
|
|
54938
55213
|
countries: countryCandidates,
|
|
54939
55214
|
palette,
|
|
55215
|
+
// One muted, contrast-floored tone shared with the orientation backdrop
|
|
55216
|
+
// (region pass) so a context country (Canada) and an orientation region
|
|
55217
|
+
// (Minnesota) read identically — never below the WCAG-AA floor, no fade.
|
|
55218
|
+
countryTone: backdropLandTone,
|
|
55219
|
+
waterTone: backdropWaterTone,
|
|
54940
55220
|
project,
|
|
54941
55221
|
collides,
|
|
54942
55222
|
contentPoints,
|
|
@@ -55490,19 +55770,60 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
55490
55770
|
sel.style("cursor", "pointer").on("click", () => onClickItem(lineNumber));
|
|
55491
55771
|
};
|
|
55492
55772
|
const gLegs = svg.append("g").attr("class", "dgmo-map-legs").attr("fill", "none");
|
|
55493
|
-
|
|
55494
|
-
const
|
|
55773
|
+
const legEnd = (d) => {
|
|
55774
|
+
const m = /^M(-?[\d.]+),(-?[\d.]+)(?:L(-?[\d.]+),(-?[\d.]+)|Q(-?[\d.]+),(-?[\d.]+) (-?[\d.]+),(-?[\d.]+))$/.exec(
|
|
55775
|
+
d
|
|
55776
|
+
);
|
|
55777
|
+
if (!m) return null;
|
|
55778
|
+
const x0 = +m[1];
|
|
55779
|
+
const y0 = +m[2];
|
|
55780
|
+
let ex;
|
|
55781
|
+
let ey;
|
|
55782
|
+
let fromX;
|
|
55783
|
+
let fromY;
|
|
55784
|
+
if (m[3] !== void 0) {
|
|
55785
|
+
ex = +m[3];
|
|
55786
|
+
ey = +m[4];
|
|
55787
|
+
fromX = x0;
|
|
55788
|
+
fromY = y0;
|
|
55789
|
+
} else {
|
|
55790
|
+
ex = +m[7];
|
|
55791
|
+
ey = +m[8];
|
|
55792
|
+
fromX = +m[5];
|
|
55793
|
+
fromY = +m[6];
|
|
55794
|
+
}
|
|
55795
|
+
const dx = ex - fromX;
|
|
55796
|
+
const dy = ey - fromY;
|
|
55797
|
+
const len = Math.hypot(dx, dy);
|
|
55798
|
+
if (!(len > 0)) return null;
|
|
55799
|
+
return { ex, ey, tx: dx / len, ty: dy / len };
|
|
55800
|
+
};
|
|
55801
|
+
layout.legs.forEach((leg) => {
|
|
55802
|
+
const end = leg.arrow ? legEnd(leg.d) : null;
|
|
55803
|
+
let drawD = leg.d;
|
|
55804
|
+
let arrowTri = null;
|
|
55805
|
+
if (end) {
|
|
55806
|
+
const aLen = arrowSize(leg.width);
|
|
55807
|
+
const aHalf = Math.max(aLen * 0.5, leg.width * 0.6 + 1);
|
|
55808
|
+
const bx = end.ex - end.tx * aLen;
|
|
55809
|
+
const by = end.ey - end.ty * aLen;
|
|
55810
|
+
const px = -end.ty;
|
|
55811
|
+
const py = end.tx;
|
|
55812
|
+
arrowTri = `M${bx + px * aHalf},${by + py * aHalf}L${end.ex},${end.ey}L${bx - px * aHalf},${by - py * aHalf}z`;
|
|
55813
|
+
drawD = leg.d.replace(
|
|
55814
|
+
/(-?[\d.]+),(-?[\d.]+)$/,
|
|
55815
|
+
`${bx.toFixed(2)},${by.toFixed(2)}`
|
|
55816
|
+
);
|
|
55817
|
+
}
|
|
55818
|
+
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);
|
|
55495
55819
|
if (leg.tags) {
|
|
55496
55820
|
for (const [group, value] of Object.entries(leg.tags)) {
|
|
55497
55821
|
p.attr(`data-tag-${group.toLowerCase()}`, value.toLowerCase());
|
|
55498
55822
|
}
|
|
55499
55823
|
}
|
|
55500
55824
|
wireSync(p, leg.lineNumber);
|
|
55501
|
-
if (
|
|
55502
|
-
|
|
55503
|
-
const s = arrowSize(leg.width);
|
|
55504
|
-
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);
|
|
55505
|
-
p.attr("marker-end", `url(#${id})`);
|
|
55825
|
+
if (arrowTri) {
|
|
55826
|
+
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);
|
|
55506
55827
|
}
|
|
55507
55828
|
if (leg.label !== void 0 && leg.labelX !== void 0) {
|
|
55508
55829
|
const lt = emitText(
|
|
@@ -65417,326 +65738,6 @@ var themes = {
|
|
|
65417
65738
|
|
|
65418
65739
|
// src/advanced.ts
|
|
65419
65740
|
init_dgmo_router();
|
|
65420
|
-
|
|
65421
|
-
// src/migrate/index.ts
|
|
65422
|
-
init_dgmo_router();
|
|
65423
|
-
import {
|
|
65424
|
-
readFileSync,
|
|
65425
|
-
writeFileSync,
|
|
65426
|
-
existsSync,
|
|
65427
|
-
statSync,
|
|
65428
|
-
readdirSync
|
|
65429
|
-
} from "fs";
|
|
65430
|
-
import { join, extname } from "path";
|
|
65431
|
-
|
|
65432
|
-
// src/migrate/line-classifier.ts
|
|
65433
|
-
function findUnsafePipePositions(line11) {
|
|
65434
|
-
const positions = [];
|
|
65435
|
-
let i = 0;
|
|
65436
|
-
let inDouble = false;
|
|
65437
|
-
let inSingle = false;
|
|
65438
|
-
let braceDepth = 0;
|
|
65439
|
-
let inArrow = false;
|
|
65440
|
-
let arrowOpenChar = null;
|
|
65441
|
-
while (i < line11.length) {
|
|
65442
|
-
const ch = line11[i];
|
|
65443
|
-
const ch2 = i + 1 < line11.length ? line11[i + 1] : "";
|
|
65444
|
-
if (inDouble) {
|
|
65445
|
-
if (ch === '"') inDouble = false;
|
|
65446
|
-
i++;
|
|
65447
|
-
continue;
|
|
65448
|
-
}
|
|
65449
|
-
if (inSingle) {
|
|
65450
|
-
if (ch === "'") inSingle = false;
|
|
65451
|
-
i++;
|
|
65452
|
-
continue;
|
|
65453
|
-
}
|
|
65454
|
-
if (inArrow) {
|
|
65455
|
-
if (arrowOpenChar === "-" && ch === "-" && ch2 === ">" || arrowOpenChar === "~" && ch === "~" && ch2 === ">") {
|
|
65456
|
-
inArrow = false;
|
|
65457
|
-
arrowOpenChar = null;
|
|
65458
|
-
i += 2;
|
|
65459
|
-
continue;
|
|
65460
|
-
}
|
|
65461
|
-
i++;
|
|
65462
|
-
continue;
|
|
65463
|
-
}
|
|
65464
|
-
if (ch === '"') {
|
|
65465
|
-
inDouble = true;
|
|
65466
|
-
i++;
|
|
65467
|
-
continue;
|
|
65468
|
-
}
|
|
65469
|
-
if (ch === "'") {
|
|
65470
|
-
inSingle = true;
|
|
65471
|
-
i++;
|
|
65472
|
-
continue;
|
|
65473
|
-
}
|
|
65474
|
-
if (ch === "{") {
|
|
65475
|
-
braceDepth++;
|
|
65476
|
-
i++;
|
|
65477
|
-
continue;
|
|
65478
|
-
}
|
|
65479
|
-
if (ch === "}") {
|
|
65480
|
-
if (braceDepth > 0) braceDepth--;
|
|
65481
|
-
i++;
|
|
65482
|
-
continue;
|
|
65483
|
-
}
|
|
65484
|
-
if ((ch === "-" || ch === "~") && i > 0) {
|
|
65485
|
-
const prev = line11[i - 1];
|
|
65486
|
-
const onBoundary = prev === " " || prev === " ";
|
|
65487
|
-
const nextIsLabelChar = ch2 !== "" && ch2 !== ch && ch2 !== ">" && ch2 !== " " && ch2 !== " ";
|
|
65488
|
-
if (onBoundary && nextIsLabelChar) {
|
|
65489
|
-
const closer = ch + ">";
|
|
65490
|
-
const closeIdx = line11.indexOf(closer, i + 1);
|
|
65491
|
-
if (closeIdx > i) {
|
|
65492
|
-
const labelRegion = line11.substring(i + 1, closeIdx);
|
|
65493
|
-
if (!labelRegion.includes("->") && !labelRegion.includes("~>")) {
|
|
65494
|
-
inArrow = true;
|
|
65495
|
-
arrowOpenChar = ch;
|
|
65496
|
-
i++;
|
|
65497
|
-
continue;
|
|
65498
|
-
}
|
|
65499
|
-
}
|
|
65500
|
-
}
|
|
65501
|
-
}
|
|
65502
|
-
if (ch === "|" && braceDepth === 0) {
|
|
65503
|
-
positions.push(i);
|
|
65504
|
-
}
|
|
65505
|
-
i++;
|
|
65506
|
-
}
|
|
65507
|
-
return positions;
|
|
65508
|
-
}
|
|
65509
|
-
function isLegacyMetadataLine(line11) {
|
|
65510
|
-
return findUnsafePipePositions(line11).length > 0;
|
|
65511
|
-
}
|
|
65512
|
-
|
|
65513
|
-
// src/migrate/line-transformer.ts
|
|
65514
|
-
function replaceUnsafePipesWithCommas(s) {
|
|
65515
|
-
const positions = findUnsafePipePositions(s);
|
|
65516
|
-
if (positions.length === 0) return s;
|
|
65517
|
-
const chars = s.split("");
|
|
65518
|
-
for (const pos of positions) {
|
|
65519
|
-
chars[pos] = ",";
|
|
65520
|
-
}
|
|
65521
|
-
return chars.join("");
|
|
65522
|
-
}
|
|
65523
|
-
var GANTT_PERCENT = {
|
|
65524
|
-
match: (t) => /^\d+(?:\.\d+)?\s*%$/.test(t.trim()),
|
|
65525
|
-
promote: (t) => `progress: ${t.trim().replace(/\s*%$/, "")}`
|
|
65526
|
-
};
|
|
65527
|
-
var JOURNEY_SCORE = {
|
|
65528
|
-
match: (t) => /^\d+(?:\s+[A-Za-z][A-Za-z0-9_-]*)?$/.test(t.trim()),
|
|
65529
|
-
promote: (t) => {
|
|
65530
|
-
const m = t.trim().match(/^(\d+)(?:\s+([A-Za-z][A-Za-z0-9_-]*))?$/);
|
|
65531
|
-
if (!m) return t;
|
|
65532
|
-
return m[2] ? `score: ${m[1]}, emotion: ${m[2]}` : `score: ${m[1]}`;
|
|
65533
|
-
}
|
|
65534
|
-
};
|
|
65535
|
-
var PROMOTIONS_BY_CHART = {
|
|
65536
|
-
gantt: [GANTT_PERCENT],
|
|
65537
|
-
"journey-map": [JOURNEY_SCORE]
|
|
65538
|
-
};
|
|
65539
|
-
var BARE_DESCRIPTION_CHARTS = /* @__PURE__ */ new Set(["pyramid", "ring"]);
|
|
65540
|
-
function tokenizeMetaRegion(region) {
|
|
65541
|
-
const tokens = [];
|
|
65542
|
-
let i = 0;
|
|
65543
|
-
let buf = "";
|
|
65544
|
-
let inQuote = null;
|
|
65545
|
-
while (i < region.length) {
|
|
65546
|
-
const ch = region[i];
|
|
65547
|
-
if (inQuote) {
|
|
65548
|
-
buf += ch;
|
|
65549
|
-
if (ch === inQuote) inQuote = null;
|
|
65550
|
-
i++;
|
|
65551
|
-
continue;
|
|
65552
|
-
}
|
|
65553
|
-
if (ch === '"' || ch === "'") {
|
|
65554
|
-
inQuote = ch;
|
|
65555
|
-
buf += ch;
|
|
65556
|
-
i++;
|
|
65557
|
-
continue;
|
|
65558
|
-
}
|
|
65559
|
-
if (ch === ",") {
|
|
65560
|
-
const t = buf.trim();
|
|
65561
|
-
if (t) tokens.push(t);
|
|
65562
|
-
buf = "";
|
|
65563
|
-
i++;
|
|
65564
|
-
continue;
|
|
65565
|
-
}
|
|
65566
|
-
buf += ch;
|
|
65567
|
-
i++;
|
|
65568
|
-
}
|
|
65569
|
-
const tail = buf.trim();
|
|
65570
|
-
if (tail) tokens.push(tail);
|
|
65571
|
-
return tokens;
|
|
65572
|
-
}
|
|
65573
|
-
function transformLine(line11, chartType) {
|
|
65574
|
-
const indentMatch = line11.match(/^[ \t]*/);
|
|
65575
|
-
const indent = indentMatch ? indentMatch[0] : "";
|
|
65576
|
-
const body = line11.substring(indent.length);
|
|
65577
|
-
const pipePositions = findUnsafePipePositions(body);
|
|
65578
|
-
if (pipePositions.length === 0) {
|
|
65579
|
-
return { line: line11, changed: false };
|
|
65580
|
-
}
|
|
65581
|
-
const cut = pipePositions[0];
|
|
65582
|
-
const nameRegion = body.substring(0, cut).trimEnd();
|
|
65583
|
-
let metaRegion = body.substring(cut + 1).trimStart();
|
|
65584
|
-
if (pipePositions.length > 1) {
|
|
65585
|
-
metaRegion = replaceUnsafePipesWithCommas(metaRegion);
|
|
65586
|
-
}
|
|
65587
|
-
if (chartType !== null && BARE_DESCRIPTION_CHARTS.has(chartType) && !metaRegion.includes(":")) {
|
|
65588
|
-
const text = metaRegion.trim();
|
|
65589
|
-
if (!text) {
|
|
65590
|
-
return {
|
|
65591
|
-
line: indent + nameRegion,
|
|
65592
|
-
changed: true
|
|
65593
|
-
};
|
|
65594
|
-
}
|
|
65595
|
-
const value = text.includes(",") ? `"${text}"` : text;
|
|
65596
|
-
return {
|
|
65597
|
-
line: `${indent}${nameRegion} description: ${value}`,
|
|
65598
|
-
changed: true
|
|
65599
|
-
};
|
|
65600
|
-
}
|
|
65601
|
-
const tokens = tokenizeMetaRegion(metaRegion);
|
|
65602
|
-
const promotions = chartType ? PROMOTIONS_BY_CHART[chartType] ?? [] : [];
|
|
65603
|
-
const emitted = [];
|
|
65604
|
-
for (const raw of tokens) {
|
|
65605
|
-
if (raw.includes(":")) {
|
|
65606
|
-
emitted.push(raw);
|
|
65607
|
-
continue;
|
|
65608
|
-
}
|
|
65609
|
-
const promo = promotions.find((p) => p.match(raw));
|
|
65610
|
-
if (promo) {
|
|
65611
|
-
emitted.push(promo.promote(raw));
|
|
65612
|
-
continue;
|
|
65613
|
-
}
|
|
65614
|
-
emitted.push(raw);
|
|
65615
|
-
}
|
|
65616
|
-
if (emitted.length === 0) {
|
|
65617
|
-
return {
|
|
65618
|
-
line: indent + nameRegion,
|
|
65619
|
-
changed: true
|
|
65620
|
-
};
|
|
65621
|
-
}
|
|
65622
|
-
return {
|
|
65623
|
-
line: `${indent}${nameRegion} ${emitted.join(", ")}`,
|
|
65624
|
-
changed: true
|
|
65625
|
-
};
|
|
65626
|
-
}
|
|
65627
|
-
|
|
65628
|
-
// src/migrate/data-comma.ts
|
|
65629
|
-
init_colors();
|
|
65630
|
-
var DATA_COMMA_CHART_TYPES = /* @__PURE__ */ new Set([
|
|
65631
|
-
// Simple charts (chart.ts)
|
|
65632
|
-
"bar",
|
|
65633
|
-
"line",
|
|
65634
|
-
"multi-line",
|
|
65635
|
-
"pie",
|
|
65636
|
-
"doughnut",
|
|
65637
|
-
"area",
|
|
65638
|
-
"polar-area",
|
|
65639
|
-
"radar",
|
|
65640
|
-
"bar-stacked",
|
|
65641
|
-
// Extended charts (echarts.ts)
|
|
65642
|
-
"scatter",
|
|
65643
|
-
"heatmap",
|
|
65644
|
-
"sankey",
|
|
65645
|
-
"chord",
|
|
65646
|
-
"funnel",
|
|
65647
|
-
// Visualizations (d3 / visualizations/parse.ts)
|
|
65648
|
-
"quadrant",
|
|
65649
|
-
"slope",
|
|
65650
|
-
"arc",
|
|
65651
|
-
"wordcloud"
|
|
65652
|
-
]);
|
|
65653
|
-
var COLOR_SET = new Set(RECOGNIZED_COLOR_NAMES);
|
|
65654
|
-
var NUMERIC_VALUE_RE = /^-?\d[\d,_]*(?:\.\d+)?,?$/;
|
|
65655
|
-
function isNumericValueToken(tok) {
|
|
65656
|
-
if (!NUMERIC_VALUE_RE.test(tok)) return false;
|
|
65657
|
-
return /\d/.test(tok);
|
|
65658
|
-
}
|
|
65659
|
-
function migrateDataRowCommaLine(line11) {
|
|
65660
|
-
const indentMatch = line11.match(/^[ \t]*/);
|
|
65661
|
-
const indent = indentMatch ? indentMatch[0] : "";
|
|
65662
|
-
const body = line11.substring(indent.length);
|
|
65663
|
-
if (!body || body.startsWith("//")) return { line: line11, changed: false };
|
|
65664
|
-
const tokens = body.split(/\s+/);
|
|
65665
|
-
if (tokens.length < 2) return { line: line11, changed: false };
|
|
65666
|
-
let i = tokens.length - 1;
|
|
65667
|
-
if (i >= 1 && COLOR_SET.has(tokens[i])) {
|
|
65668
|
-
i--;
|
|
65669
|
-
}
|
|
65670
|
-
const valueStart = (() => {
|
|
65671
|
-
let j = i;
|
|
65672
|
-
while (j >= 1 && isNumericValueToken(tokens[j])) j--;
|
|
65673
|
-
return j + 1;
|
|
65674
|
-
})();
|
|
65675
|
-
if (valueStart > i || valueStart < 1) return { line: line11, changed: false };
|
|
65676
|
-
const valueTokens = tokens.slice(valueStart, i + 1);
|
|
65677
|
-
const hasComma = valueTokens.some((t) => t.includes(","));
|
|
65678
|
-
if (!hasComma) return { line: line11, changed: false };
|
|
65679
|
-
const cleaned = valueTokens.map((t) => t.replace(/,/g, ""));
|
|
65680
|
-
const labelPart = tokens.slice(0, valueStart);
|
|
65681
|
-
const tail = tokens.slice(i + 1);
|
|
65682
|
-
const rebuiltBody = [...labelPart, ...cleaned, ...tail].join(" ");
|
|
65683
|
-
return { line: indent + rebuiltBody, changed: rebuiltBody !== body };
|
|
65684
|
-
}
|
|
65685
|
-
|
|
65686
|
-
// src/migrate/index.ts
|
|
65687
|
-
function migrateContent(source) {
|
|
65688
|
-
const chartType = parseDgmoChartType(source);
|
|
65689
|
-
const lines = source.split("\n");
|
|
65690
|
-
const out = [];
|
|
65691
|
-
const changedLines = [];
|
|
65692
|
-
let changed = false;
|
|
65693
|
-
const migrateDataCommas = chartType !== null && DATA_COMMA_CHART_TYPES.has(chartType);
|
|
65694
|
-
let firstContentSeen = false;
|
|
65695
|
-
for (let i = 0; i < lines.length; i++) {
|
|
65696
|
-
let line11 = lines[i];
|
|
65697
|
-
const trimmed = line11.trim();
|
|
65698
|
-
if (migrateDataCommas && firstContentSeen && trimmed && !trimmed.startsWith("//")) {
|
|
65699
|
-
const dc = migrateDataRowCommaLine(line11);
|
|
65700
|
-
if (dc.changed) {
|
|
65701
|
-
line11 = dc.line;
|
|
65702
|
-
changed = true;
|
|
65703
|
-
changedLines.push(i + 1);
|
|
65704
|
-
}
|
|
65705
|
-
}
|
|
65706
|
-
if (trimmed && !trimmed.startsWith("//")) firstContentSeen = true;
|
|
65707
|
-
if (!isLegacyMetadataLine(line11)) {
|
|
65708
|
-
out.push(line11);
|
|
65709
|
-
continue;
|
|
65710
|
-
}
|
|
65711
|
-
const result = transformLine(line11, chartType);
|
|
65712
|
-
if (result.changed) {
|
|
65713
|
-
changed = true;
|
|
65714
|
-
if (!changedLines.includes(i + 1)) changedLines.push(i + 1);
|
|
65715
|
-
}
|
|
65716
|
-
out.push(result.line);
|
|
65717
|
-
}
|
|
65718
|
-
return {
|
|
65719
|
-
migrated: out.join("\n"),
|
|
65720
|
-
changed,
|
|
65721
|
-
chartType,
|
|
65722
|
-
changedLines
|
|
65723
|
-
};
|
|
65724
|
-
}
|
|
65725
|
-
function formatLineDiff(path, original, migrated) {
|
|
65726
|
-
const origLines = original.split("\n");
|
|
65727
|
-
const newLines = migrated.split("\n");
|
|
65728
|
-
const lines = [`--- ${path}`, `+++ ${path}`];
|
|
65729
|
-
const max = Math.max(origLines.length, newLines.length);
|
|
65730
|
-
for (let i = 0; i < max; i++) {
|
|
65731
|
-
const a = origLines[i];
|
|
65732
|
-
const b = newLines[i];
|
|
65733
|
-
if (a === b) continue;
|
|
65734
|
-
if (a !== void 0) lines.push(`@@ line ${i + 1}
|
|
65735
|
-
- ${a}`);
|
|
65736
|
-
if (b !== void 0) lines.push(`+ ${b}`);
|
|
65737
|
-
}
|
|
65738
|
-
return lines.join("\n");
|
|
65739
|
-
}
|
|
65740
65741
|
export {
|
|
65741
65742
|
ALL_CHART_TYPES,
|
|
65742
65743
|
ARROW_DIAGNOSTIC_CODES,
|
|
@@ -65805,12 +65806,10 @@ export {
|
|
|
65805
65806
|
extractSymbols as extractFlowchartSymbols,
|
|
65806
65807
|
extractSymbols4 as extractInfraSymbols,
|
|
65807
65808
|
extractPertSymbols,
|
|
65808
|
-
findUnsafePipePositions,
|
|
65809
65809
|
focusBoxesAndLines,
|
|
65810
65810
|
focusOrgTree,
|
|
65811
65811
|
formatDateLabel,
|
|
65812
65812
|
formatDgmoError,
|
|
65813
|
-
formatLineDiff,
|
|
65814
65813
|
getAllChartTypes,
|
|
65815
65814
|
getAvailablePalettes,
|
|
65816
65815
|
getExtendedChartLegendGroups,
|
|
@@ -65831,7 +65830,6 @@ export {
|
|
|
65831
65830
|
isArchiveColumn,
|
|
65832
65831
|
isExtendedChartType,
|
|
65833
65832
|
isInvalidColorToken,
|
|
65834
|
-
isLegacyMetadataLine,
|
|
65835
65833
|
isRecognizedColorName,
|
|
65836
65834
|
isSequenceBlock,
|
|
65837
65835
|
isSequenceNote,
|
|
@@ -65868,7 +65866,6 @@ export {
|
|
|
65868
65866
|
mapExportDimensions,
|
|
65869
65867
|
mapNeutralLandColor,
|
|
65870
65868
|
measurePertAnalysisBlock,
|
|
65871
|
-
migrateContent,
|
|
65872
65869
|
mix,
|
|
65873
65870
|
mulberry32,
|
|
65874
65871
|
nearestNamedColor,
|
|
@@ -65996,7 +65993,6 @@ export {
|
|
|
65996
65993
|
tidewaterPalette,
|
|
65997
65994
|
tint,
|
|
65998
65995
|
tokyoNightPalette,
|
|
65999
|
-
transformLine,
|
|
66000
65996
|
truncateBareUrl,
|
|
66001
65997
|
parseDgmo as validate,
|
|
66002
65998
|
validateComputed,
|