@diagrammo/dgmo 0.36.0 → 0.38.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/.cursorrules +3 -0
- package/.github/copilot-instructions.md +3 -0
- package/.windsurfrules +3 -0
- package/SKILL.md +3 -0
- package/dist/advanced.cjs +1058 -135
- package/dist/advanced.d.cts +122 -8
- package/dist/advanced.d.ts +122 -8
- package/dist/advanced.js +1055 -133
- package/dist/auto.cjs +1047 -132
- package/dist/auto.js +96 -95
- package/dist/auto.mjs +1048 -130
- package/dist/cli.cjs +117 -116
- package/dist/editor.cjs +4 -1
- package/dist/editor.js +4 -1
- package/dist/highlight.cjs +3 -0
- package/dist/highlight.js +3 -0
- package/dist/index.cjs +1043 -131
- package/dist/index.js +1044 -129
- package/docs/ai-integration.md +3 -0
- package/docs/language-reference.md +106 -7
- package/gallery/fixtures/map-coastline.dgmo +2 -2
- package/gallery/fixtures/map-route.dgmo +5 -5
- package/gallery/fixtures/treemap-branch.dgmo +15 -0
- package/gallery/fixtures/treemap-heat.dgmo +12 -0
- package/gallery/fixtures/treemap-tag-heat.dgmo +21 -0
- package/gallery/fixtures/treemap-tags.dgmo +18 -0
- package/package.json +1 -1
- package/src/advanced.ts +11 -0
- package/src/boxes-and-lines/layout-search.ts +19 -1
- package/src/chart-type-registry.ts +4 -0
- package/src/chart-types.ts +5 -0
- package/src/completion.ts +64 -0
- package/src/d3.ts +30 -18
- package/src/editor/highlight-api.ts +2 -0
- package/src/editor/keywords.ts +3 -0
- package/src/infra/parser.ts +95 -38
- package/src/map/dimensions.ts +19 -2
- package/src/map/layout.ts +91 -7
- package/src/map/parser.ts +51 -29
- package/src/map/renderer.ts +10 -0
- package/src/map/types.ts +9 -8
- package/src/treemap/layout.ts +189 -0
- package/src/treemap/parser.ts +475 -0
- package/src/treemap/renderer.ts +698 -0
- package/src/treemap/types.ts +57 -0
- package/src/utils/parsing.ts +1 -0
- package/src/utils/reserved-key-registry.ts +5 -0
package/dist/auto.cjs
CHANGED
|
@@ -602,7 +602,7 @@ function withTagAliases(base, aliases) {
|
|
|
602
602
|
function isReservedKey(registry, key) {
|
|
603
603
|
return registry.keys.has(key) || registry.tagAliases.has(key);
|
|
604
604
|
}
|
|
605
|
-
var SEQUENCE_REGISTRY, INFRA_REGISTRY, MAP_REGISTRY, ORG_REGISTRY, C4_REGISTRY, ER_REGISTRY, KANBAN_REGISTRY, SITEMAP_REGISTRY, GANTT_REGISTRY, PERT_REGISTRY, BOXES_AND_LINES_REGISTRY, TIMELINE_REGISTRY, MINDMAP_REGISTRY, TECH_RADAR_REGISTRY, CYCLE_REGISTRY, JOURNEY_MAP_REGISTRY, PYRAMID_REGISTRY, RING_REGISTRY, RACI_REGISTRY;
|
|
605
|
+
var SEQUENCE_REGISTRY, INFRA_REGISTRY, MAP_REGISTRY, ORG_REGISTRY, C4_REGISTRY, ER_REGISTRY, KANBAN_REGISTRY, SITEMAP_REGISTRY, GANTT_REGISTRY, PERT_REGISTRY, BOXES_AND_LINES_REGISTRY, TIMELINE_REGISTRY, MINDMAP_REGISTRY, TECH_RADAR_REGISTRY, CYCLE_REGISTRY, JOURNEY_MAP_REGISTRY, PYRAMID_REGISTRY, RING_REGISTRY, TREEMAP_REGISTRY, RACI_REGISTRY;
|
|
606
606
|
var init_reserved_key_registry = __esm({
|
|
607
607
|
"src/utils/reserved-key-registry.ts"() {
|
|
608
608
|
"use strict";
|
|
@@ -721,6 +721,7 @@ var init_reserved_key_registry = __esm({
|
|
|
721
721
|
"color",
|
|
722
722
|
"description"
|
|
723
723
|
]);
|
|
724
|
+
TREEMAP_REGISTRY = staticRegistry(["heat"]);
|
|
724
725
|
RACI_REGISTRY = staticRegistry([
|
|
725
726
|
"color",
|
|
726
727
|
"description"
|
|
@@ -1150,6 +1151,7 @@ var init_parsing = __esm({
|
|
|
1150
1151
|
"journey-map",
|
|
1151
1152
|
"pyramid",
|
|
1152
1153
|
"ring",
|
|
1154
|
+
"treemap",
|
|
1153
1155
|
"raci",
|
|
1154
1156
|
"rasci",
|
|
1155
1157
|
"daci",
|
|
@@ -11809,6 +11811,10 @@ var init_chart_types = __esm({
|
|
|
11809
11811
|
id: "ring",
|
|
11810
11812
|
description: "Concentric rings showing nested or hierarchical categories (read core-out)"
|
|
11811
11813
|
},
|
|
11814
|
+
{
|
|
11815
|
+
id: "treemap",
|
|
11816
|
+
description: "Nested rectangles sized by value \u2014 show a hierarchy\u2019s proportions (budgets, disk usage, portfolios) with color by category, value heatmap, or branch"
|
|
11817
|
+
},
|
|
11812
11818
|
{
|
|
11813
11819
|
id: "map",
|
|
11814
11820
|
description: "Geographic concept map: highlight/score regions, drop points of interest, connect with routes or edges"
|
|
@@ -16665,6 +16671,7 @@ function parseInfra(content) {
|
|
|
16665
16671
|
let currentGroup = null;
|
|
16666
16672
|
let currentTagGroup = null;
|
|
16667
16673
|
let baseIndent = 0;
|
|
16674
|
+
let firstLineConsumed = false;
|
|
16668
16675
|
function finishCurrentNode() {
|
|
16669
16676
|
if (!currentNode) return;
|
|
16670
16677
|
const key = currentNode.id;
|
|
@@ -16672,7 +16679,8 @@ function parseInfra(content) {
|
|
|
16672
16679
|
if (existing) {
|
|
16673
16680
|
const incomingDisplay = displayName(currentNode.label);
|
|
16674
16681
|
const existingDisplay = displayName(existing.label);
|
|
16675
|
-
|
|
16682
|
+
const isAliasRef = nameAliasMap.get(currentNode.label) === key;
|
|
16683
|
+
if (incomingDisplay !== existingDisplay && !isAliasRef) {
|
|
16676
16684
|
result.diagnostics.push(
|
|
16677
16685
|
makeDgmoError(
|
|
16678
16686
|
currentNode.lineNumber,
|
|
@@ -16738,19 +16746,22 @@ function parseInfra(content) {
|
|
|
16738
16746
|
if (indent === 0 && currentNode && !trimmed.startsWith("-")) {
|
|
16739
16747
|
finishCurrentNode();
|
|
16740
16748
|
}
|
|
16741
|
-
|
|
16742
|
-
|
|
16743
|
-
|
|
16744
|
-
|
|
16745
|
-
|
|
16746
|
-
|
|
16747
|
-
|
|
16748
|
-
|
|
16749
|
-
|
|
16750
|
-
|
|
16751
|
-
|
|
16749
|
+
if (!firstLineConsumed) {
|
|
16750
|
+
firstLineConsumed = true;
|
|
16751
|
+
const firstLineResult = parseFirstLine(trimmed);
|
|
16752
|
+
if (firstLineResult) {
|
|
16753
|
+
if (firstLineResult.chartType !== "infra") {
|
|
16754
|
+
setError(
|
|
16755
|
+
lineNumber,
|
|
16756
|
+
`Expected chart type 'infra', got '${firstLineResult.chartType}'`
|
|
16757
|
+
);
|
|
16758
|
+
}
|
|
16759
|
+
if (firstLineResult.title) {
|
|
16760
|
+
result.title = firstLineResult.title;
|
|
16761
|
+
result.titleLineNumber = lineNumber;
|
|
16762
|
+
}
|
|
16763
|
+
continue;
|
|
16752
16764
|
}
|
|
16753
|
-
continue;
|
|
16754
16765
|
}
|
|
16755
16766
|
if (/^direction-tb$/i.test(trimmed)) {
|
|
16756
16767
|
result.direction = "TB";
|
|
@@ -16816,18 +16827,20 @@ function parseInfra(content) {
|
|
|
16816
16827
|
if (compMatch) {
|
|
16817
16828
|
finishCurrentNode();
|
|
16818
16829
|
finishCurrentTagGroup();
|
|
16819
|
-
const
|
|
16830
|
+
const { qname, uname, alias: asAlias, meta } = compMatch.groups;
|
|
16831
|
+
const rawName = (qname ?? uname ?? "").trim();
|
|
16820
16832
|
const peeled = peelInfraDecorations(rawName, lineNumber);
|
|
16821
16833
|
const name = peeled.label;
|
|
16822
|
-
const
|
|
16834
|
+
const alias = asAlias ?? peeled.alias;
|
|
16835
|
+
const rest = meta ?? "";
|
|
16823
16836
|
const { tags } = extractPipeMetadata(rest);
|
|
16824
16837
|
warnUnknownMetaKeys(
|
|
16825
16838
|
tags,
|
|
16826
16839
|
withTagAliases(INFRA_REGISTRY, tagAliasSet),
|
|
16827
16840
|
(msg) => warn2(lineNumber, msg)
|
|
16828
16841
|
);
|
|
16829
|
-
const id = nodeId2(name);
|
|
16830
|
-
if (
|
|
16842
|
+
const id = nameAliasMap.get(name) ?? nodeId2(name);
|
|
16843
|
+
if (alias) nameAliasMap.set(alias, id);
|
|
16831
16844
|
const isEdge = EDGE_NODE_NAMES.has(id.toLowerCase());
|
|
16832
16845
|
currentNode = {
|
|
16833
16846
|
id,
|
|
@@ -16911,18 +16924,20 @@ function parseInfra(content) {
|
|
|
16911
16924
|
const compMatch = trimmed.match(COMPONENT_RE);
|
|
16912
16925
|
if (compMatch) {
|
|
16913
16926
|
finishCurrentTagGroup();
|
|
16914
|
-
const
|
|
16927
|
+
const { qname, uname, alias: asAlias, meta } = compMatch.groups;
|
|
16928
|
+
const rawName = (qname ?? uname ?? "").trim();
|
|
16915
16929
|
const peeled = peelInfraDecorations(rawName, lineNumber);
|
|
16916
16930
|
const name = peeled.label;
|
|
16917
|
-
const
|
|
16931
|
+
const alias = asAlias ?? peeled.alias;
|
|
16932
|
+
const rest = meta ?? "";
|
|
16918
16933
|
const { tags: nodeTags } = extractPipeMetadata(rest);
|
|
16919
16934
|
warnUnknownMetaKeys(
|
|
16920
16935
|
nodeTags,
|
|
16921
16936
|
withTagAliases(INFRA_REGISTRY, tagAliasSet),
|
|
16922
16937
|
(msg) => warn2(lineNumber, msg)
|
|
16923
16938
|
);
|
|
16924
|
-
const id = nodeId2(name);
|
|
16925
|
-
if (
|
|
16939
|
+
const id = nameAliasMap.get(name) ?? nodeId2(name);
|
|
16940
|
+
if (alias) nameAliasMap.set(alias, id);
|
|
16926
16941
|
const tags = currentGroup.metadata ? { ...currentGroup.metadata, ...nodeTags } : nodeTags;
|
|
16927
16942
|
currentNode = {
|
|
16928
16943
|
id,
|
|
@@ -17113,6 +17128,11 @@ function parseInfra(content) {
|
|
|
17113
17128
|
}
|
|
17114
17129
|
continue;
|
|
17115
17130
|
}
|
|
17131
|
+
if (currentNode && tagAliasSet.has(normalizeName(key))) {
|
|
17132
|
+
const mut = nodeMutableTags.get(currentNode.id);
|
|
17133
|
+
if (mut) mut[tagAttrKey(key)] = rawVal;
|
|
17134
|
+
continue;
|
|
17135
|
+
}
|
|
17116
17136
|
if (!INFRA_BEHAVIOR_KEYS.has(key) && !EDGE_ONLY_KEYS.has(key)) {
|
|
17117
17137
|
const allKeys = [...INFRA_BEHAVIOR_KEYS, ...EDGE_ONLY_KEYS];
|
|
17118
17138
|
const hint = suggest(key, allKeys);
|
|
@@ -17178,18 +17198,20 @@ function parseInfra(content) {
|
|
|
17178
17198
|
finishCurrentNode();
|
|
17179
17199
|
const compMatch = trimmed.match(COMPONENT_RE);
|
|
17180
17200
|
if (compMatch) {
|
|
17181
|
-
const
|
|
17201
|
+
const { qname, uname, alias: asAlias, meta } = compMatch.groups;
|
|
17202
|
+
const rawName = (qname ?? uname ?? "").trim();
|
|
17182
17203
|
const peeled = peelInfraDecorations(rawName, lineNumber);
|
|
17183
17204
|
const name = peeled.label;
|
|
17184
|
-
const
|
|
17205
|
+
const alias = asAlias ?? peeled.alias;
|
|
17206
|
+
const rest = meta ?? "";
|
|
17185
17207
|
const { tags: nodeTags } = extractPipeMetadata(rest);
|
|
17186
17208
|
warnUnknownMetaKeys(
|
|
17187
17209
|
nodeTags,
|
|
17188
17210
|
withTagAliases(INFRA_REGISTRY, tagAliasSet),
|
|
17189
17211
|
(msg) => warn2(lineNumber, msg)
|
|
17190
17212
|
);
|
|
17191
|
-
const id = nodeId2(name);
|
|
17192
|
-
if (
|
|
17213
|
+
const id = nameAliasMap.get(name) ?? nodeId2(name);
|
|
17214
|
+
if (alias) nameAliasMap.set(alias, id);
|
|
17193
17215
|
const tags = currentGroup.metadata ? { ...currentGroup.metadata, ...nodeTags } : nodeTags;
|
|
17194
17216
|
currentNode = {
|
|
17195
17217
|
id,
|
|
@@ -17211,18 +17233,20 @@ function parseInfra(content) {
|
|
|
17211
17233
|
finishCurrentNode();
|
|
17212
17234
|
finishCurrentTagGroup();
|
|
17213
17235
|
currentGroup = null;
|
|
17214
|
-
const
|
|
17236
|
+
const { qname, uname, alias: asAlias, meta } = compMatch.groups;
|
|
17237
|
+
const rawName = (qname ?? uname ?? "").trim();
|
|
17215
17238
|
const peeled = peelInfraDecorations(rawName, lineNumber);
|
|
17216
17239
|
const name = peeled.label;
|
|
17217
|
-
const
|
|
17240
|
+
const alias = asAlias ?? peeled.alias;
|
|
17241
|
+
const rest = meta ?? "";
|
|
17218
17242
|
const { tags } = extractPipeMetadata(rest);
|
|
17219
17243
|
warnUnknownMetaKeys(
|
|
17220
17244
|
tags,
|
|
17221
17245
|
withTagAliases(INFRA_REGISTRY, tagAliasSet),
|
|
17222
17246
|
(msg) => warn2(lineNumber, msg)
|
|
17223
17247
|
);
|
|
17224
|
-
const id = nodeId2(name);
|
|
17225
|
-
if (
|
|
17248
|
+
const id = nameAliasMap.get(name) ?? nodeId2(name);
|
|
17249
|
+
if (alias) nameAliasMap.set(alias, id);
|
|
17226
17250
|
currentNode = {
|
|
17227
17251
|
id,
|
|
17228
17252
|
label: name,
|
|
@@ -17422,7 +17446,7 @@ var init_parser15 = __esm({
|
|
|
17422
17446
|
DEPRECATED_FANOUT_RE = /\bx(\d+)\s*$/;
|
|
17423
17447
|
GROUP_RE = /^\[([^\]]+)\]\s*(?:as\s+([A-Za-z][A-Za-z0-9_]{0,11})\s*)?((?:\|.*)|(?:[a-zA-Z_]\w*\s*:.*))?$/;
|
|
17424
17448
|
TAG_VALUE_RE = /^(\w[\w\s]+?)\s*$/;
|
|
17425
|
-
COMPONENT_RE = /^(?:"([^"]+)"|([a-zA-Z_][\w -]*?))\s*((?:\|.*)|(?:[a-zA-Z_]\w*\s*:.*))?$/;
|
|
17449
|
+
COMPONENT_RE = /^(?:"(?<qname>[^"]+)"|(?<uname>[a-zA-Z_][\w -]*?))(?:\s+as\s+(?<alias>[A-Za-z][A-Za-z0-9_]{0,11}))?\s*(?<meta>(?:\|.*)|(?:[a-zA-Z_]\w*\s*:.*))?$/;
|
|
17426
17450
|
PIPE_META_RE = /[|,]\s*(\w+)\s*:\s*([^|,]+)/g;
|
|
17427
17451
|
SAMELINE_META_RE = /(?:^|[\s,])(\w+)\s*:\s*([^,]+?)(?=\s*,|\s*$)/g;
|
|
17428
17452
|
PROPERTY_RE = /^([\w-]+):\s*(.+)$/;
|
|
@@ -18906,8 +18930,8 @@ function parseMap(content, palette) {
|
|
|
18906
18930
|
continue;
|
|
18907
18931
|
}
|
|
18908
18932
|
if (open.route && indent > open.route.indent) {
|
|
18909
|
-
const leg = parseLeg(trimmed, lineNumber
|
|
18910
|
-
open.route.route.legs.push(leg);
|
|
18933
|
+
const leg = parseLeg(trimmed, lineNumber);
|
|
18934
|
+
if (leg) open.route.route.legs.push(leg);
|
|
18911
18935
|
continue;
|
|
18912
18936
|
}
|
|
18913
18937
|
if (open.poi && indent > open.poi.indent) {
|
|
@@ -18936,6 +18960,14 @@ function parseMap(content, palette) {
|
|
|
18936
18960
|
Object.assign(open.poi.poi.meta, split.meta);
|
|
18937
18961
|
continue;
|
|
18938
18962
|
}
|
|
18963
|
+
if (split.name) {
|
|
18964
|
+
const src = open.poi.poi.alias ?? poiName(open.poi.poi.pos) ?? "the poi";
|
|
18965
|
+
pushError(
|
|
18966
|
+
lineNumber,
|
|
18967
|
+
`Malformed hub edge: "${trimmed}" \u2014 an indented line under a poi is an edge from "${src}" and needs an arrow glyph (\`-> dest\`, \`~> dest\`, or labeled \`-label-> dest\`). For a standalone place, declare it at the top level. (\xA724B.5)`
|
|
18968
|
+
);
|
|
18969
|
+
continue;
|
|
18970
|
+
}
|
|
18939
18971
|
}
|
|
18940
18972
|
closeBlocks();
|
|
18941
18973
|
const firstWord = trimmed.split(/\s+/)[0];
|
|
@@ -18944,7 +18976,7 @@ function parseMap(content, palette) {
|
|
|
18944
18976
|
continue;
|
|
18945
18977
|
}
|
|
18946
18978
|
if (DIRECTIVE_SET.has(firstWord) && !trimmed.slice(firstWord.length).trimStart().startsWith(":")) {
|
|
18947
|
-
|
|
18979
|
+
handleDirective2(
|
|
18948
18980
|
firstWord,
|
|
18949
18981
|
trimmed.slice(firstWord.length).trim(),
|
|
18950
18982
|
lineNumber
|
|
@@ -18983,7 +19015,7 @@ function parseMap(content, palette) {
|
|
|
18983
19015
|
}
|
|
18984
19016
|
}
|
|
18985
19017
|
return result;
|
|
18986
|
-
function
|
|
19018
|
+
function handleDirective2(key, value, line11) {
|
|
18987
19019
|
const d = result.directives;
|
|
18988
19020
|
const dup = (have) => {
|
|
18989
19021
|
if (have !== void 0)
|
|
@@ -19184,31 +19216,44 @@ function parseMap(content, palette) {
|
|
|
19184
19216
|
const { tags, meta } = partitionMeta(split.meta, tagGroupNames());
|
|
19185
19217
|
const originLabel = meta["label"];
|
|
19186
19218
|
const originValue = meta["value"];
|
|
19187
|
-
|
|
19219
|
+
if (meta["style"] !== void 0) {
|
|
19220
|
+
pushError(
|
|
19221
|
+
line11,
|
|
19222
|
+
"route header no longer takes `style:` \u2014 set leg shape with the arrow glyph instead (`~\u2026~>` for an arc leg, `-\u2026->` for a straight one). (\xA724B.6)"
|
|
19223
|
+
);
|
|
19224
|
+
}
|
|
19188
19225
|
const route = {
|
|
19189
19226
|
origin: pos,
|
|
19190
19227
|
...split.alias !== void 0 && { originAlias: split.alias },
|
|
19191
19228
|
...originLabel !== void 0 && { originLabel },
|
|
19192
19229
|
...originValue !== void 0 && { originValue },
|
|
19193
19230
|
originTags: tags,
|
|
19194
|
-
style,
|
|
19195
19231
|
legs: [],
|
|
19196
19232
|
lineNumber: line11
|
|
19197
19233
|
};
|
|
19198
19234
|
routes.push(route);
|
|
19199
19235
|
open.route = { route, indent };
|
|
19200
19236
|
}
|
|
19201
|
-
function parseLeg(trimmed, line11
|
|
19202
|
-
let arrowStyle = "straight";
|
|
19203
|
-
let label;
|
|
19204
|
-
let rest = trimmed;
|
|
19237
|
+
function parseLeg(trimmed, line11) {
|
|
19205
19238
|
const m = trimmed.match(LEG_ARROW_RE);
|
|
19206
|
-
if (m) {
|
|
19207
|
-
|
|
19208
|
-
|
|
19209
|
-
|
|
19210
|
-
|
|
19239
|
+
if (!m) {
|
|
19240
|
+
pushError(
|
|
19241
|
+
line11,
|
|
19242
|
+
`Malformed route leg: "${trimmed}" \u2014 a leg needs an arrow glyph (\`-> dest\`, \`~> dest\`, or labeled \`-label-> dest\` / \`~label~> dest\`). (\xA724B.6)`
|
|
19243
|
+
);
|
|
19244
|
+
return null;
|
|
19211
19245
|
}
|
|
19246
|
+
const arr = classifyArrow(m[1], line11);
|
|
19247
|
+
if (!arr.directed) {
|
|
19248
|
+
pushError(
|
|
19249
|
+
line11,
|
|
19250
|
+
`A route leg is directional \u2014 "${trimmed}" uses an undirected glyph; use \`-> \` (straight) or \`~> \` (arc). (\xA724B.6)`
|
|
19251
|
+
);
|
|
19252
|
+
return null;
|
|
19253
|
+
}
|
|
19254
|
+
const arrowStyle = arr.style;
|
|
19255
|
+
const label = arr.label;
|
|
19256
|
+
const rest = m[2];
|
|
19212
19257
|
const split = splitNameAndMeta(
|
|
19213
19258
|
rest,
|
|
19214
19259
|
registry(),
|
|
@@ -19224,10 +19269,9 @@ function parseMap(content, palette) {
|
|
|
19224
19269
|
const { tags, meta } = partitionMeta(split.meta, tagGroupNames());
|
|
19225
19270
|
const value = meta["value"];
|
|
19226
19271
|
const destLabel = meta["label"];
|
|
19227
|
-
const style = arrowStyle === "arc" || headerStyle === "arc" ? "arc" : "straight";
|
|
19228
19272
|
return {
|
|
19229
19273
|
...label !== void 0 && { label },
|
|
19230
|
-
style,
|
|
19274
|
+
style: arrowStyle,
|
|
19231
19275
|
...value !== void 0 && { value },
|
|
19232
19276
|
dest: pos,
|
|
19233
19277
|
...split.alias !== void 0 && { destAlias: split.alias },
|
|
@@ -22841,6 +22885,344 @@ var init_parser25 = __esm({
|
|
|
22841
22885
|
}
|
|
22842
22886
|
});
|
|
22843
22887
|
|
|
22888
|
+
// src/treemap/parser.ts
|
|
22889
|
+
var parser_exports20 = {};
|
|
22890
|
+
__export(parser_exports20, {
|
|
22891
|
+
TREEMAP_DIAGNOSTIC_CODES: () => TREEMAP_DIAGNOSTIC_CODES,
|
|
22892
|
+
parseTreemap: () => parseTreemap
|
|
22893
|
+
});
|
|
22894
|
+
function isFullyQuoted(s) {
|
|
22895
|
+
return s.length >= 2 && (s.startsWith('"') && s.endsWith('"') || s.startsWith("'") && s.endsWith("'"));
|
|
22896
|
+
}
|
|
22897
|
+
function parseTreemap(content, palette) {
|
|
22898
|
+
const options = {
|
|
22899
|
+
heatColors: [],
|
|
22900
|
+
noValues: false,
|
|
22901
|
+
noPercent: false,
|
|
22902
|
+
noHeaders: false,
|
|
22903
|
+
noLegend: false
|
|
22904
|
+
};
|
|
22905
|
+
const result = {
|
|
22906
|
+
type: "treemap",
|
|
22907
|
+
title: null,
|
|
22908
|
+
titleLineNumber: null,
|
|
22909
|
+
roots: [],
|
|
22910
|
+
tagGroups: [],
|
|
22911
|
+
hasHeat: false,
|
|
22912
|
+
defaultColorMode: "branch",
|
|
22913
|
+
options,
|
|
22914
|
+
diagnostics: [],
|
|
22915
|
+
error: null
|
|
22916
|
+
};
|
|
22917
|
+
const fail = makeFail(result);
|
|
22918
|
+
const pushError = (line11, message, code) => {
|
|
22919
|
+
const diag = makeDgmoError(line11, message, "error", code);
|
|
22920
|
+
result.diagnostics.push(diag);
|
|
22921
|
+
if (!result.error) result.error = formatDgmoError(diag);
|
|
22922
|
+
};
|
|
22923
|
+
const pushWarning = (line11, message, code) => {
|
|
22924
|
+
result.diagnostics.push(makeDgmoError(line11, message, "warning", code));
|
|
22925
|
+
};
|
|
22926
|
+
if (!content?.trim()) {
|
|
22927
|
+
return fail(0, "No content provided");
|
|
22928
|
+
}
|
|
22929
|
+
const lines = content.split("\n");
|
|
22930
|
+
let contentStarted = false;
|
|
22931
|
+
let nodeCounter = 0;
|
|
22932
|
+
let currentTagGroup = null;
|
|
22933
|
+
const aliasMap = /* @__PURE__ */ new Map();
|
|
22934
|
+
const indentStack = [];
|
|
22935
|
+
for (let i = 0; i < lines.length; i++) {
|
|
22936
|
+
const line11 = lines[i];
|
|
22937
|
+
const lineNumber = i + 1;
|
|
22938
|
+
const trimmed = line11.trim();
|
|
22939
|
+
if (!trimmed) {
|
|
22940
|
+
currentTagGroup = null;
|
|
22941
|
+
continue;
|
|
22942
|
+
}
|
|
22943
|
+
if (trimmed.startsWith("//")) continue;
|
|
22944
|
+
if (!contentStarted) {
|
|
22945
|
+
const firstLine = parseFirstLine(trimmed);
|
|
22946
|
+
if (firstLine && result.titleLineNumber === null && i === 0) {
|
|
22947
|
+
if (firstLine.chartType !== "treemap") {
|
|
22948
|
+
let msg = `Expected chart type "treemap", got "${firstLine.chartType}"`;
|
|
22949
|
+
const hint = suggest(firstLine.chartType, ["treemap"]);
|
|
22950
|
+
if (hint) msg += `. ${hint}`;
|
|
22951
|
+
return fail(lineNumber, msg);
|
|
22952
|
+
}
|
|
22953
|
+
result.title = firstLine.title ?? null;
|
|
22954
|
+
result.titleLineNumber = lineNumber;
|
|
22955
|
+
continue;
|
|
22956
|
+
}
|
|
22957
|
+
}
|
|
22958
|
+
const tagBlockMatch = matchTagBlockHeading(trimmed);
|
|
22959
|
+
if (tagBlockMatch) {
|
|
22960
|
+
emitTagLegacyDiagnostic(tagBlockMatch, lineNumber, result.diagnostics);
|
|
22961
|
+
if (contentStarted) {
|
|
22962
|
+
pushError(
|
|
22963
|
+
lineNumber,
|
|
22964
|
+
"Tag groups must appear before treemap content",
|
|
22965
|
+
"E_TAG_DECLARED_AFTER_CONTENT"
|
|
22966
|
+
);
|
|
22967
|
+
continue;
|
|
22968
|
+
}
|
|
22969
|
+
currentTagGroup = {
|
|
22970
|
+
name: tagBlockMatch.name,
|
|
22971
|
+
...tagBlockMatch.alias !== void 0 && {
|
|
22972
|
+
alias: tagBlockMatch.alias
|
|
22973
|
+
},
|
|
22974
|
+
entries: [],
|
|
22975
|
+
lineNumber
|
|
22976
|
+
};
|
|
22977
|
+
if (tagBlockMatch.alias) {
|
|
22978
|
+
aliasMap.set(
|
|
22979
|
+
tagBlockMatch.alias.toLowerCase(),
|
|
22980
|
+
tagAttrKey(tagBlockMatch.name)
|
|
22981
|
+
);
|
|
22982
|
+
}
|
|
22983
|
+
aliasMap.set(
|
|
22984
|
+
tagAttrKey(tagBlockMatch.name),
|
|
22985
|
+
tagAttrKey(tagBlockMatch.name)
|
|
22986
|
+
);
|
|
22987
|
+
result.tagGroups.push(currentTagGroup);
|
|
22988
|
+
continue;
|
|
22989
|
+
}
|
|
22990
|
+
if (currentTagGroup && !contentStarted) {
|
|
22991
|
+
const indent2 = measureIndent(line11);
|
|
22992
|
+
if (indent2 > 0) {
|
|
22993
|
+
const { text: cleanEntry, isDefault } = stripDefaultModifier(trimmed);
|
|
22994
|
+
const { label, color } = extractColor(
|
|
22995
|
+
cleanEntry,
|
|
22996
|
+
palette,
|
|
22997
|
+
result.diagnostics,
|
|
22998
|
+
lineNumber
|
|
22999
|
+
);
|
|
23000
|
+
if (isDefault) {
|
|
23001
|
+
currentTagGroup.defaultValue = label;
|
|
23002
|
+
} else if (currentTagGroup.entries.length === 0) {
|
|
23003
|
+
currentTagGroup.defaultValue = label;
|
|
23004
|
+
}
|
|
23005
|
+
currentTagGroup.entries.push({
|
|
23006
|
+
value: label,
|
|
23007
|
+
color: color ?? AUTO_TAG_COLOR_SENTINEL,
|
|
23008
|
+
lineNumber
|
|
23009
|
+
});
|
|
23010
|
+
continue;
|
|
23011
|
+
}
|
|
23012
|
+
currentTagGroup = null;
|
|
23013
|
+
}
|
|
23014
|
+
if (!contentStarted && measureIndent(line11) === 0) {
|
|
23015
|
+
if (handleDirective(trimmed, options, result, pushWarning, lineNumber)) {
|
|
23016
|
+
continue;
|
|
23017
|
+
}
|
|
23018
|
+
}
|
|
23019
|
+
contentStarted = true;
|
|
23020
|
+
currentTagGroup = null;
|
|
23021
|
+
const indent = measureIndent(line11);
|
|
23022
|
+
const node = parseNodeLine3(
|
|
23023
|
+
trimmed,
|
|
23024
|
+
lineNumber,
|
|
23025
|
+
++nodeCounter,
|
|
23026
|
+
aliasMap,
|
|
23027
|
+
result.diagnostics,
|
|
23028
|
+
pushWarning
|
|
23029
|
+
);
|
|
23030
|
+
if (node.heat !== void 0) result.hasHeat = true;
|
|
23031
|
+
attachNode4(node, indent, indentStack, result);
|
|
23032
|
+
}
|
|
23033
|
+
finalizeAutoTagColors(result.tagGroups, palette);
|
|
23034
|
+
const allNodes = [];
|
|
23035
|
+
const collectAll = (nodes) => {
|
|
23036
|
+
for (const n of nodes) {
|
|
23037
|
+
allNodes.push(n);
|
|
23038
|
+
collectAll(n.children);
|
|
23039
|
+
}
|
|
23040
|
+
};
|
|
23041
|
+
collectAll(result.roots);
|
|
23042
|
+
for (const n of allNodes) {
|
|
23043
|
+
const node = n;
|
|
23044
|
+
const isBranch = node.children.length > 0;
|
|
23045
|
+
if (isBranch) {
|
|
23046
|
+
if (node.value !== void 0) {
|
|
23047
|
+
pushWarning(
|
|
23048
|
+
node.lineNumber,
|
|
23049
|
+
`"${node.label}" is a branch \u2014 its trailing number is ignored; the area is the auto-sum of its children`,
|
|
23050
|
+
TREEMAP_DIAGNOSTIC_CODES.BRANCH_VALUE_IGNORED
|
|
23051
|
+
);
|
|
23052
|
+
delete node.value;
|
|
23053
|
+
}
|
|
23054
|
+
} else if (node.value === void 0) {
|
|
23055
|
+
pushWarning(
|
|
23056
|
+
node.lineNumber,
|
|
23057
|
+
`Leaf "${node.label}" has no value \u2014 it renders with zero area`,
|
|
23058
|
+
TREEMAP_DIAGNOSTIC_CODES.LEAF_NO_VALUE
|
|
23059
|
+
);
|
|
23060
|
+
node.value = 0;
|
|
23061
|
+
} else if (node.value < 0) {
|
|
23062
|
+
pushError(
|
|
23063
|
+
node.lineNumber,
|
|
23064
|
+
`Leaf "${node.label}" has a negative value (${node.value}) \u2014 treemap sizes must be \u2265 0`,
|
|
23065
|
+
TREEMAP_DIAGNOSTIC_CODES.NEGATIVE_VALUE
|
|
23066
|
+
);
|
|
23067
|
+
}
|
|
23068
|
+
}
|
|
23069
|
+
if (result.hasHeat || options.heatLabel !== void 0) {
|
|
23070
|
+
result.hasHeat = true;
|
|
23071
|
+
}
|
|
23072
|
+
if (result.tagGroups.length > 0) {
|
|
23073
|
+
validateTagValues(allNodes, result.tagGroups, pushWarning, suggest);
|
|
23074
|
+
validateTagGroupNames(result.tagGroups, pushWarning);
|
|
23075
|
+
cascadeTagMetadata(result.roots, result.tagGroups);
|
|
23076
|
+
}
|
|
23077
|
+
result.defaultColorMode = resolveDefaultColorMode(result);
|
|
23078
|
+
if (result.roots.length === 0 && !result.error) {
|
|
23079
|
+
const diag = makeDgmoError(1, "No nodes found in treemap");
|
|
23080
|
+
result.diagnostics.push(diag);
|
|
23081
|
+
result.error = formatDgmoError(diag);
|
|
23082
|
+
}
|
|
23083
|
+
return result;
|
|
23084
|
+
}
|
|
23085
|
+
function handleDirective(trimmed, options, result, pushWarning, lineNumber) {
|
|
23086
|
+
const depthMatch = trimmed.match(/^depth\s+(-?\d+)\s*$/i);
|
|
23087
|
+
if (depthMatch) {
|
|
23088
|
+
const n = parseInt(depthMatch[1], 10);
|
|
23089
|
+
if (n >= 1) options.maxDepth = n;
|
|
23090
|
+
else pushWarning(lineNumber, '"depth" must be \u2265 1 \u2014 ignored');
|
|
23091
|
+
return true;
|
|
23092
|
+
}
|
|
23093
|
+
if (/^other-below\b/i.test(trimmed)) {
|
|
23094
|
+
pushWarning(
|
|
23095
|
+
lineNumber,
|
|
23096
|
+
'"other-below" is no longer supported \u2014 remove this line'
|
|
23097
|
+
);
|
|
23098
|
+
return true;
|
|
23099
|
+
}
|
|
23100
|
+
const heatMatch = trimmed.match(/^heat\s+(.+)$/i);
|
|
23101
|
+
if (heatMatch) {
|
|
23102
|
+
const { label, low, high } = peelRampColors(heatMatch[1].trim());
|
|
23103
|
+
options.heatLabel = label || "Value";
|
|
23104
|
+
const colors = [];
|
|
23105
|
+
if (low !== void 0) colors.push(low);
|
|
23106
|
+
if (high !== void 0) colors.push(high);
|
|
23107
|
+
options.heatColors = colors;
|
|
23108
|
+
result.hasHeat = true;
|
|
23109
|
+
return true;
|
|
23110
|
+
}
|
|
23111
|
+
const noMatch = trimmed.match(/^no-(values|percent|headers|legend)\s*$/i);
|
|
23112
|
+
if (noMatch) {
|
|
23113
|
+
const key = noMatch[1].toLowerCase();
|
|
23114
|
+
if (key === "values") options.noValues = true;
|
|
23115
|
+
else if (key === "percent") options.noPercent = true;
|
|
23116
|
+
else if (key === "headers") options.noHeaders = true;
|
|
23117
|
+
else if (key === "legend") options.noLegend = true;
|
|
23118
|
+
return true;
|
|
23119
|
+
}
|
|
23120
|
+
return false;
|
|
23121
|
+
}
|
|
23122
|
+
function resolveDefaultColorMode(result) {
|
|
23123
|
+
if (result.tagGroups.length > 0) return "tag";
|
|
23124
|
+
if (result.hasHeat) return "heat";
|
|
23125
|
+
return "branch";
|
|
23126
|
+
}
|
|
23127
|
+
function parseNodeLine3(trimmed, lineNumber, counter, aliasMap, diagnostics, pushWarning) {
|
|
23128
|
+
if (trimmed.includes("|")) {
|
|
23129
|
+
diagnostics.push(
|
|
23130
|
+
makeDgmoError(
|
|
23131
|
+
lineNumber,
|
|
23132
|
+
pipeOperatorRemovedMessage(),
|
|
23133
|
+
"error",
|
|
23134
|
+
METADATA_DIAGNOSTIC_CODES.PIPE_OPERATOR_REMOVED
|
|
23135
|
+
)
|
|
23136
|
+
);
|
|
23137
|
+
}
|
|
23138
|
+
const registry = withTagAliases(TREEMAP_REGISTRY, new Set(aliasMap.keys()));
|
|
23139
|
+
const split = splitNameAndMeta(
|
|
23140
|
+
trimmed,
|
|
23141
|
+
registry,
|
|
23142
|
+
aliasMap,
|
|
23143
|
+
void 0,
|
|
23144
|
+
diagnostics,
|
|
23145
|
+
lineNumber
|
|
23146
|
+
);
|
|
23147
|
+
warnUnknownMetaKeys(
|
|
23148
|
+
split.meta,
|
|
23149
|
+
registry,
|
|
23150
|
+
(msg) => diagnostics.push(makeDgmoError(lineNumber, msg, "warning")),
|
|
23151
|
+
split.name
|
|
23152
|
+
);
|
|
23153
|
+
const metadata = { ...split.meta };
|
|
23154
|
+
let heat;
|
|
23155
|
+
if ("heat" in metadata) {
|
|
23156
|
+
const h = parseFloat(metadata["heat"].replace(/_/g, ""));
|
|
23157
|
+
if (Number.isFinite(h)) heat = h;
|
|
23158
|
+
delete metadata["heat"];
|
|
23159
|
+
}
|
|
23160
|
+
const rawName = split.name;
|
|
23161
|
+
let label;
|
|
23162
|
+
let value;
|
|
23163
|
+
if (isFullyQuoted(rawName)) {
|
|
23164
|
+
label = stripQuotes(rawName);
|
|
23165
|
+
} else {
|
|
23166
|
+
const vm = rawName.match(VALUE_TOKEN_RE);
|
|
23167
|
+
if (vm) {
|
|
23168
|
+
const labelPart = vm[1].trim();
|
|
23169
|
+
const token = vm[2];
|
|
23170
|
+
if (token.includes(",")) {
|
|
23171
|
+
pushWarning(lineNumber, dataCommaRemovedMessage(labelPart));
|
|
23172
|
+
}
|
|
23173
|
+
const cleaned = token.replace(/[_,]/g, "");
|
|
23174
|
+
const parsed = parseFloat(cleaned);
|
|
23175
|
+
if (Number.isFinite(parsed)) {
|
|
23176
|
+
value = parsed;
|
|
23177
|
+
label = isFullyQuoted(labelPart) ? stripQuotes(labelPart) : labelPart;
|
|
23178
|
+
} else {
|
|
23179
|
+
label = rawName;
|
|
23180
|
+
}
|
|
23181
|
+
} else {
|
|
23182
|
+
label = rawName;
|
|
23183
|
+
}
|
|
23184
|
+
}
|
|
23185
|
+
return {
|
|
23186
|
+
id: `treemap-node-${counter}`,
|
|
23187
|
+
label,
|
|
23188
|
+
...value !== void 0 && { value },
|
|
23189
|
+
...heat !== void 0 && { heat },
|
|
23190
|
+
metadata,
|
|
23191
|
+
children: [],
|
|
23192
|
+
lineNumber
|
|
23193
|
+
};
|
|
23194
|
+
}
|
|
23195
|
+
function attachNode4(node, indent, indentStack, result) {
|
|
23196
|
+
while (indentStack.length > 0) {
|
|
23197
|
+
const top = indentStack[indentStack.length - 1];
|
|
23198
|
+
if (top.indent < indent) break;
|
|
23199
|
+
indentStack.pop();
|
|
23200
|
+
}
|
|
23201
|
+
if (indentStack.length > 0) {
|
|
23202
|
+
const parent = indentStack[indentStack.length - 1].node;
|
|
23203
|
+
parent.children.push(node);
|
|
23204
|
+
} else {
|
|
23205
|
+
result.roots.push(node);
|
|
23206
|
+
}
|
|
23207
|
+
indentStack.push({ node, indent });
|
|
23208
|
+
}
|
|
23209
|
+
var TREEMAP_DIAGNOSTIC_CODES, VALUE_TOKEN_RE;
|
|
23210
|
+
var init_parser26 = __esm({
|
|
23211
|
+
"src/treemap/parser.ts"() {
|
|
23212
|
+
"use strict";
|
|
23213
|
+
init_diagnostics();
|
|
23214
|
+
init_tag_groups();
|
|
23215
|
+
init_parsing();
|
|
23216
|
+
init_reserved_key_registry();
|
|
23217
|
+
TREEMAP_DIAGNOSTIC_CODES = {
|
|
23218
|
+
NEGATIVE_VALUE: "E_TREEMAP_NEGATIVE_VALUE",
|
|
23219
|
+
LEAF_NO_VALUE: "W_TREEMAP_LEAF_NO_VALUE",
|
|
23220
|
+
BRANCH_VALUE_IGNORED: "W_TREEMAP_BRANCH_VALUE_IGNORED"
|
|
23221
|
+
};
|
|
23222
|
+
VALUE_TOKEN_RE = /^(.+?)\s+(-?\d[\d_,.]*)$/;
|
|
23223
|
+
}
|
|
23224
|
+
});
|
|
23225
|
+
|
|
22844
23226
|
// src/raci/variants.ts
|
|
22845
23227
|
function inferVariant(markers) {
|
|
22846
23228
|
let hasD = false;
|
|
@@ -23095,8 +23477,8 @@ var init_variants = __esm({
|
|
|
23095
23477
|
});
|
|
23096
23478
|
|
|
23097
23479
|
// src/raci/parser.ts
|
|
23098
|
-
var
|
|
23099
|
-
__export(
|
|
23480
|
+
var parser_exports21 = {};
|
|
23481
|
+
__export(parser_exports21, {
|
|
23100
23482
|
allTasks: () => allTasks,
|
|
23101
23483
|
parseRaci: () => parseRaci
|
|
23102
23484
|
});
|
|
@@ -23617,7 +23999,7 @@ function* allTasks(parsed) {
|
|
|
23617
23999
|
}
|
|
23618
24000
|
}
|
|
23619
24001
|
var RACI_CHART_TYPE_IDS, CHART_TYPE_VARIANT_LOCK, VARIANT_LOCK_DIRECTIVES, KNOWN_OPTIONS10, KNOWN_BOOLEANS7, REMOVED_BOOLEANS3, PHASE_RE2, PHASE_PALETTE_COLOR_RE, ROLE_ASSIGNMENT_RE;
|
|
23620
|
-
var
|
|
24002
|
+
var init_parser27 = __esm({
|
|
23621
24003
|
"src/raci/parser.ts"() {
|
|
23622
24004
|
"use strict";
|
|
23623
24005
|
init_diagnostics();
|
|
@@ -23863,6 +24245,7 @@ var init_chart_type_registry = __esm({
|
|
|
23863
24245
|
init_parser24();
|
|
23864
24246
|
init_parser25();
|
|
23865
24247
|
init_parser26();
|
|
24248
|
+
init_parser27();
|
|
23866
24249
|
CHART_TYPE_REGISTRY = [
|
|
23867
24250
|
// ── Structured diagrams ───────────────────────────────────
|
|
23868
24251
|
{
|
|
@@ -24003,6 +24386,9 @@ var init_chart_type_registry = __esm({
|
|
|
24003
24386
|
{ id: "cycle", category: "visualization", parse: parseCycle },
|
|
24004
24387
|
{ id: "pyramid", category: "visualization", parse: parsePyramid },
|
|
24005
24388
|
{ id: "ring", category: "visualization", parse: parseRing },
|
|
24389
|
+
// Treemap: squarified hierarchy. No measure/minDims — a treemap fills whatever
|
|
24390
|
+
// rectangle it's given and has no intrinsic aspect/size (F11).
|
|
24391
|
+
{ id: "treemap", category: "visualization", parse: parseTreemap },
|
|
24006
24392
|
// ── Geographic map (own parser → resolver → layout → renderer) ──
|
|
24007
24393
|
{ id: "map", category: "visualization", parse: parseMap }
|
|
24008
24394
|
];
|
|
@@ -26735,10 +27121,10 @@ async function renderSitemapForExport(content, theme, palette) {
|
|
|
26735
27121
|
const parsed = parseSitemap2(content, effectivePalette);
|
|
26736
27122
|
if (parsed.error || parsed.roots.length === 0) return "";
|
|
26737
27123
|
const sitemapLayout = layoutSitemap2(parsed, void 0, null, void 0, true);
|
|
26738
|
-
const
|
|
27124
|
+
const PADDING4 = 20;
|
|
26739
27125
|
const titleOffset = parsed.title ? 30 : 0;
|
|
26740
|
-
const exportWidth = sitemapLayout.width +
|
|
26741
|
-
const exportHeight = sitemapLayout.height +
|
|
27126
|
+
const exportWidth = sitemapLayout.width + PADDING4 * 2;
|
|
27127
|
+
const exportHeight = sitemapLayout.height + PADDING4 * 2 + titleOffset;
|
|
26742
27128
|
const container = document.createElement("div");
|
|
26743
27129
|
container.style.width = `${exportWidth}px`;
|
|
26744
27130
|
container.style.height = `${exportHeight}px`;
|
|
@@ -31766,6 +32152,10 @@ async function layoutBoxesAndLinesSearch(parsed, collapseInfo, opts) {
|
|
|
31766
32152
|
const reserveEdgeLabels = opts?.reserveEdgeLabels ?? false;
|
|
31767
32153
|
const onProgress = opts?.onProgress;
|
|
31768
32154
|
const tick = onProgress ? () => new Promise((r) => setTimeout(r)) : () => void 0;
|
|
32155
|
+
const YIELD_AFTER_MS = 150;
|
|
32156
|
+
const YIELD_EVERY_MS = 30;
|
|
32157
|
+
const searchStart = performance.now();
|
|
32158
|
+
let lastYield = searchStart;
|
|
31769
32159
|
const collapsedGroupLabels = /* @__PURE__ */ new Set();
|
|
31770
32160
|
if (collapseInfo) {
|
|
31771
32161
|
const missing = /* @__PURE__ */ new Set();
|
|
@@ -32195,7 +32585,11 @@ async function layoutBoxesAndLinesSearch(parsed, collapseInfo, opts) {
|
|
|
32195
32585
|
const step = async (phase) => {
|
|
32196
32586
|
if (!onProgress) return;
|
|
32197
32587
|
onProgress(++progressDone, progressTotal, phase);
|
|
32198
|
-
|
|
32588
|
+
const now = performance.now();
|
|
32589
|
+
if (now - searchStart > YIELD_AFTER_MS && now - lastYield > YIELD_EVERY_MS) {
|
|
32590
|
+
lastYield = now;
|
|
32591
|
+
await tick();
|
|
32592
|
+
}
|
|
32199
32593
|
};
|
|
32200
32594
|
const pool = [];
|
|
32201
32595
|
for (const cfg of configs) {
|
|
@@ -50585,7 +50979,7 @@ function computeEdgeLabelPosition(midAngle, radius, cx, cy, lineCount, labelPxW,
|
|
|
50585
50979
|
};
|
|
50586
50980
|
}
|
|
50587
50981
|
function fitToCanvas(nodes, edges, parsed, _cx, _cy, radius, width, height, _isClockwise) {
|
|
50588
|
-
const
|
|
50982
|
+
const PADDING4 = 30;
|
|
50589
50983
|
let contentMinX = Infinity, contentMaxX = -Infinity;
|
|
50590
50984
|
let contentMinY = Infinity, contentMaxY = -Infinity;
|
|
50591
50985
|
for (const n of nodes) {
|
|
@@ -50627,13 +51021,13 @@ function fitToCanvas(nodes, edges, parsed, _cx, _cy, radius, width, height, _isC
|
|
|
50627
51021
|
contentMinY = Math.min(contentMinY, le.labelY - 12);
|
|
50628
51022
|
contentMaxY = Math.max(contentMaxY, le.labelY + (lineCount - 1) * 15);
|
|
50629
51023
|
}
|
|
50630
|
-
const overflowX = Math.max(0,
|
|
50631
|
-
const overflowY = Math.max(0,
|
|
51024
|
+
const overflowX = Math.max(0, PADDING4 - contentMinX) + Math.max(0, contentMaxX - (width - PADDING4));
|
|
51025
|
+
const overflowY = Math.max(0, PADDING4 - contentMinY) + Math.max(0, contentMaxY - (height - PADDING4));
|
|
50632
51026
|
if (overflowX <= 0 && overflowY <= 0) return null;
|
|
50633
51027
|
const contentW = contentMaxX - contentMinX;
|
|
50634
51028
|
const contentH = contentMaxY - contentMinY;
|
|
50635
|
-
const availW = width - 2 *
|
|
50636
|
-
const availH = height - 2 *
|
|
51029
|
+
const availW = width - 2 * PADDING4;
|
|
51030
|
+
const availH = height - 2 * PADDING4;
|
|
50637
51031
|
const shrink = Math.min(availW / contentW, availH / contentH);
|
|
50638
51032
|
const newRadius = Math.max(80, radius * shrink);
|
|
50639
51033
|
return { radius: newRadius };
|
|
@@ -50831,7 +51225,7 @@ function renderCycle(container, parsed, palette, isDark, onClickItem, exportDims
|
|
|
50831
51225
|
}
|
|
50832
51226
|
edgeLabelInfo.push({ le, edge });
|
|
50833
51227
|
}
|
|
50834
|
-
const
|
|
51228
|
+
const HEADER_H2 = 36 * layout.scale;
|
|
50835
51229
|
const scaledNodeFont = Math.max(6, Math.round(NODE_FONT_SIZE7 * layout.scale));
|
|
50836
51230
|
const scaledEdgeLabelFont = Math.max(
|
|
50837
51231
|
6,
|
|
@@ -50895,10 +51289,10 @@ function renderCycle(container, parsed, palette, isDark, onClickItem, exportDims
|
|
|
50895
51289
|
const rx = 6;
|
|
50896
51290
|
nodeG.append("rect").attr("x", ln.x - nodeW / 2).attr("y", ln.y - nodeH / 2).attr("width", nodeW).attr("height", nodeH).attr("rx", rx).attr("ry", rx).attr("fill", fillColor).attr("stroke", solidColor).attr("stroke-width", 2);
|
|
50897
51291
|
if (hasDesc) {
|
|
50898
|
-
const headerCenterY = ln.y - nodeH / 2 +
|
|
51292
|
+
const headerCenterY = ln.y - nodeH / 2 + HEADER_H2 / 2;
|
|
50899
51293
|
const labelText = nodeG.append("text").attr("x", ln.x).attr("y", headerCenterY + scaledNodeFont / 3).attr("text-anchor", "middle").attr("fill", textColor).attr("font-family", FONT_FAMILY).attr("font-size", scaledNodeFont).attr("font-weight", "600");
|
|
50900
51294
|
renderInlineText(labelText, node.label, palette, scaledNodeFont);
|
|
50901
|
-
const sepY = ln.y - nodeH / 2 +
|
|
51295
|
+
const sepY = ln.y - nodeH / 2 + HEADER_H2;
|
|
50902
51296
|
nodeG.append("line").attr("x1", ln.x - nodeW / 2).attr("y1", sepY).attr("x2", ln.x + nodeW / 2).attr("y2", sepY).attr("stroke", solid ? descColor : solidColor).attr("stroke-opacity", 0.3).attr("stroke-width", 1);
|
|
50903
51297
|
const descStartY = sepY + 4 + scaledDescFont;
|
|
50904
51298
|
const descPadX = Math.max(8, 12 * layout.scale);
|
|
@@ -53718,13 +54112,15 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
53718
54112
|
labelY: lp.y
|
|
53719
54113
|
};
|
|
53720
54114
|
const routeLabelStyle = leg.label !== void 0 ? labelOnFill(fillAt(bow.labelX, bow.labelY)) : void 0;
|
|
54115
|
+
const routeVal = Number(leg.value);
|
|
53721
54116
|
legs.push({
|
|
53722
54117
|
d: legPath(a, b, bow.curved, bow.offset),
|
|
53723
|
-
width: routeWidthFor(
|
|
54118
|
+
width: routeWidthFor(routeVal),
|
|
53724
54119
|
color: lineColor(leg.tags) ?? mix(palette.text, palette.bg, 72),
|
|
53725
54120
|
arrow: true,
|
|
53726
54121
|
fromId: leg.fromId,
|
|
53727
54122
|
toId: leg.toId,
|
|
54123
|
+
...Number.isFinite(routeVal) && routeVal > 0 && { value: routeVal },
|
|
53728
54124
|
...Object.keys(leg.tags).length > 0 && { tags: leg.tags },
|
|
53729
54125
|
lineNumber: leg.lineNumber,
|
|
53730
54126
|
...leg.label !== void 0 && {
|
|
@@ -53771,6 +54167,7 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
53771
54167
|
labelY: lp.y
|
|
53772
54168
|
};
|
|
53773
54169
|
const edgeLabelStyle = e.label !== void 0 ? labelOnFill(fillAt(bow.labelX, bow.labelY)) : void 0;
|
|
54170
|
+
const edgeVal = Number(e.meta["value"]);
|
|
53774
54171
|
legs.push({
|
|
53775
54172
|
d: legPath(a, b, bow.curved, bow.offset),
|
|
53776
54173
|
width: widthFor(e),
|
|
@@ -53778,6 +54175,7 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
53778
54175
|
arrow: e.directed,
|
|
53779
54176
|
fromId: e.fromId,
|
|
53780
54177
|
toId: e.toId,
|
|
54178
|
+
...Number.isFinite(edgeVal) && edgeVal > 0 && { value: edgeVal },
|
|
53781
54179
|
...Object.keys(e.tags).length > 0 && { tags: e.tags },
|
|
53782
54180
|
lineNumber: e.lineNumber,
|
|
53783
54181
|
...e.label !== void 0 && {
|
|
@@ -53935,18 +54333,49 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
53935
54333
|
const SHORT_HOP_MAX = Math.max(46, Math.min(width, height) * 0.11);
|
|
53936
54334
|
const STEP = 4;
|
|
53937
54335
|
const HOP_GAP = 9;
|
|
54336
|
+
const CLEAR_STEP = 6;
|
|
54337
|
+
const CLEAR_MAX = SHORT_HOP_MAX * 3;
|
|
54338
|
+
const CLEAR_TOL = CLEAR_STEP;
|
|
54339
|
+
const clearanceAt = (px, py, ox, oy) => {
|
|
54340
|
+
const baseAng = Math.atan2(oy, ox);
|
|
54341
|
+
let minClear = CLEAR_MAX;
|
|
54342
|
+
for (let k = -2; k <= 2; k++) {
|
|
54343
|
+
const a = baseAng + k * Math.PI / 4;
|
|
54344
|
+
const rx = Math.cos(a);
|
|
54345
|
+
const ry = Math.sin(a);
|
|
54346
|
+
let d = CLEAR_STEP;
|
|
54347
|
+
for (; d <= CLEAR_MAX; d += CLEAR_STEP) {
|
|
54348
|
+
const qx = px + rx * d;
|
|
54349
|
+
const qy = py + ry * d;
|
|
54350
|
+
if (qx < FIT_PAD || qy < topPad || qx > width - FIT_PAD || qy > height - FIT_PAD)
|
|
54351
|
+
break;
|
|
54352
|
+
if (fillAt(qx, qy) !== water) break;
|
|
54353
|
+
}
|
|
54354
|
+
if (d < minClear) minClear = d;
|
|
54355
|
+
}
|
|
54356
|
+
return minClear;
|
|
54357
|
+
};
|
|
53938
54358
|
const tryShortHopCallout = (cx, cy, fill2, name, value, font = FONT2, gap = HOP_GAP, maxLen = SHORT_HOP_MAX) => {
|
|
53939
54359
|
const chipW = stackW(name, value, font);
|
|
53940
54360
|
const chipH = stackH(value !== void 0, font);
|
|
54361
|
+
const D = Math.SQRT1_2;
|
|
53941
54362
|
const dirs = [
|
|
53942
54363
|
[0, -1],
|
|
53943
|
-
// north
|
|
54364
|
+
// north
|
|
53944
54365
|
[0, 1],
|
|
53945
|
-
// south
|
|
54366
|
+
// south
|
|
53946
54367
|
[1, 0],
|
|
53947
|
-
// east
|
|
53948
|
-
[-1, 0]
|
|
53949
|
-
// west
|
|
54368
|
+
// east
|
|
54369
|
+
[-1, 0],
|
|
54370
|
+
// west
|
|
54371
|
+
[D, -D],
|
|
54372
|
+
// NE
|
|
54373
|
+
[D, D],
|
|
54374
|
+
// SE
|
|
54375
|
+
[-D, -D],
|
|
54376
|
+
// NW
|
|
54377
|
+
[-D, D]
|
|
54378
|
+
// SW
|
|
53950
54379
|
];
|
|
53951
54380
|
let best = null;
|
|
53952
54381
|
for (const [dx, dy] of dirs) {
|
|
@@ -53996,13 +54425,16 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
53996
54425
|
(p) => segmentRectOverlap(cx, cy, innerX, innerY, p)
|
|
53997
54426
|
))
|
|
53998
54427
|
continue;
|
|
53999
|
-
|
|
54428
|
+
const clear = clearanceAt(ccx, ccy, dx, dy);
|
|
54429
|
+
const better = best === null || clear > best.clear + CLEAR_TOL || clear >= best.clear - CLEAR_TOL && len < best.len;
|
|
54430
|
+
if (better)
|
|
54000
54431
|
best = {
|
|
54001
54432
|
x: ccx,
|
|
54002
54433
|
y: ccy,
|
|
54003
54434
|
rect,
|
|
54004
54435
|
leader: [cx, cy, innerX, innerY],
|
|
54005
|
-
len
|
|
54436
|
+
len,
|
|
54437
|
+
clear
|
|
54006
54438
|
};
|
|
54007
54439
|
}
|
|
54008
54440
|
return best ? { x: best.x, y: best.y, rect: best.rect, leader: best.leader } : null;
|
|
@@ -54663,6 +55095,9 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54663
55095
|
const nx = -dy / len;
|
|
54664
55096
|
const ny = dx / len;
|
|
54665
55097
|
const perp = labelH + 2;
|
|
55098
|
+
const stroke2 = lg.width ?? W_MIN;
|
|
55099
|
+
const clearW = stroke2 / 2 + labelH / 2 + 3;
|
|
55100
|
+
const offList = stroke2 >= 4 ? [clearW, -clearW, clearW + perp, -(clearW + perp), 0] : [0, perp, -perp, 2 * perp, -2 * perp];
|
|
54666
55101
|
const pm = /^M(-?[\d.]+),(-?[\d.]+)(?:L(-?[\d.]+),(-?[\d.]+)|Q(-?[\d.]+),(-?[\d.]+) (-?[\d.]+),(-?[\d.]+))$/.exec(
|
|
54667
55102
|
lg.d
|
|
54668
55103
|
);
|
|
@@ -54682,7 +55117,7 @@ function layoutMap(resolvedIn, data, size, opts) {
|
|
|
54682
55117
|
return [a.cx + dx * t, a.cy + dy * t];
|
|
54683
55118
|
};
|
|
54684
55119
|
const candidates = [];
|
|
54685
|
-
for (const off of
|
|
55120
|
+
for (const off of offList)
|
|
54686
55121
|
for (const t of T_LIST) {
|
|
54687
55122
|
const [bx, by] = pointAt(t);
|
|
54688
55123
|
candidates.push([bx + nx * off, by + ny * off - 4]);
|
|
@@ -55434,6 +55869,12 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
55434
55869
|
}
|
|
55435
55870
|
}
|
|
55436
55871
|
wireSync(p, leg.lineNumber);
|
|
55872
|
+
if (leg.value !== void 0) {
|
|
55873
|
+
p.attr("data-value", leg.value);
|
|
55874
|
+
p.append("title").text(
|
|
55875
|
+
leg.label !== void 0 ? `${leg.label}: ${leg.value}` : `${leg.value}`
|
|
55876
|
+
);
|
|
55877
|
+
}
|
|
55437
55878
|
if (arrowTri) {
|
|
55438
55879
|
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);
|
|
55439
55880
|
}
|
|
@@ -55663,7 +56104,9 @@ function mapContentAspect(resolved, data, ref = REF) {
|
|
|
55663
56104
|
function mapExportDimensions(resolved, data, baseWidth = 1200, aspectOverride) {
|
|
55664
56105
|
const useOverride = aspectOverride !== void 0 && Number.isFinite(aspectOverride) && aspectOverride > 0;
|
|
55665
56106
|
const raw = useOverride ? aspectOverride : mapContentAspect(resolved, data);
|
|
55666
|
-
const
|
|
56107
|
+
const isGlobal = !useOverride && buildMapProjection(resolved, data).fitIsGlobal;
|
|
56108
|
+
const target = isGlobal ? raw / GLOBAL_HEIGHT_BOOST : raw;
|
|
56109
|
+
const clamped = useOverride ? raw : Math.max(ASPECT_MIN, Math.min(ASPECT_MAX, target));
|
|
55667
56110
|
const width = baseWidth;
|
|
55668
56111
|
let height = Math.round(width / clamped);
|
|
55669
56112
|
let chromeReserve = 0;
|
|
@@ -55676,10 +56119,10 @@ function mapExportDimensions(resolved, data, baseWidth = 1200, aspectOverride) {
|
|
|
55676
56119
|
height = Math.round(chromeReserve + MIN_MAP_BAND);
|
|
55677
56120
|
floored = true;
|
|
55678
56121
|
}
|
|
55679
|
-
const preferContain = useOverride ? floored : clamped !==
|
|
56122
|
+
const preferContain = useOverride ? floored : clamped !== target || floored;
|
|
55680
56123
|
return { width, height, preferContain };
|
|
55681
56124
|
}
|
|
55682
|
-
var import_d3_geo3, FIT_PAD2, TITLE_GAP, ASPECT_MAX, ASPECT_MIN, MIN_MAP_BAND, FALLBACK_ASPECT, REF;
|
|
56125
|
+
var import_d3_geo3, FIT_PAD2, TITLE_GAP, ASPECT_MAX, ASPECT_MIN, GLOBAL_HEIGHT_BOOST, MIN_MAP_BAND, FALLBACK_ASPECT, REF;
|
|
55683
56126
|
var init_dimensions = __esm({
|
|
55684
56127
|
"src/map/dimensions.ts"() {
|
|
55685
56128
|
"use strict";
|
|
@@ -55690,6 +56133,7 @@ var init_dimensions = __esm({
|
|
|
55690
56133
|
TITLE_GAP = 16;
|
|
55691
56134
|
ASPECT_MAX = 3;
|
|
55692
56135
|
ASPECT_MIN = 0.9;
|
|
56136
|
+
GLOBAL_HEIGHT_BOOST = 1.12;
|
|
55693
56137
|
MIN_MAP_BAND = 200;
|
|
55694
56138
|
FALLBACK_ASPECT = 1.5;
|
|
55695
56139
|
REF = 1e3;
|
|
@@ -56479,9 +56923,469 @@ var init_renderer18 = __esm({
|
|
|
56479
56923
|
}
|
|
56480
56924
|
});
|
|
56481
56925
|
|
|
56482
|
-
// src/
|
|
56926
|
+
// src/treemap/layout.ts
|
|
56927
|
+
function toDatum(node) {
|
|
56928
|
+
if (node.children.length === 0) {
|
|
56929
|
+
return {
|
|
56930
|
+
ref: node,
|
|
56931
|
+
label: node.label,
|
|
56932
|
+
value: node.value ?? 0,
|
|
56933
|
+
...node.heat !== void 0 && { heat: node.heat },
|
|
56934
|
+
lineNumber: node.lineNumber
|
|
56935
|
+
};
|
|
56936
|
+
}
|
|
56937
|
+
return {
|
|
56938
|
+
ref: node,
|
|
56939
|
+
label: node.label,
|
|
56940
|
+
...node.heat !== void 0 && { heat: node.heat },
|
|
56941
|
+
lineNumber: node.lineNumber,
|
|
56942
|
+
children: node.children.map((c) => toDatum(c))
|
|
56943
|
+
};
|
|
56944
|
+
}
|
|
56945
|
+
function datumHeat(node) {
|
|
56946
|
+
if (node.data.heat !== void 0) return node.data.heat;
|
|
56947
|
+
const xs = [];
|
|
56948
|
+
for (const l of node.leaves()) {
|
|
56949
|
+
if (l.data.heat !== void 0) xs.push(l.data.heat);
|
|
56950
|
+
}
|
|
56951
|
+
if (xs.length === 0) return void 0;
|
|
56952
|
+
return xs.reduce((a, b) => a + b, 0) / xs.length;
|
|
56953
|
+
}
|
|
56954
|
+
function layoutTreemap(roots, opts) {
|
|
56955
|
+
const maxDepth = opts.maxDepth ?? Infinity;
|
|
56956
|
+
const rootDatum = {
|
|
56957
|
+
label: "__root",
|
|
56958
|
+
children: roots.map((r) => toDatum(r))
|
|
56959
|
+
};
|
|
56960
|
+
const h = (0, import_d3_hierarchy2.hierarchy)(rootDatum).sum((d) => d.children?.length ? 0 : d.value ?? 0).sort((a, b) => (b.value ?? 0) - (a.value ?? 0));
|
|
56961
|
+
const hroot = (0, import_d3_hierarchy2.treemap)().tile(import_d3_hierarchy2.treemapSquarify).size([opts.width, opts.height]).paddingOuter(opts.paddingOuter ?? 3).paddingTop(opts.headerH > 0 ? opts.headerH : opts.paddingInner ?? 2).paddingInner(opts.paddingInner ?? 2).round(true)(h);
|
|
56962
|
+
const total = hroot.value ?? 0;
|
|
56963
|
+
(hroot.children ?? []).forEach((top, i) => {
|
|
56964
|
+
top.each((d) => {
|
|
56965
|
+
d._topIndex = i;
|
|
56966
|
+
});
|
|
56967
|
+
});
|
|
56968
|
+
const cells = [];
|
|
56969
|
+
for (const d of hroot.descendants()) {
|
|
56970
|
+
if (d.depth === 0) continue;
|
|
56971
|
+
if (d.depth > maxDepth) continue;
|
|
56972
|
+
const hasChildren = !!d.children && d.children.length > 0;
|
|
56973
|
+
const isCollapsed = hasChildren && d.depth >= maxDepth;
|
|
56974
|
+
const isContainer = hasChildren && !isCollapsed;
|
|
56975
|
+
const path = [];
|
|
56976
|
+
let p = d;
|
|
56977
|
+
while (p && p.depth > 0) {
|
|
56978
|
+
path.unshift(p.data.label);
|
|
56979
|
+
p = p.parent;
|
|
56980
|
+
}
|
|
56981
|
+
const heatVal = datumHeat(d);
|
|
56982
|
+
cells.push({
|
|
56983
|
+
node: d.data.ref ?? null,
|
|
56984
|
+
label: d.data.label,
|
|
56985
|
+
x0: d.x0,
|
|
56986
|
+
y0: d.y0,
|
|
56987
|
+
x1: d.x1,
|
|
56988
|
+
y1: d.y1,
|
|
56989
|
+
depth: d.depth,
|
|
56990
|
+
value: d.value ?? 0,
|
|
56991
|
+
isContainer,
|
|
56992
|
+
isCollapsed,
|
|
56993
|
+
topIndex: d._topIndex ?? 0,
|
|
56994
|
+
pctOfRoot: total > 0 ? (d.value ?? 0) / total : 0,
|
|
56995
|
+
pctOfParent: d.parent && (d.parent.value ?? 0) > 0 ? (d.value ?? 0) / (d.parent.value ?? 1) : 1,
|
|
56996
|
+
...heatVal !== void 0 && { heat: heatVal },
|
|
56997
|
+
path,
|
|
56998
|
+
...d.data.lineNumber !== void 0 && { lineNumber: d.data.lineNumber }
|
|
56999
|
+
});
|
|
57000
|
+
}
|
|
57001
|
+
return { cells, total };
|
|
57002
|
+
}
|
|
57003
|
+
var import_d3_hierarchy2;
|
|
57004
|
+
var init_layout16 = __esm({
|
|
57005
|
+
"src/treemap/layout.ts"() {
|
|
57006
|
+
"use strict";
|
|
57007
|
+
import_d3_hierarchy2 = require("d3-hierarchy");
|
|
57008
|
+
}
|
|
57009
|
+
});
|
|
57010
|
+
|
|
57011
|
+
// src/treemap/renderer.ts
|
|
56483
57012
|
var renderer_exports19 = {};
|
|
56484
57013
|
__export(renderer_exports19, {
|
|
57014
|
+
compactNumber: () => compactNumber2,
|
|
57015
|
+
renderTreemap: () => renderTreemap,
|
|
57016
|
+
renderTreemapForExport: () => renderTreemapForExport
|
|
57017
|
+
});
|
|
57018
|
+
function renderTreemapForExport(container, parsed, palette, isDark, exportDims, options) {
|
|
57019
|
+
renderTreemap(container, parsed, palette, isDark, exportDims, {
|
|
57020
|
+
exportMode: true,
|
|
57021
|
+
...options
|
|
57022
|
+
});
|
|
57023
|
+
}
|
|
57024
|
+
function renderTreemap(container, parsed, palette, isDark, exportDims, options = {}) {
|
|
57025
|
+
if (parsed.error || parsed.roots.length === 0) return;
|
|
57026
|
+
void isDark;
|
|
57027
|
+
d3Selection26.select(container).selectAll(":not([data-d3-tooltip])").remove();
|
|
57028
|
+
const width = exportDims?.width ?? container.clientWidth;
|
|
57029
|
+
const height = exportDims?.height ?? container.clientHeight;
|
|
57030
|
+
if (width <= 0 || height <= 0) return;
|
|
57031
|
+
const mode = resolveColorMode(parsed, options.colorMode);
|
|
57032
|
+
const opts = parsed.options;
|
|
57033
|
+
const exportMode = options.exportMode ?? false;
|
|
57034
|
+
const seriesColorsTop = getSeriesColors(palette);
|
|
57035
|
+
const showTitle = !!parsed.title;
|
|
57036
|
+
const titleH = showTitle ? TITLE_BAND : 0;
|
|
57037
|
+
const heat = buildHeatScale(parsed, palette);
|
|
57038
|
+
const legend = !opts.noLegend ? buildLegend(mode, parsed, heat, seriesColorsTop, options.colorOffset ?? 0) : null;
|
|
57039
|
+
const legendReserve = legend ? getMaxLegendReservedHeight(
|
|
57040
|
+
{ groups: legend.groups, position: LEGEND_POSITION, mode: "preview" },
|
|
57041
|
+
width
|
|
57042
|
+
) + LEGEND_GROUP_GAP : 0;
|
|
57043
|
+
const headerH = opts.noHeaders ? 0 : HEADER_H;
|
|
57044
|
+
const areaX = PADDING3;
|
|
57045
|
+
const areaY = titleH + legendReserve + PADDING3;
|
|
57046
|
+
const areaW = Math.max(1, width - PADDING3 * 2);
|
|
57047
|
+
const areaH = Math.max(1, height - areaY - PADDING3);
|
|
57048
|
+
const layout = layoutTreemap(parsed.roots, {
|
|
57049
|
+
width: areaW,
|
|
57050
|
+
height: areaH,
|
|
57051
|
+
headerH,
|
|
57052
|
+
...options.maxDepth !== void 0 && { maxDepth: options.maxDepth }
|
|
57053
|
+
});
|
|
57054
|
+
const svg = d3Selection26.select(container).append("svg").attr("width", width).attr("height", height).attr("viewBox", `0 0 ${width} ${height}`).attr("preserveAspectRatio", "xMidYMin meet").attr("xmlns", "http://www.w3.org/2000/svg").attr("class", "dgmo-treemap").style("font-family", FONT_FAMILY);
|
|
57055
|
+
svg.append("style").text(
|
|
57056
|
+
".dgmo-treemap-focus{opacity:.3;transition:opacity .12s}.dgmo-treemap-cell:hover .dgmo-treemap-focus{opacity:.7}"
|
|
57057
|
+
);
|
|
57058
|
+
svg.append("rect").attr("width", width).attr("height", height).attr("fill", palette.bg);
|
|
57059
|
+
if (showTitle) {
|
|
57060
|
+
const title = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", TITLE_Y).attr("text-anchor", "middle").attr("fill", palette.text).attr("font-family", FONT_FAMILY).attr("font-size", TITLE_FONT_SIZE).attr("font-weight", TITLE_FONT_WEIGHT).text(parsed.title);
|
|
57061
|
+
if (parsed.titleLineNumber !== null) {
|
|
57062
|
+
title.attr("data-line-number", parsed.titleLineNumber);
|
|
57063
|
+
}
|
|
57064
|
+
}
|
|
57065
|
+
const root = svg.append("g").attr("class", "dgmo-treemap-cells").attr("transform", `translate(${areaX},${areaY})`);
|
|
57066
|
+
const seriesColors2 = seriesColorsTop;
|
|
57067
|
+
const colorOffset = options.colorOffset ?? 0;
|
|
57068
|
+
const activeGroup = parsed.tagGroups.length > 0 ? parsed.tagGroups[0].name : null;
|
|
57069
|
+
const rootIndexByLabel = new Map(parsed.roots.map((r, i) => [r.label, i]));
|
|
57070
|
+
const colorOf = (cell) => {
|
|
57071
|
+
if (mode === "heat") {
|
|
57072
|
+
return cell.heat !== void 0 && heat ? heat.scale(cell.heat) : MUTED_FILL;
|
|
57073
|
+
}
|
|
57074
|
+
if (mode === "tag") {
|
|
57075
|
+
if (!cell.node) return MUTED_FILL;
|
|
57076
|
+
return resolveTagColor(cell.node.metadata, parsed.tagGroups, activeGroup) ?? MUTED_FILL;
|
|
57077
|
+
}
|
|
57078
|
+
const topLabel = cell.path[0] ?? cell.label;
|
|
57079
|
+
const idx = (rootIndexByLabel.get(topLabel) ?? cell.topIndex) + colorOffset;
|
|
57080
|
+
const hue = seriesColors2[idx % seriesColors2.length];
|
|
57081
|
+
if (cell.depth <= 1) return hue;
|
|
57082
|
+
const keepPct = Math.max(55, 100 - (cell.depth - 1) * 18);
|
|
57083
|
+
return mix(hue, palette.bg, keepPct);
|
|
57084
|
+
};
|
|
57085
|
+
for (const cell of layout.cells) {
|
|
57086
|
+
const w = Math.max(0, cell.x1 - cell.x0);
|
|
57087
|
+
const h = Math.max(0, cell.y1 - cell.y0);
|
|
57088
|
+
if (w <= 0 || h <= 0) continue;
|
|
57089
|
+
const baseColor = colorOf(cell);
|
|
57090
|
+
const fill2 = cell.isContainer ? baseColor : mix(baseColor, palette.bg, LEAF_MUTE_PCT);
|
|
57091
|
+
const drillable = cell.isContainer || cell.isCollapsed;
|
|
57092
|
+
const g = root.append("g").attr("class", "dgmo-treemap-cell").attr("transform", `translate(${cell.x0},${cell.y0})`).attr("data-node-path", cell.path.join(" / "));
|
|
57093
|
+
if (cell.lineNumber !== void 0) {
|
|
57094
|
+
g.attr("data-line-number", cell.lineNumber);
|
|
57095
|
+
}
|
|
57096
|
+
if (cell.heat !== void 0) g.attr("data-heat", cell.heat);
|
|
57097
|
+
if (cell.node && activeGroup) {
|
|
57098
|
+
const key = tagAttrKey(activeGroup);
|
|
57099
|
+
const tagVal = cell.node.metadata[key];
|
|
57100
|
+
if (tagVal) g.attr(`data-tag-${key}`, tagVal);
|
|
57101
|
+
}
|
|
57102
|
+
const rect = g.append("rect").attr(
|
|
57103
|
+
"class",
|
|
57104
|
+
cell.isContainer ? "dgmo-treemap-rect branch" : "dgmo-treemap-rect"
|
|
57105
|
+
).attr("width", w).attr("height", h).attr("rx", 2).attr("fill", fill2).attr("fill-opacity", 1).attr("stroke", palette.bg).attr("stroke-width", cell.isContainer ? 1 : 0);
|
|
57106
|
+
if (drillable && options.onClickItem && cell.lineNumber !== void 0) {
|
|
57107
|
+
const ln = cell.lineNumber;
|
|
57108
|
+
rect.style("cursor", "pointer").on("click", () => options.onClickItem(ln));
|
|
57109
|
+
}
|
|
57110
|
+
const ink = contrastText(
|
|
57111
|
+
fill2,
|
|
57112
|
+
palette.textOnFillLight,
|
|
57113
|
+
palette.textOnFillDark
|
|
57114
|
+
);
|
|
57115
|
+
if (cell.isContainer && headerH > 0 && w > 34 && h > headerH) {
|
|
57116
|
+
const valParts = [];
|
|
57117
|
+
if (!opts.noValues) valParts.push(compactNumber2(cell.value));
|
|
57118
|
+
if (!opts.noPercent) valParts.push(formatPct(cell.pctOfRoot));
|
|
57119
|
+
const valStr = valParts.join(" \xB7 ");
|
|
57120
|
+
const ICON_RESERVE = drillable ? 16 : 4;
|
|
57121
|
+
const showVal = valStr.length > 0 && w > 110;
|
|
57122
|
+
const valW = showVal ? measureText(valStr, 10.5) : 0;
|
|
57123
|
+
const labelMax = w - 8 - ICON_RESERVE - (showVal ? valW + 10 : 0);
|
|
57124
|
+
g.append("text").attr("class", "dgmo-treemap-header").attr("x", 6).attr("y", 13).attr("font-size", 11).attr("font-weight", 700).attr("fill", ink).text(clipLabel(cell.label, Math.max(0, labelMax), 11));
|
|
57125
|
+
if (showVal) {
|
|
57126
|
+
g.append("text").attr("class", "dgmo-treemap-header-value").attr("x", w - ICON_RESERVE - 4).attr("y", 13).attr("text-anchor", "end").attr("font-size", 10.5).attr("fill", ink).attr("opacity", 0.75).text(valStr);
|
|
57127
|
+
}
|
|
57128
|
+
}
|
|
57129
|
+
const PAD = Math.max(4, Math.min(14, Math.floor(Math.min(w, h) / 5)));
|
|
57130
|
+
const MIN_FS = 7;
|
|
57131
|
+
if (!cell.isContainer && w >= 2 * PAD + 8 && h >= 2 * PAD + 8) {
|
|
57132
|
+
const maxW = w - 2 * PAD;
|
|
57133
|
+
let fs = clamp3(Math.round(Math.min(w / 3.6, h / 3.4)), MIN_FS, 72);
|
|
57134
|
+
const nameW = measureText(cell.label, fs) * 1.06;
|
|
57135
|
+
if (nameW > maxW) fs = Math.max(MIN_FS, Math.floor(fs * maxW / nameW));
|
|
57136
|
+
const tg = clamp3((fs - MIN_FS) / (72 - MIN_FS), 0, 1);
|
|
57137
|
+
const nameOpacity = 0.95 - tg * 0.5;
|
|
57138
|
+
const vfs = clamp3(Math.round(fs * 0.42), 11, 28);
|
|
57139
|
+
const valOpacity = Math.max(0.45, nameOpacity - 0.1);
|
|
57140
|
+
let y = PAD + Math.round(fs * 0.78);
|
|
57141
|
+
g.append("text").attr("class", "dgmo-treemap-label").attr("x", PAD).attr("y", y).attr("font-size", fs).attr("font-weight", 600).attr("fill", ink).attr("opacity", nameOpacity).text(clipLabel(cell.label, maxW, fs));
|
|
57142
|
+
const valParts = [
|
|
57143
|
+
opts.noValues ? "" : compactNumber2(cell.value),
|
|
57144
|
+
opts.noPercent ? "" : formatPct(cell.pctOfRoot)
|
|
57145
|
+
].filter(Boolean);
|
|
57146
|
+
const combined = valParts.join(" \xB7 ");
|
|
57147
|
+
const nameBaseY = y;
|
|
57148
|
+
const addLineAt = (text, yy, size, opacity) => {
|
|
57149
|
+
g.append("text").attr("class", "dgmo-treemap-value").attr("x", PAD).attr("y", yy).attr("font-size", size).attr("fill", ink).attr("opacity", opacity).text(text);
|
|
57150
|
+
};
|
|
57151
|
+
if (combined) {
|
|
57152
|
+
const fitsW = measureText(combined, vfs) <= maxW;
|
|
57153
|
+
const roomBelow = h - PAD > y + vfs + 6;
|
|
57154
|
+
if (fitsW && roomBelow) {
|
|
57155
|
+
addLineAt(combined, y + vfs + 6, vfs, valOpacity);
|
|
57156
|
+
} else if (fitsW) {
|
|
57157
|
+
const ivfs = clamp3(Math.round(fs * 0.5), 11, Math.max(11, vfs));
|
|
57158
|
+
const rendered = clipLabel(cell.label, maxW, fs);
|
|
57159
|
+
const nW = measureText(rendered, fs) * 1.12;
|
|
57160
|
+
const gap = Math.max(12, Math.round(fs * 0.25));
|
|
57161
|
+
if (PAD + nW + gap + measureText(combined, ivfs) <= w - PAD) {
|
|
57162
|
+
g.append("text").attr("class", "dgmo-treemap-value").attr("x", PAD + nW + gap).attr("y", nameBaseY).attr("font-size", ivfs).attr("fill", ink).attr("opacity", valOpacity).text(combined);
|
|
57163
|
+
}
|
|
57164
|
+
} else if (valParts.length === 2) {
|
|
57165
|
+
if (h - PAD > y + vfs + 6) {
|
|
57166
|
+
y += vfs + 6;
|
|
57167
|
+
addLineAt(valParts[0], y, vfs, valOpacity);
|
|
57168
|
+
}
|
|
57169
|
+
const pfs = Math.max(10, Math.round(vfs * 0.9));
|
|
57170
|
+
if (h - PAD > y + pfs + 4) {
|
|
57171
|
+
y += pfs + 4;
|
|
57172
|
+
addLineAt(valParts[1], y, pfs, valOpacity);
|
|
57173
|
+
}
|
|
57174
|
+
} else if (h - PAD > y + vfs + 6) {
|
|
57175
|
+
addLineAt(combined, y + vfs + 6, vfs, valOpacity);
|
|
57176
|
+
}
|
|
57177
|
+
}
|
|
57178
|
+
}
|
|
57179
|
+
if (drillable && w > 30 && h > 22) {
|
|
57180
|
+
drawFocusIcon(g, w, ink, 9);
|
|
57181
|
+
}
|
|
57182
|
+
}
|
|
57183
|
+
if (legend) {
|
|
57184
|
+
const legendG = svg.append("g").attr("class", "dgmo-treemap-legend").attr("transform", `translate(0, ${titleH})`);
|
|
57185
|
+
renderIntegratedLegend(legendG, {
|
|
57186
|
+
groups: legend.groups,
|
|
57187
|
+
palette: {
|
|
57188
|
+
bg: palette.bg,
|
|
57189
|
+
surface: palette.surface,
|
|
57190
|
+
text: palette.text,
|
|
57191
|
+
textMuted: palette.textMuted,
|
|
57192
|
+
primary: palette.primary
|
|
57193
|
+
},
|
|
57194
|
+
isDark,
|
|
57195
|
+
width,
|
|
57196
|
+
mode: exportMode ? "export" : "preview",
|
|
57197
|
+
position: LEGEND_POSITION,
|
|
57198
|
+
activeGroup: legend.activeGroup,
|
|
57199
|
+
// The color-mode switcher is the legend itself: each applicable mode is a
|
|
57200
|
+
// group pill; the active one is the open capsule, the rest are clickable
|
|
57201
|
+
// pills that switch mode. Export shows only the active group.
|
|
57202
|
+
showInactivePills: !exportMode,
|
|
57203
|
+
showEmptyGroups: !exportMode,
|
|
57204
|
+
...options.onSelectMode !== void 0 && {
|
|
57205
|
+
callbacks: {
|
|
57206
|
+
onGroupToggle: (name) => {
|
|
57207
|
+
const m = legend.modeByName.get(name);
|
|
57208
|
+
if (m) options.onSelectMode(m);
|
|
57209
|
+
}
|
|
57210
|
+
}
|
|
57211
|
+
}
|
|
57212
|
+
});
|
|
57213
|
+
}
|
|
57214
|
+
}
|
|
57215
|
+
function buildLegend(activeMode, parsed, heat, seriesColors2, colorOffset) {
|
|
57216
|
+
const groups = [];
|
|
57217
|
+
const modeByName = /* @__PURE__ */ new Map();
|
|
57218
|
+
let activeGroup = null;
|
|
57219
|
+
if (parsed.tagGroups.length > 0) {
|
|
57220
|
+
const tg = parsed.tagGroups[0];
|
|
57221
|
+
const used = /* @__PURE__ */ new Set();
|
|
57222
|
+
const collect = (nodes) => {
|
|
57223
|
+
for (const n of nodes) {
|
|
57224
|
+
const v = n.metadata[tagAttrKey(tg.name)];
|
|
57225
|
+
if (v) used.add(v.toLowerCase());
|
|
57226
|
+
collect(n.children);
|
|
57227
|
+
}
|
|
57228
|
+
};
|
|
57229
|
+
collect(parsed.roots);
|
|
57230
|
+
groups.push({
|
|
57231
|
+
name: tg.name,
|
|
57232
|
+
entries: tg.entries.filter((e) => used.has(e.value.toLowerCase())).map((e) => ({ value: e.value, color: e.color }))
|
|
57233
|
+
});
|
|
57234
|
+
modeByName.set(tg.name, "tag");
|
|
57235
|
+
if (activeMode === "tag") activeGroup = tg.name;
|
|
57236
|
+
}
|
|
57237
|
+
if (heat) {
|
|
57238
|
+
const name = parsed.options.heatLabel ?? "Value";
|
|
57239
|
+
groups.push({
|
|
57240
|
+
name,
|
|
57241
|
+
entries: [],
|
|
57242
|
+
gradient: {
|
|
57243
|
+
min: heat.min,
|
|
57244
|
+
max: heat.max,
|
|
57245
|
+
low: heat.stops[0],
|
|
57246
|
+
high: heat.stops[heat.stops.length - 1]
|
|
57247
|
+
}
|
|
57248
|
+
});
|
|
57249
|
+
modeByName.set(name, "heat");
|
|
57250
|
+
if (activeMode === "heat") activeGroup = name;
|
|
57251
|
+
}
|
|
57252
|
+
groups.push({
|
|
57253
|
+
name: "Branch",
|
|
57254
|
+
entries: parsed.roots.map((r, i) => ({
|
|
57255
|
+
value: r.label,
|
|
57256
|
+
color: seriesColors2[(i + colorOffset) % seriesColors2.length]
|
|
57257
|
+
}))
|
|
57258
|
+
});
|
|
57259
|
+
modeByName.set("Branch", "branch");
|
|
57260
|
+
if (activeMode === "branch" || activeGroup === null) activeGroup = "Branch";
|
|
57261
|
+
return { groups, activeGroup, modeByName };
|
|
57262
|
+
}
|
|
57263
|
+
function buildHeatScale(parsed, palette) {
|
|
57264
|
+
if (!parsed.hasHeat) return null;
|
|
57265
|
+
const values = [];
|
|
57266
|
+
const collect = (nodes) => {
|
|
57267
|
+
for (const n of nodes) {
|
|
57268
|
+
if (typeof n.heat === "number") values.push(n.heat);
|
|
57269
|
+
collect(n.children);
|
|
57270
|
+
}
|
|
57271
|
+
};
|
|
57272
|
+
collect(parsed.roots);
|
|
57273
|
+
if (values.length === 0) return null;
|
|
57274
|
+
const min = Math.min(...values);
|
|
57275
|
+
const max = Math.max(...values);
|
|
57276
|
+
const signed = min < 0 && max > 0;
|
|
57277
|
+
const neutral = palette.surface;
|
|
57278
|
+
const explicit = parsed.options.heatColors.map((c) => resolveColor(c, palette) ?? c).filter((c) => !!c);
|
|
57279
|
+
let stops;
|
|
57280
|
+
let domain;
|
|
57281
|
+
if (explicit.length >= 2) {
|
|
57282
|
+
stops = [explicit[0], neutral, explicit[1]];
|
|
57283
|
+
const mid = signed ? 0 : (min + max) / 2;
|
|
57284
|
+
domain = [min, mid, max];
|
|
57285
|
+
} else if (explicit.length === 1) {
|
|
57286
|
+
stops = [neutral, explicit[0]];
|
|
57287
|
+
domain = [min, max];
|
|
57288
|
+
} else if (signed) {
|
|
57289
|
+
stops = [palette.colors.red, neutral, palette.colors.green];
|
|
57290
|
+
domain = [min, 0, max];
|
|
57291
|
+
} else {
|
|
57292
|
+
stops = [neutral, palette.primary];
|
|
57293
|
+
domain = [min, max];
|
|
57294
|
+
}
|
|
57295
|
+
if (domain[0] === domain[domain.length - 1]) {
|
|
57296
|
+
const last = stops[stops.length - 1];
|
|
57297
|
+
return { scale: () => last, min, max, stops, signed };
|
|
57298
|
+
}
|
|
57299
|
+
const linear = (0, import_d3_scale.scaleLinear)().domain(domain).range(stops).clamp(true);
|
|
57300
|
+
return { scale: (v) => toHex(linear(v)), min, max, stops, signed };
|
|
57301
|
+
}
|
|
57302
|
+
function toHex(c) {
|
|
57303
|
+
if (c.startsWith("#")) return c;
|
|
57304
|
+
const m = c.match(/rgba?\(([^)]+)\)/);
|
|
57305
|
+
if (!m) return c;
|
|
57306
|
+
const parts = m[1].split(",").map((s) => Math.round(parseFloat(s)));
|
|
57307
|
+
const h = (n) => Math.max(0, Math.min(255, n || 0)).toString(16).padStart(2, "0");
|
|
57308
|
+
return `#${h(parts[0] ?? 0)}${h(parts[1] ?? 0)}${h(parts[2] ?? 0)}`;
|
|
57309
|
+
}
|
|
57310
|
+
function resolveColorMode(parsed, override) {
|
|
57311
|
+
let mode = override ?? parsed.defaultColorMode;
|
|
57312
|
+
if (mode === "tag" && parsed.tagGroups.length === 0) {
|
|
57313
|
+
mode = parsed.hasHeat ? "heat" : "branch";
|
|
57314
|
+
}
|
|
57315
|
+
if (mode === "heat" && !parsed.hasHeat) mode = "branch";
|
|
57316
|
+
return mode;
|
|
57317
|
+
}
|
|
57318
|
+
function drawFocusIcon(g, w, ink, cy) {
|
|
57319
|
+
const r = 4.5;
|
|
57320
|
+
const cx = w - r - 5;
|
|
57321
|
+
const fi = g.append("g").attr("class", "dgmo-treemap-focus").attr("data-export-ignore", "true");
|
|
57322
|
+
fi.append("rect").attr("x", cx - 9).attr("y", cy - 9).attr("width", 18).attr("height", 18).attr("fill", "transparent");
|
|
57323
|
+
fi.append("circle").attr("cx", cx).attr("cy", cy).attr("r", r).attr("fill", "none").attr("stroke", ink).attr("stroke-width", 1.25);
|
|
57324
|
+
fi.append("circle").attr("cx", cx).attr("cy", cy).attr("r", 1.4).attr("fill", ink);
|
|
57325
|
+
}
|
|
57326
|
+
function clamp3(x, lo, hi) {
|
|
57327
|
+
return Math.max(lo, Math.min(hi, x));
|
|
57328
|
+
}
|
|
57329
|
+
function clipLabel(s, maxWidth, fs) {
|
|
57330
|
+
if (measureText(s, fs) <= maxWidth) return s;
|
|
57331
|
+
let lo = 0;
|
|
57332
|
+
let hi = s.length;
|
|
57333
|
+
while (lo < hi) {
|
|
57334
|
+
const mid = Math.ceil((lo + hi) / 2);
|
|
57335
|
+
if (measureText(s.slice(0, mid) + "\u2026", fs) <= maxWidth) lo = mid;
|
|
57336
|
+
else hi = mid - 1;
|
|
57337
|
+
}
|
|
57338
|
+
return lo <= 0 ? "" : s.slice(0, lo) + "\u2026";
|
|
57339
|
+
}
|
|
57340
|
+
function compactNumber2(v) {
|
|
57341
|
+
const abs = Math.abs(v);
|
|
57342
|
+
if (abs >= 1e9) return strip(v / 1e9) + "B";
|
|
57343
|
+
if (abs >= 1e6) return strip(v / 1e6) + "M";
|
|
57344
|
+
if (abs >= 1e3) return strip(v / 1e3) + "k";
|
|
57345
|
+
return strip(Math.round(v * 100) / 100);
|
|
57346
|
+
}
|
|
57347
|
+
function strip(n) {
|
|
57348
|
+
return parseFloat(
|
|
57349
|
+
n.toFixed(n < 10 && !Number.isInteger(n) ? 1 : 0)
|
|
57350
|
+
).toString();
|
|
57351
|
+
}
|
|
57352
|
+
function formatPct(frac) {
|
|
57353
|
+
const pct = frac * 100;
|
|
57354
|
+
if (pct >= 10) return `${Math.round(pct)}%`;
|
|
57355
|
+
if (pct >= 1) return `${pct.toFixed(0)}%`;
|
|
57356
|
+
return `${pct.toFixed(1)}%`;
|
|
57357
|
+
}
|
|
57358
|
+
var d3Selection26, import_d3_scale, PADDING3, HEADER_H, TITLE_BAND, MUTED_FILL, LEAF_MUTE_PCT, LEGEND_POSITION;
|
|
57359
|
+
var init_renderer19 = __esm({
|
|
57360
|
+
"src/treemap/renderer.ts"() {
|
|
57361
|
+
"use strict";
|
|
57362
|
+
d3Selection26 = __toESM(require("d3-selection"), 1);
|
|
57363
|
+
import_d3_scale = require("d3-scale");
|
|
57364
|
+
init_fonts();
|
|
57365
|
+
init_colors();
|
|
57366
|
+
init_color_utils();
|
|
57367
|
+
init_tag_groups();
|
|
57368
|
+
init_text_measure();
|
|
57369
|
+
init_legend_integration();
|
|
57370
|
+
init_legend_layout();
|
|
57371
|
+
init_legend_constants();
|
|
57372
|
+
init_title_constants();
|
|
57373
|
+
init_layout16();
|
|
57374
|
+
PADDING3 = 12;
|
|
57375
|
+
HEADER_H = 18;
|
|
57376
|
+
TITLE_BAND = 36;
|
|
57377
|
+
MUTED_FILL = "#cbd5e1";
|
|
57378
|
+
LEAF_MUTE_PCT = 50;
|
|
57379
|
+
LEGEND_POSITION = {
|
|
57380
|
+
placement: "top-center",
|
|
57381
|
+
titleRelation: "below-title"
|
|
57382
|
+
};
|
|
57383
|
+
}
|
|
57384
|
+
});
|
|
57385
|
+
|
|
57386
|
+
// src/raci/renderer.ts
|
|
57387
|
+
var renderer_exports20 = {};
|
|
57388
|
+
__export(renderer_exports20, {
|
|
56485
57389
|
MARKER_LABELS: () => MARKER_LABELS,
|
|
56486
57390
|
renderRaci: () => renderRaci,
|
|
56487
57391
|
renderRaciForExport: () => renderRaciForExport
|
|
@@ -56557,7 +57461,7 @@ function renderRaci(container, parsed, palette, isDark, handlers, exportDims) {
|
|
|
56557
57461
|
const hideLegend = opts.hideLegend ?? false;
|
|
56558
57462
|
const collapsedPhases = opts.collapsedPhases ?? /* @__PURE__ */ new Set();
|
|
56559
57463
|
const hideTitle = (opts.hideTitle ?? false) || parsed.options["no-title"] === "on";
|
|
56560
|
-
|
|
57464
|
+
d3Selection27.select(container).selectAll(":not([data-d3-tooltip])").remove();
|
|
56561
57465
|
const width = exportDims?.width ?? container.clientWidth;
|
|
56562
57466
|
const height = exportDims?.height ?? container.clientHeight;
|
|
56563
57467
|
if (width <= 0 || height <= 0) return;
|
|
@@ -56664,7 +57568,7 @@ function renderRaci(container, parsed, palette, isDark, handlers, exportDims) {
|
|
|
56664
57568
|
const colBottomY = cursorY + sColumnBottomPad;
|
|
56665
57569
|
const totalHeight = colBottomY + sVMargin;
|
|
56666
57570
|
const svgHeight = exportDims ? totalHeight : Math.max(height, totalHeight);
|
|
56667
|
-
const svg =
|
|
57571
|
+
const svg = d3Selection27.select(container).append("svg").attr("xmlns", "http://www.w3.org/2000/svg").attr("width", width).attr("height", svgHeight).attr("viewBox", `0 0 ${width} ${svgHeight}`).attr("preserveAspectRatio", "xMidYMin meet").attr("font-family", FONT_FAMILY).style("background", "transparent");
|
|
56668
57572
|
if (ctx.isBelowFloor) {
|
|
56669
57573
|
svg.attr("width", "100%");
|
|
56670
57574
|
}
|
|
@@ -57144,15 +58048,15 @@ function parseQuotedSegments(message) {
|
|
|
57144
58048
|
out.push({ text: message.slice(last), bold: false });
|
|
57145
58049
|
return out;
|
|
57146
58050
|
}
|
|
57147
|
-
var
|
|
57148
|
-
var
|
|
58051
|
+
var d3Selection27, MARKER_LABELS, TITLE_AREA_HEIGHT4, H_MARGIN, V_MARGIN3, LEGEND_HEIGHT2, LEGEND_CHIP_GAP, LEGEND_CHIP_LABEL_MIN, LEGEND_LETTER_CHIP_W, TITLE_LEGEND_GAP, LEGEND_LABEL_FONT, LEGEND_LETTER_FONT, HEADER_HEIGHT5, ROW_HEIGHT, PHASE_HEIGHT, TASK_LABEL_MIN, TASK_LABEL_MAX, ROLE_COL_MIN, ROLE_COL_MAX, CELL_PAD, VIOLATION_LINE_HEIGHT, STACK_TOP_GAP, DESC_FONT, COLUMN_RADIUS3, COLUMN_INSET, COLUMN_BOTTOM_PAD, MARKER_FONT, MARKER_FONT_WEIGHT, LABEL_FONT2, ROLE_HEADER_FONT, PHASE_FONT, TINT_PCT, NODE_RADIUS3, AUTO_ACCENTS, SLICE_GAP, NAME_LINE_HEIGHT, DESC_LINE_HEIGHT9;
|
|
58052
|
+
var init_renderer20 = __esm({
|
|
57149
58053
|
"src/raci/renderer.ts"() {
|
|
57150
58054
|
"use strict";
|
|
57151
|
-
|
|
58055
|
+
d3Selection27 = __toESM(require("d3-selection"), 1);
|
|
57152
58056
|
init_fonts();
|
|
57153
58057
|
init_title_constants();
|
|
57154
58058
|
init_color_utils();
|
|
57155
|
-
|
|
58059
|
+
init_parser27();
|
|
57156
58060
|
init_variants();
|
|
57157
58061
|
init_scaling();
|
|
57158
58062
|
init_text_measure();
|
|
@@ -57409,8 +58313,8 @@ var init_tag_resolution = __esm({
|
|
|
57409
58313
|
});
|
|
57410
58314
|
|
|
57411
58315
|
// src/sequence/renderer.ts
|
|
57412
|
-
var
|
|
57413
|
-
__export(
|
|
58316
|
+
var renderer_exports21 = {};
|
|
58317
|
+
__export(renderer_exports21, {
|
|
57414
58318
|
applyGroupOrdering: () => applyGroupOrdering,
|
|
57415
58319
|
applyPositionOverrides: () => applyPositionOverrides,
|
|
57416
58320
|
buildNoteMessageMap: () => buildNoteMessageMap,
|
|
@@ -57750,7 +58654,7 @@ function applyGroupOrdering(participants, groups, messages = []) {
|
|
|
57750
58654
|
return result;
|
|
57751
58655
|
}
|
|
57752
58656
|
function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateToLine, options) {
|
|
57753
|
-
|
|
58657
|
+
d3Selection28.select(container).selectAll("*").remove();
|
|
57754
58658
|
const { title, options: parsedOptions } = parsed;
|
|
57755
58659
|
const solid = parsedOptions["solid-fill"] === "on";
|
|
57756
58660
|
const effectiveCollapsedGroups = /* @__PURE__ */ new Set();
|
|
@@ -58401,7 +59305,7 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
|
|
|
58401
59305
|
offsetX = leftMargin + Math.max(0, (svgWidth - totalWidth) / 2);
|
|
58402
59306
|
buildParticipantX();
|
|
58403
59307
|
}
|
|
58404
|
-
const svg =
|
|
59308
|
+
const svg = d3Selection28.select(container).append("svg").attr("width", "100%").attr("height", totalHeight).attr("viewBox", `0 0 ${svgWidth} ${totalHeight}`).attr("preserveAspectRatio", "xMidYMin meet").attr("class", "sequence-diagram").style("font-family", FONT_FAMILY);
|
|
58405
59309
|
const defs = svg.append("defs");
|
|
58406
59310
|
defs.append("marker").attr("id", "seq-arrowhead").attr("viewBox", `0 0 ${sArrowheadSize} ${sArrowheadSize}`).attr("refX", sArrowheadSize).attr("refY", sArrowheadSize / 2).attr("markerWidth", sArrowheadSize).attr("markerHeight", sArrowheadSize).attr("orient", "auto").append("polygon").attr(
|
|
58407
59311
|
"points",
|
|
@@ -59013,12 +59917,12 @@ function renderParticipant(svg, participant, cx, cy, palette, isDark, color, tag
|
|
|
59013
59917
|
});
|
|
59014
59918
|
}
|
|
59015
59919
|
}
|
|
59016
|
-
var
|
|
59017
|
-
var
|
|
59920
|
+
var d3Selection28, PARTICIPANT_GAP, PARTICIPANT_BOX_WIDTH, PARTICIPANT_BOX_HEIGHT, LABEL_FONT_SIZE5, TOP_MARGIN, TITLE_HEIGHT8, PARTICIPANT_Y_OFFSET, MESSAGE_START_OFFSET, LIFELINE_TAIL, ARROWHEAD_SIZE, NOTE_MAX_W2, NOTE_FOLD2, NOTE_PAD_H2, NOTE_PAD_V2, NOTE_FONT_SIZE2, NOTE_LINE_H2, NOTE_GAP2, ACTIVATION_WIDTH, SELF_CALL_HEIGHT, SELF_CALL_WIDTH, ACTOR_LABEL_CLEARANCE, labelTextWidth, fill, stroke, SW, W, H;
|
|
59921
|
+
var init_renderer21 = __esm({
|
|
59018
59922
|
"src/sequence/renderer.ts"() {
|
|
59019
59923
|
"use strict";
|
|
59020
59924
|
init_tag_groups();
|
|
59021
|
-
|
|
59925
|
+
d3Selection28 = __toESM(require("d3-selection"), 1);
|
|
59022
59926
|
init_color_utils();
|
|
59023
59927
|
init_inline_markdown();
|
|
59024
59928
|
init_fonts();
|
|
@@ -62907,6 +63811,7 @@ var DIAGRAM_EXPORT_HANDLERS = {
|
|
|
62907
63811
|
map: exportMap,
|
|
62908
63812
|
pyramid: exportPyramid,
|
|
62909
63813
|
ring: exportRing,
|
|
63814
|
+
treemap: exportTreemap,
|
|
62910
63815
|
raci: exportRaci,
|
|
62911
63816
|
rasci: exportRaci,
|
|
62912
63817
|
daci: exportRaci,
|
|
@@ -62964,10 +63869,10 @@ async function exportOrg(ctx) {
|
|
|
62964
63869
|
false
|
|
62965
63870
|
// expandAllLegend off — collapsed-by-default per §1.3
|
|
62966
63871
|
);
|
|
62967
|
-
const
|
|
63872
|
+
const PADDING4 = 20;
|
|
62968
63873
|
const titleOffset = effectiveParsed.title ? 30 : 0;
|
|
62969
|
-
const exportWidth = orgLayout.width +
|
|
62970
|
-
const exportHeight = orgLayout.height +
|
|
63874
|
+
const exportWidth = orgLayout.width + PADDING4 * 2;
|
|
63875
|
+
const exportHeight = orgLayout.height + PADDING4 * 2 + titleOffset;
|
|
62971
63876
|
const container = createExportContainer(exportWidth, exportHeight);
|
|
62972
63877
|
renderOrg2(
|
|
62973
63878
|
container,
|
|
@@ -63009,10 +63914,10 @@ async function exportSitemap(ctx) {
|
|
|
63009
63914
|
hiddenAttributes,
|
|
63010
63915
|
true
|
|
63011
63916
|
);
|
|
63012
|
-
const
|
|
63917
|
+
const PADDING4 = 20;
|
|
63013
63918
|
const titleOffset = effectiveParsed.title ? 30 : 0;
|
|
63014
|
-
const exportWidth = sitemapLayout.width +
|
|
63015
|
-
const exportHeight = sitemapLayout.height +
|
|
63919
|
+
const exportWidth = sitemapLayout.width + PADDING4 * 2;
|
|
63920
|
+
const exportHeight = sitemapLayout.height + PADDING4 * 2 + titleOffset;
|
|
63016
63921
|
const container = createExportContainer(exportWidth, exportHeight);
|
|
63017
63922
|
renderSitemap2(
|
|
63018
63923
|
container,
|
|
@@ -63068,10 +63973,10 @@ async function exportClass(ctx) {
|
|
|
63068
63973
|
const classParsed = parseClassDiagram2(content, effectivePalette);
|
|
63069
63974
|
if (classParsed.error || classParsed.classes.length === 0) return "";
|
|
63070
63975
|
const classLayout = layoutClassDiagram2(classParsed);
|
|
63071
|
-
const
|
|
63976
|
+
const PADDING4 = 20;
|
|
63072
63977
|
const titleOffset = classParsed.title ? 40 : 0;
|
|
63073
|
-
const exportWidth = classLayout.width +
|
|
63074
|
-
const exportHeight = classLayout.height +
|
|
63978
|
+
const exportWidth = classLayout.width + PADDING4 * 2;
|
|
63979
|
+
const exportHeight = classLayout.height + PADDING4 * 2 + titleOffset;
|
|
63075
63980
|
const container = createExportContainer(exportWidth, exportHeight);
|
|
63076
63981
|
renderClassDiagram2(
|
|
63077
63982
|
container,
|
|
@@ -63095,10 +64000,10 @@ async function exportEr(ctx) {
|
|
|
63095
64000
|
const erParsed = parseERDiagram2(content, effectivePalette);
|
|
63096
64001
|
if (erParsed.error || erParsed.tables.length === 0) return "";
|
|
63097
64002
|
const erLayout = layoutERDiagram2(erParsed);
|
|
63098
|
-
const
|
|
64003
|
+
const PADDING4 = 20;
|
|
63099
64004
|
const titleOffset = erParsed.title ? 40 : 0;
|
|
63100
|
-
const exportWidth = erLayout.width +
|
|
63101
|
-
const exportHeight = erLayout.height +
|
|
64005
|
+
const exportWidth = erLayout.width + PADDING4 * 2;
|
|
64006
|
+
const exportHeight = erLayout.height + PADDING4 * 2 + titleOffset;
|
|
63102
64007
|
const container = createExportContainer(exportWidth, exportHeight);
|
|
63103
64008
|
renderERDiagram2(
|
|
63104
64009
|
container,
|
|
@@ -63134,10 +64039,10 @@ async function exportBoxesAndLines(ctx) {
|
|
|
63134
64039
|
const { renderBoxesAndLinesForExport: renderBoxesAndLinesForExport2 } = await Promise.resolve().then(() => (init_renderer6(), renderer_exports6));
|
|
63135
64040
|
const { layoutBoxesAndLines: layoutBoxesAndLines2 } = await Promise.resolve().then(() => (init_layout5(), layout_exports5));
|
|
63136
64041
|
const blLayout = await layoutBoxesAndLines2(blParsed);
|
|
63137
|
-
const
|
|
64042
|
+
const PADDING4 = 20;
|
|
63138
64043
|
const titleOffset = blParsed.title ? 40 : 0;
|
|
63139
|
-
const exportWidth = blLayout.width +
|
|
63140
|
-
const exportHeight = blLayout.height +
|
|
64044
|
+
const exportWidth = blLayout.width + PADDING4 * 2;
|
|
64045
|
+
const exportHeight = blLayout.height + PADDING4 * 2 + titleOffset;
|
|
63141
64046
|
const container = createExportContainer(exportWidth, exportHeight);
|
|
63142
64047
|
const blActiveTagGroup = ctxTagOverride(ctx);
|
|
63143
64048
|
renderBoxesAndLinesForExport2(
|
|
@@ -63184,10 +64089,10 @@ async function exportMindmap(ctx) {
|
|
|
63184
64089
|
activeTagGroup,
|
|
63185
64090
|
hideDescriptions
|
|
63186
64091
|
});
|
|
63187
|
-
const
|
|
64092
|
+
const PADDING4 = 20;
|
|
63188
64093
|
const titleOffset = effectiveParsed.title ? 30 : 0;
|
|
63189
|
-
const exportWidth = mmLayout.width +
|
|
63190
|
-
const exportHeight = mmLayout.height +
|
|
64094
|
+
const exportWidth = mmLayout.width + PADDING4 * 2;
|
|
64095
|
+
const exportHeight = mmLayout.height + PADDING4 * 2 + titleOffset;
|
|
63191
64096
|
const container = createExportContainer(exportWidth, exportHeight);
|
|
63192
64097
|
const colorByDepth = viewState?.cbd === true;
|
|
63193
64098
|
renderMindmap2(
|
|
@@ -63248,10 +64153,10 @@ async function exportC4(ctx) {
|
|
|
63248
64153
|
const c4Container = ctx.options?.c4Container ?? viewState?.c4c;
|
|
63249
64154
|
const c4Layout = c4Level === "deployment" ? layoutC4Deployment2(c4Parsed) : c4Level === "components" && c4System && c4Container ? layoutC4Components2(c4Parsed, c4System, c4Container) : c4Level === "containers" && c4System ? layoutC4Containers2(c4Parsed, c4System) : layoutC4Context2(c4Parsed);
|
|
63250
64155
|
if (c4Layout.nodes.length === 0) return "";
|
|
63251
|
-
const
|
|
64156
|
+
const PADDING4 = 20;
|
|
63252
64157
|
const titleOffset = c4Parsed.title ? 40 : 0;
|
|
63253
|
-
const exportWidth = c4Layout.width +
|
|
63254
|
-
const exportHeight = c4Layout.height +
|
|
64158
|
+
const exportWidth = c4Layout.width + PADDING4 * 2;
|
|
64159
|
+
const exportHeight = c4Layout.height + PADDING4 * 2 + titleOffset;
|
|
63255
64160
|
const container = createExportContainer(exportWidth, exportHeight);
|
|
63256
64161
|
const renderFn = c4Level === "deployment" || c4Level === "components" && c4System && c4Container || c4Level === "containers" && c4System ? renderC4Containers2 : renderC4Context2;
|
|
63257
64162
|
renderFn(
|
|
@@ -63567,30 +64472,44 @@ async function exportRing(ctx) {
|
|
|
63567
64472
|
const ringParsed = parseRing2(content);
|
|
63568
64473
|
if (ringParsed.error || ringParsed.layers.length === 0) return "";
|
|
63569
64474
|
const container = createExportContainer(EXPORT_WIDTH, EXPORT_HEIGHT);
|
|
63570
|
-
renderRingForExport2(
|
|
64475
|
+
renderRingForExport2(container, ringParsed, effectivePalette, ctx.isDark, {
|
|
64476
|
+
width: EXPORT_WIDTH,
|
|
64477
|
+
height: EXPORT_HEIGHT
|
|
64478
|
+
});
|
|
64479
|
+
return finalizeSvgExport(container, theme, effectivePalette);
|
|
64480
|
+
}
|
|
64481
|
+
async function exportTreemap(ctx) {
|
|
64482
|
+
const { content, theme, palette } = ctx;
|
|
64483
|
+
const { parseTreemap: parseTreemap2 } = await Promise.resolve().then(() => (init_parser26(), parser_exports20));
|
|
64484
|
+
const { renderTreemapForExport: renderTreemapForExport2 } = await Promise.resolve().then(() => (init_renderer19(), renderer_exports19));
|
|
64485
|
+
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
64486
|
+
const treemapParsed = parseTreemap2(content, effectivePalette);
|
|
64487
|
+
if (treemapParsed.error || treemapParsed.roots.length === 0) return "";
|
|
64488
|
+
const container = createExportContainer(EXPORT_WIDTH, EXPORT_HEIGHT);
|
|
64489
|
+
renderTreemapForExport2(
|
|
63571
64490
|
container,
|
|
63572
|
-
|
|
64491
|
+
treemapParsed,
|
|
63573
64492
|
effectivePalette,
|
|
63574
64493
|
ctx.isDark,
|
|
63575
|
-
{
|
|
64494
|
+
{
|
|
64495
|
+
width: EXPORT_WIDTH,
|
|
64496
|
+
height: EXPORT_HEIGHT
|
|
64497
|
+
}
|
|
63576
64498
|
);
|
|
63577
64499
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
63578
64500
|
}
|
|
63579
64501
|
async function exportRaci(ctx) {
|
|
63580
64502
|
const { content, theme, palette } = ctx;
|
|
63581
|
-
const { parseRaci: parseRaci2 } = await Promise.resolve().then(() => (
|
|
63582
|
-
const { renderRaciForExport: renderRaciForExport2 } = await Promise.resolve().then(() => (
|
|
64503
|
+
const { parseRaci: parseRaci2 } = await Promise.resolve().then(() => (init_parser27(), parser_exports21));
|
|
64504
|
+
const { renderRaciForExport: renderRaciForExport2 } = await Promise.resolve().then(() => (init_renderer20(), renderer_exports20));
|
|
63583
64505
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
63584
64506
|
const raciParsed = parseRaci2(content, effectivePalette);
|
|
63585
64507
|
if (raciParsed.error) return "";
|
|
63586
64508
|
const container = createExportContainer(EXPORT_WIDTH, EXPORT_HEIGHT);
|
|
63587
|
-
renderRaciForExport2(
|
|
63588
|
-
|
|
63589
|
-
|
|
63590
|
-
|
|
63591
|
-
ctx.isDark,
|
|
63592
|
-
{ width: EXPORT_WIDTH, height: EXPORT_HEIGHT }
|
|
63593
|
-
);
|
|
64509
|
+
renderRaciForExport2(container, raciParsed, effectivePalette, ctx.isDark, {
|
|
64510
|
+
width: EXPORT_WIDTH,
|
|
64511
|
+
height: EXPORT_HEIGHT
|
|
64512
|
+
});
|
|
63594
64513
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
63595
64514
|
}
|
|
63596
64515
|
function beginVizExport() {
|
|
@@ -63679,14 +64598,7 @@ async function exportVenn(ctx) {
|
|
|
63679
64598
|
if (parsed.error || parsed.vennSets.length < 2) return "";
|
|
63680
64599
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
63681
64600
|
const { container, dims } = beginVizExport();
|
|
63682
|
-
renderVenn(
|
|
63683
|
-
container,
|
|
63684
|
-
parsed,
|
|
63685
|
-
effectivePalette,
|
|
63686
|
-
ctx.isDark,
|
|
63687
|
-
void 0,
|
|
63688
|
-
dims
|
|
63689
|
-
);
|
|
64601
|
+
renderVenn(container, parsed, effectivePalette, ctx.isDark, void 0, dims);
|
|
63690
64602
|
return finalizeSvgExport(container, theme, effectivePalette);
|
|
63691
64603
|
}
|
|
63692
64604
|
async function exportQuadrant(ctx) {
|
|
@@ -63720,7 +64632,7 @@ async function exportVisualization(ctx) {
|
|
|
63720
64632
|
const isDark = ctx.isDark;
|
|
63721
64633
|
const container = createExportContainer(EXPORT_WIDTH, EXPORT_HEIGHT);
|
|
63722
64634
|
const { parseSequenceDgmo: parseSequenceDgmo2 } = await Promise.resolve().then(() => (init_parser7(), parser_exports));
|
|
63723
|
-
const { renderSequenceDiagram: renderSequenceDiagram2 } = await Promise.resolve().then(() => (
|
|
64635
|
+
const { renderSequenceDiagram: renderSequenceDiagram2 } = await Promise.resolve().then(() => (init_renderer21(), renderer_exports21));
|
|
63724
64636
|
const seqParsed = parseSequenceDgmo2(content, effectivePalette);
|
|
63725
64637
|
if (seqParsed.error || seqParsed.participants.length === 0) return "";
|
|
63726
64638
|
const collapsedSections = viewState?.cs ? new Set(viewState.cs) : void 0;
|
|
@@ -63931,6 +64843,7 @@ var CHART_TYPES = /* @__PURE__ */ new Set([
|
|
|
63931
64843
|
"journey-map",
|
|
63932
64844
|
"pyramid",
|
|
63933
64845
|
"ring",
|
|
64846
|
+
"treemap",
|
|
63934
64847
|
"raci",
|
|
63935
64848
|
"rasci",
|
|
63936
64849
|
"daci",
|
|
@@ -64122,6 +65035,8 @@ var ATTRIBUTE_KEYS = /* @__PURE__ */ new Set([
|
|
|
64122
65035
|
"value",
|
|
64123
65036
|
"label",
|
|
64124
65037
|
"style",
|
|
65038
|
+
// Treemap color-by-value metric key
|
|
65039
|
+
"heat",
|
|
64125
65040
|
// Infra node behavior + edge colon-keys (§4) come from the single-source
|
|
64126
65041
|
// directives registry — the parser accepts them only as `key: value` node
|
|
64127
65042
|
// properties, so they render as `propertyName`. The dual-use top-level SLO
|
|
@@ -64499,7 +65414,7 @@ pre.dgmo, code.language-dgmo, pre > code.language-dgmo,
|
|
|
64499
65414
|
|
|
64500
65415
|
// src/auto/index.ts
|
|
64501
65416
|
init_safe_href();
|
|
64502
|
-
var VERSION = "0.
|
|
65417
|
+
var VERSION = "0.38.0";
|
|
64503
65418
|
var DEFAULTS = {
|
|
64504
65419
|
theme: "auto",
|
|
64505
65420
|
palette: "slate",
|