@diagrammo/dgmo 0.4.3 → 0.5.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/dist/cli.cjs +152 -152
- package/dist/index.cjs +546 -154
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -20
- package/dist/index.d.ts +25 -20
- package/dist/index.js +546 -154
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/chart.ts +5 -2
- package/src/d3.ts +388 -21
- package/src/echarts.ts +13 -12
- package/src/er/parser.ts +88 -3
- package/src/er/renderer.ts +91 -2
- package/src/er/types.ts +3 -0
- package/src/infra/layout.ts +6 -3
- package/src/infra/parser.ts +2 -2
- package/src/infra/renderer.ts +52 -8
- package/src/kanban/mutations.ts +1 -1
- package/src/kanban/parser.ts +55 -36
- package/src/sharing.ts +8 -0
package/dist/index.cjs
CHANGED
|
@@ -1379,6 +1379,94 @@ var init_parsing = __esm({
|
|
|
1379
1379
|
}
|
|
1380
1380
|
});
|
|
1381
1381
|
|
|
1382
|
+
// src/utils/tag-groups.ts
|
|
1383
|
+
function isTagBlockHeading(trimmed) {
|
|
1384
|
+
return TAG_BLOCK_RE.test(trimmed) || GROUP_HEADING_RE.test(trimmed);
|
|
1385
|
+
}
|
|
1386
|
+
function resolveTagColor(metadata, tagGroups, activeGroupName, isContainer) {
|
|
1387
|
+
if (!activeGroupName) return void 0;
|
|
1388
|
+
const group = tagGroups.find(
|
|
1389
|
+
(g) => g.name.toLowerCase() === activeGroupName.toLowerCase()
|
|
1390
|
+
);
|
|
1391
|
+
if (!group) return void 0;
|
|
1392
|
+
const metaValue = metadata[group.name.toLowerCase()] ?? (isContainer ? void 0 : group.defaultValue);
|
|
1393
|
+
if (!metaValue) return "#999999";
|
|
1394
|
+
return group.entries.find(
|
|
1395
|
+
(e) => e.value.toLowerCase() === metaValue.toLowerCase()
|
|
1396
|
+
)?.color ?? "#999999";
|
|
1397
|
+
}
|
|
1398
|
+
function validateTagValues(entities, tagGroups, pushWarning, suggestFn) {
|
|
1399
|
+
if (tagGroups.length === 0) return;
|
|
1400
|
+
const groupMap = /* @__PURE__ */ new Map();
|
|
1401
|
+
for (const g of tagGroups) groupMap.set(g.name.toLowerCase(), g);
|
|
1402
|
+
for (const entity of entities) {
|
|
1403
|
+
for (const [key, value] of Object.entries(entity.metadata)) {
|
|
1404
|
+
const group = groupMap.get(key);
|
|
1405
|
+
if (!group) continue;
|
|
1406
|
+
const match = group.entries.some(
|
|
1407
|
+
(e) => e.value.toLowerCase() === value.toLowerCase()
|
|
1408
|
+
);
|
|
1409
|
+
if (!match) {
|
|
1410
|
+
const defined = group.entries.map((e) => e.value);
|
|
1411
|
+
let msg = `Unknown value '${value}' for tag group '${group.name}'`;
|
|
1412
|
+
const hint = suggestFn?.(value, defined);
|
|
1413
|
+
if (hint) {
|
|
1414
|
+
msg += `. ${hint}`;
|
|
1415
|
+
} else {
|
|
1416
|
+
msg += ` \u2014 defined values: ${defined.join(", ")}`;
|
|
1417
|
+
}
|
|
1418
|
+
pushWarning(entity.lineNumber, msg);
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
function injectDefaultTagMetadata(entities, tagGroups, skip) {
|
|
1424
|
+
const defaults = [];
|
|
1425
|
+
for (const group of tagGroups) {
|
|
1426
|
+
if (group.defaultValue) {
|
|
1427
|
+
defaults.push({ key: group.name.toLowerCase(), value: group.defaultValue });
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
if (defaults.length === 0) return;
|
|
1431
|
+
for (const entity of entities) {
|
|
1432
|
+
if (skip?.(entity)) continue;
|
|
1433
|
+
for (const { key, value } of defaults) {
|
|
1434
|
+
if (!(key in entity.metadata)) {
|
|
1435
|
+
entity.metadata[key] = value;
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
function matchTagBlockHeading(trimmed) {
|
|
1441
|
+
const tagMatch = trimmed.match(TAG_BLOCK_RE);
|
|
1442
|
+
if (tagMatch) {
|
|
1443
|
+
return {
|
|
1444
|
+
name: tagMatch[1].trim(),
|
|
1445
|
+
alias: tagMatch[2] || void 0,
|
|
1446
|
+
colorHint: tagMatch[3] || void 0,
|
|
1447
|
+
deprecated: false
|
|
1448
|
+
};
|
|
1449
|
+
}
|
|
1450
|
+
const groupMatch = trimmed.match(GROUP_HEADING_RE);
|
|
1451
|
+
if (groupMatch) {
|
|
1452
|
+
return {
|
|
1453
|
+
name: groupMatch[1].trim(),
|
|
1454
|
+
alias: groupMatch[2] || void 0,
|
|
1455
|
+
colorHint: groupMatch[3] || void 0,
|
|
1456
|
+
deprecated: true
|
|
1457
|
+
};
|
|
1458
|
+
}
|
|
1459
|
+
return null;
|
|
1460
|
+
}
|
|
1461
|
+
var TAG_BLOCK_RE, GROUP_HEADING_RE;
|
|
1462
|
+
var init_tag_groups = __esm({
|
|
1463
|
+
"src/utils/tag-groups.ts"() {
|
|
1464
|
+
"use strict";
|
|
1465
|
+
TAG_BLOCK_RE = /^tag:\s+(.+?)(?:\s+alias\s+(\w+))?(?:\s*\(([^)]+)\))?\s*$/i;
|
|
1466
|
+
GROUP_HEADING_RE = /^##\s+(.+?)(?:\s+alias\s+(\w+))?(?:\s*\(([^)]+)\))?\s*$/;
|
|
1467
|
+
}
|
|
1468
|
+
});
|
|
1469
|
+
|
|
1382
1470
|
// src/sequence/participant-inference.ts
|
|
1383
1471
|
function inferParticipantType(name) {
|
|
1384
1472
|
for (const rule of PARTICIPANT_RULES) {
|
|
@@ -1708,94 +1796,6 @@ var init_arrows = __esm({
|
|
|
1708
1796
|
}
|
|
1709
1797
|
});
|
|
1710
1798
|
|
|
1711
|
-
// src/utils/tag-groups.ts
|
|
1712
|
-
function isTagBlockHeading(trimmed) {
|
|
1713
|
-
return TAG_BLOCK_RE.test(trimmed) || GROUP_HEADING_RE.test(trimmed);
|
|
1714
|
-
}
|
|
1715
|
-
function resolveTagColor(metadata, tagGroups, activeGroupName, isContainer) {
|
|
1716
|
-
if (!activeGroupName) return void 0;
|
|
1717
|
-
const group = tagGroups.find(
|
|
1718
|
-
(g) => g.name.toLowerCase() === activeGroupName.toLowerCase()
|
|
1719
|
-
);
|
|
1720
|
-
if (!group) return void 0;
|
|
1721
|
-
const metaValue = metadata[group.name.toLowerCase()] ?? (isContainer ? void 0 : group.defaultValue);
|
|
1722
|
-
if (!metaValue) return "#999999";
|
|
1723
|
-
return group.entries.find(
|
|
1724
|
-
(e) => e.value.toLowerCase() === metaValue.toLowerCase()
|
|
1725
|
-
)?.color ?? "#999999";
|
|
1726
|
-
}
|
|
1727
|
-
function validateTagValues(entities, tagGroups, pushWarning, suggestFn) {
|
|
1728
|
-
if (tagGroups.length === 0) return;
|
|
1729
|
-
const groupMap = /* @__PURE__ */ new Map();
|
|
1730
|
-
for (const g of tagGroups) groupMap.set(g.name.toLowerCase(), g);
|
|
1731
|
-
for (const entity of entities) {
|
|
1732
|
-
for (const [key, value] of Object.entries(entity.metadata)) {
|
|
1733
|
-
const group = groupMap.get(key);
|
|
1734
|
-
if (!group) continue;
|
|
1735
|
-
const match = group.entries.some(
|
|
1736
|
-
(e) => e.value.toLowerCase() === value.toLowerCase()
|
|
1737
|
-
);
|
|
1738
|
-
if (!match) {
|
|
1739
|
-
const defined = group.entries.map((e) => e.value);
|
|
1740
|
-
let msg = `Unknown value '${value}' for tag group '${group.name}'`;
|
|
1741
|
-
const hint = suggestFn?.(value, defined);
|
|
1742
|
-
if (hint) {
|
|
1743
|
-
msg += `. ${hint}`;
|
|
1744
|
-
} else {
|
|
1745
|
-
msg += ` \u2014 defined values: ${defined.join(", ")}`;
|
|
1746
|
-
}
|
|
1747
|
-
pushWarning(entity.lineNumber, msg);
|
|
1748
|
-
}
|
|
1749
|
-
}
|
|
1750
|
-
}
|
|
1751
|
-
}
|
|
1752
|
-
function injectDefaultTagMetadata(entities, tagGroups, skip) {
|
|
1753
|
-
const defaults = [];
|
|
1754
|
-
for (const group of tagGroups) {
|
|
1755
|
-
if (group.defaultValue) {
|
|
1756
|
-
defaults.push({ key: group.name.toLowerCase(), value: group.defaultValue });
|
|
1757
|
-
}
|
|
1758
|
-
}
|
|
1759
|
-
if (defaults.length === 0) return;
|
|
1760
|
-
for (const entity of entities) {
|
|
1761
|
-
if (skip?.(entity)) continue;
|
|
1762
|
-
for (const { key, value } of defaults) {
|
|
1763
|
-
if (!(key in entity.metadata)) {
|
|
1764
|
-
entity.metadata[key] = value;
|
|
1765
|
-
}
|
|
1766
|
-
}
|
|
1767
|
-
}
|
|
1768
|
-
}
|
|
1769
|
-
function matchTagBlockHeading(trimmed) {
|
|
1770
|
-
const tagMatch = trimmed.match(TAG_BLOCK_RE);
|
|
1771
|
-
if (tagMatch) {
|
|
1772
|
-
return {
|
|
1773
|
-
name: tagMatch[1].trim(),
|
|
1774
|
-
alias: tagMatch[2] || void 0,
|
|
1775
|
-
colorHint: tagMatch[3] || void 0,
|
|
1776
|
-
deprecated: false
|
|
1777
|
-
};
|
|
1778
|
-
}
|
|
1779
|
-
const groupMatch = trimmed.match(GROUP_HEADING_RE);
|
|
1780
|
-
if (groupMatch) {
|
|
1781
|
-
return {
|
|
1782
|
-
name: groupMatch[1].trim(),
|
|
1783
|
-
alias: groupMatch[2] || void 0,
|
|
1784
|
-
colorHint: groupMatch[3] || void 0,
|
|
1785
|
-
deprecated: true
|
|
1786
|
-
};
|
|
1787
|
-
}
|
|
1788
|
-
return null;
|
|
1789
|
-
}
|
|
1790
|
-
var TAG_BLOCK_RE, GROUP_HEADING_RE;
|
|
1791
|
-
var init_tag_groups = __esm({
|
|
1792
|
-
"src/utils/tag-groups.ts"() {
|
|
1793
|
-
"use strict";
|
|
1794
|
-
TAG_BLOCK_RE = /^tag:\s+(.+?)(?:\s+alias\s+(\w+))?(?:\s*\(([^)]+)\))?\s*$/i;
|
|
1795
|
-
GROUP_HEADING_RE = /^##\s+(.+?)(?:\s+alias\s+(\w+))?(?:\s*\(([^)]+)\))?\s*$/;
|
|
1796
|
-
}
|
|
1797
|
-
});
|
|
1798
|
-
|
|
1799
1799
|
// src/sequence/parser.ts
|
|
1800
1800
|
var parser_exports = {};
|
|
1801
1801
|
__export(parser_exports, {
|
|
@@ -3383,6 +3383,7 @@ function parseERDiagram(content, palette) {
|
|
|
3383
3383
|
options: {},
|
|
3384
3384
|
tables: [],
|
|
3385
3385
|
relationships: [],
|
|
3386
|
+
tagGroups: [],
|
|
3386
3387
|
diagnostics: [],
|
|
3387
3388
|
error: null
|
|
3388
3389
|
};
|
|
@@ -3400,6 +3401,8 @@ function parseERDiagram(content, palette) {
|
|
|
3400
3401
|
const tableMap = /* @__PURE__ */ new Map();
|
|
3401
3402
|
let currentTable = null;
|
|
3402
3403
|
let contentStarted = false;
|
|
3404
|
+
let currentTagGroup = null;
|
|
3405
|
+
const aliasMap = /* @__PURE__ */ new Map();
|
|
3403
3406
|
function getOrCreateTable(name, lineNumber) {
|
|
3404
3407
|
const id = tableId(name);
|
|
3405
3408
|
const existing = tableMap.get(id);
|
|
@@ -3408,6 +3411,7 @@ function parseERDiagram(content, palette) {
|
|
|
3408
3411
|
id,
|
|
3409
3412
|
name,
|
|
3410
3413
|
columns: [],
|
|
3414
|
+
metadata: {},
|
|
3411
3415
|
lineNumber
|
|
3412
3416
|
};
|
|
3413
3417
|
tableMap.set(id, table);
|
|
@@ -3424,6 +3428,50 @@ function parseERDiagram(content, palette) {
|
|
|
3424
3428
|
continue;
|
|
3425
3429
|
}
|
|
3426
3430
|
if (trimmed.startsWith("//")) continue;
|
|
3431
|
+
if (!contentStarted && indent === 0) {
|
|
3432
|
+
const tagBlockMatch = matchTagBlockHeading(trimmed);
|
|
3433
|
+
if (tagBlockMatch) {
|
|
3434
|
+
if (tagBlockMatch.deprecated) {
|
|
3435
|
+
result.diagnostics.push(makeDgmoError(
|
|
3436
|
+
lineNumber,
|
|
3437
|
+
`'## ${tagBlockMatch.name}' is deprecated for tag groups \u2014 use 'tag: ${tagBlockMatch.name}' instead`,
|
|
3438
|
+
"warning"
|
|
3439
|
+
));
|
|
3440
|
+
}
|
|
3441
|
+
currentTagGroup = {
|
|
3442
|
+
name: tagBlockMatch.name,
|
|
3443
|
+
alias: tagBlockMatch.alias,
|
|
3444
|
+
entries: [],
|
|
3445
|
+
lineNumber
|
|
3446
|
+
};
|
|
3447
|
+
if (tagBlockMatch.alias) {
|
|
3448
|
+
aliasMap.set(tagBlockMatch.alias.toLowerCase(), tagBlockMatch.name.toLowerCase());
|
|
3449
|
+
}
|
|
3450
|
+
result.tagGroups.push(currentTagGroup);
|
|
3451
|
+
continue;
|
|
3452
|
+
}
|
|
3453
|
+
}
|
|
3454
|
+
if (currentTagGroup && !contentStarted && indent > 0) {
|
|
3455
|
+
const isDefault = /\bdefault\s*$/.test(trimmed);
|
|
3456
|
+
const entryText = isDefault ? trimmed.replace(/\s+default\s*$/, "").trim() : trimmed;
|
|
3457
|
+
const { label, color } = extractColor(entryText, palette);
|
|
3458
|
+
if (!color) {
|
|
3459
|
+
result.diagnostics.push(makeDgmoError(
|
|
3460
|
+
lineNumber,
|
|
3461
|
+
`Expected 'Value(color)' in tag group '${currentTagGroup.name}'`,
|
|
3462
|
+
"warning"
|
|
3463
|
+
));
|
|
3464
|
+
continue;
|
|
3465
|
+
}
|
|
3466
|
+
if (isDefault) {
|
|
3467
|
+
currentTagGroup.defaultValue = label;
|
|
3468
|
+
}
|
|
3469
|
+
currentTagGroup.entries.push({ value: label, color, lineNumber });
|
|
3470
|
+
continue;
|
|
3471
|
+
}
|
|
3472
|
+
if (currentTagGroup && indent === 0) {
|
|
3473
|
+
currentTagGroup = null;
|
|
3474
|
+
}
|
|
3427
3475
|
if (!contentStarted && indent === 0 && /^[a-z][a-z0-9-]*\s*:/i.test(trimmed)) {
|
|
3428
3476
|
const colonIdx = trimmed.indexOf(":");
|
|
3429
3477
|
const key = trimmed.substring(0, colonIdx).trim().toLowerCase();
|
|
@@ -3505,6 +3553,11 @@ function parseERDiagram(content, palette) {
|
|
|
3505
3553
|
const table = getOrCreateTable(name, lineNumber);
|
|
3506
3554
|
if (color) table.color = color;
|
|
3507
3555
|
table.lineNumber = lineNumber;
|
|
3556
|
+
const pipeStr = tableDecl[3]?.trim();
|
|
3557
|
+
if (pipeStr) {
|
|
3558
|
+
const meta = parsePipeMetadata(["", pipeStr], aliasMap);
|
|
3559
|
+
Object.assign(table.metadata, meta);
|
|
3560
|
+
}
|
|
3508
3561
|
currentTable = table;
|
|
3509
3562
|
continue;
|
|
3510
3563
|
}
|
|
@@ -3514,6 +3567,27 @@ function parseERDiagram(content, palette) {
|
|
|
3514
3567
|
result.diagnostics.push(diag);
|
|
3515
3568
|
result.error = formatDgmoError(diag);
|
|
3516
3569
|
}
|
|
3570
|
+
if (result.tagGroups.length > 0) {
|
|
3571
|
+
const tagEntities = result.tables.map((t) => ({
|
|
3572
|
+
metadata: t.metadata,
|
|
3573
|
+
lineNumber: t.lineNumber
|
|
3574
|
+
}));
|
|
3575
|
+
validateTagValues(
|
|
3576
|
+
tagEntities,
|
|
3577
|
+
result.tagGroups,
|
|
3578
|
+
(line10, msg) => result.diagnostics.push(makeDgmoError(line10, msg, "warning")),
|
|
3579
|
+
suggest
|
|
3580
|
+
);
|
|
3581
|
+
for (const group of result.tagGroups) {
|
|
3582
|
+
if (!group.defaultValue) continue;
|
|
3583
|
+
const key = group.name.toLowerCase();
|
|
3584
|
+
for (const table of result.tables) {
|
|
3585
|
+
if (!table.metadata[key]) {
|
|
3586
|
+
table.metadata[key] = group.defaultValue;
|
|
3587
|
+
}
|
|
3588
|
+
}
|
|
3589
|
+
}
|
|
3590
|
+
}
|
|
3517
3591
|
if (result.tables.length >= 2 && result.relationships.length >= 1 && !result.error) {
|
|
3518
3592
|
const connectedIds = /* @__PURE__ */ new Set();
|
|
3519
3593
|
for (const rel of result.relationships) {
|
|
@@ -3565,7 +3639,8 @@ var init_parser3 = __esm({
|
|
|
3565
3639
|
init_colors();
|
|
3566
3640
|
init_diagnostics();
|
|
3567
3641
|
init_parsing();
|
|
3568
|
-
|
|
3642
|
+
init_tag_groups();
|
|
3643
|
+
TABLE_DECL_RE = /^([a-zA-Z_]\w*)(?:\s*\(([^)]+)\))?(?:\s*\|(.+))?$/;
|
|
3569
3644
|
COLUMN_RE = /^(\w+)(?:\s*:\s*(\w[\w()]*(?:\s*\[\])?))?(?:\s+\[([^\]]+)\])?\s*$/;
|
|
3570
3645
|
INDENT_REL_RE = /^([1*?])-(?:(.+)-)?([1*?])\s+([a-zA-Z_]\w*)\s*$/;
|
|
3571
3646
|
CONSTRAINT_MAP = {
|
|
@@ -3603,7 +3678,10 @@ function parseChart(content, palette) {
|
|
|
3603
3678
|
const trimmed = lines[i].trim();
|
|
3604
3679
|
const lineNumber = i + 1;
|
|
3605
3680
|
if (!trimmed) continue;
|
|
3606
|
-
if (/^#{2,}\s+/.test(trimmed))
|
|
3681
|
+
if (/^#{2,}\s+/.test(trimmed)) {
|
|
3682
|
+
result.diagnostics.push(makeDgmoError(lineNumber, `'${trimmed}' \u2014 ## syntax is no longer supported. Use [Group] containers instead`));
|
|
3683
|
+
continue;
|
|
3684
|
+
}
|
|
3607
3685
|
if (trimmed.startsWith("//")) continue;
|
|
3608
3686
|
const colonIndex = trimmed.indexOf(":");
|
|
3609
3687
|
if (colonIndex === -1) continue;
|
|
@@ -3750,9 +3828,16 @@ function parseEChart(content, palette) {
|
|
|
3750
3828
|
const trimmed = lines[i].trim();
|
|
3751
3829
|
const lineNumber = i + 1;
|
|
3752
3830
|
if (!trimmed) continue;
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3831
|
+
if (/^#{2,}\s+/.test(trimmed)) {
|
|
3832
|
+
const name = trimmed.replace(/^#{2,}\s+/, "").replace(/\s*\([^)]*\)\s*$/, "").trim();
|
|
3833
|
+
result.diagnostics.push(makeDgmoError(lineNumber, `'## ${name}' is no longer supported. Use '[${name}]' instead`));
|
|
3834
|
+
continue;
|
|
3835
|
+
}
|
|
3836
|
+
if (trimmed.startsWith("//")) continue;
|
|
3837
|
+
const categoryMatch = trimmed.match(/^\[(.+?)\](?:\s*\(([^)]+)\))?\s*$/);
|
|
3838
|
+
if (categoryMatch) {
|
|
3839
|
+
const catName = categoryMatch[1].trim();
|
|
3840
|
+
const catColor = categoryMatch[2] ? resolveColor(categoryMatch[2].trim(), palette) : null;
|
|
3756
3841
|
if (catColor) {
|
|
3757
3842
|
if (!result.categoryColors) result.categoryColors = {};
|
|
3758
3843
|
result.categoryColors[catName] = catColor;
|
|
@@ -3760,12 +3845,6 @@ function parseEChart(content, palette) {
|
|
|
3760
3845
|
currentCategory = catName;
|
|
3761
3846
|
continue;
|
|
3762
3847
|
}
|
|
3763
|
-
if (trimmed.startsWith("//")) continue;
|
|
3764
|
-
const categoryMatch = trimmed.match(/^\[(.+)\]$/);
|
|
3765
|
-
if (categoryMatch) {
|
|
3766
|
-
currentCategory = categoryMatch[1].trim();
|
|
3767
|
-
continue;
|
|
3768
|
-
}
|
|
3769
3848
|
const colonIndex = trimmed.indexOf(":");
|
|
3770
3849
|
if (result.type === "sankey" && colonIndex === -1) {
|
|
3771
3850
|
const indent = measureIndent(lines[i]);
|
|
@@ -5397,6 +5476,7 @@ function parseKanban(content, palette) {
|
|
|
5397
5476
|
let currentTagGroup = null;
|
|
5398
5477
|
let currentColumn = null;
|
|
5399
5478
|
let currentCard = null;
|
|
5479
|
+
let cardBaseIndent = 0;
|
|
5400
5480
|
let columnCounter = 0;
|
|
5401
5481
|
let cardCounter = 0;
|
|
5402
5482
|
const aliasMap = /* @__PURE__ */ new Map();
|
|
@@ -5496,7 +5576,14 @@ function parseKanban(content, palette) {
|
|
|
5496
5576
|
}
|
|
5497
5577
|
currentTagGroup = null;
|
|
5498
5578
|
}
|
|
5499
|
-
const
|
|
5579
|
+
const indent = measureIndent(line10);
|
|
5580
|
+
if (LEGACY_COLUMN_RE.test(trimmed)) {
|
|
5581
|
+
const legacyMatch = trimmed.match(LEGACY_COLUMN_RE);
|
|
5582
|
+
const name = legacyMatch[1].replace(/\s*\(.*\)\s*$/, "").trim();
|
|
5583
|
+
warn(lineNumber, `'== ${name} ==' is no longer supported. Use '[${name}]' instead`);
|
|
5584
|
+
continue;
|
|
5585
|
+
}
|
|
5586
|
+
const columnMatch = indent === 0 ? trimmed.match(COLUMN_RE2) : null;
|
|
5500
5587
|
if (columnMatch) {
|
|
5501
5588
|
contentStarted = true;
|
|
5502
5589
|
currentTagGroup = null;
|
|
@@ -5508,16 +5595,20 @@ function parseKanban(content, palette) {
|
|
|
5508
5595
|
}
|
|
5509
5596
|
currentCard = null;
|
|
5510
5597
|
columnCounter++;
|
|
5511
|
-
const
|
|
5512
|
-
const
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
|
|
5598
|
+
const colName = columnMatch[1].trim();
|
|
5599
|
+
const colColor = columnMatch[2] ? resolveColor(columnMatch[2].trim(), palette) : void 0;
|
|
5600
|
+
let wipLimit;
|
|
5601
|
+
const pipeStr = columnMatch[3];
|
|
5602
|
+
if (pipeStr) {
|
|
5603
|
+
const wipMatch = pipeStr.match(/\bwip\s*:\s*(\d+)\b/i);
|
|
5604
|
+
if (wipMatch) {
|
|
5605
|
+
wipLimit = parseInt(wipMatch[1], 10);
|
|
5606
|
+
}
|
|
5607
|
+
}
|
|
5517
5608
|
currentColumn = {
|
|
5518
5609
|
id: `col-${columnCounter}`,
|
|
5519
5610
|
name: colName,
|
|
5520
|
-
wipLimit
|
|
5611
|
+
wipLimit,
|
|
5521
5612
|
color: colColor,
|
|
5522
5613
|
cards: [],
|
|
5523
5614
|
lineNumber
|
|
@@ -5532,24 +5623,25 @@ function parseKanban(content, palette) {
|
|
|
5532
5623
|
warn(lineNumber, "Card line found before any column");
|
|
5533
5624
|
continue;
|
|
5534
5625
|
}
|
|
5535
|
-
|
|
5536
|
-
if (indent > 0 && currentCard) {
|
|
5626
|
+
if (currentCard && indent > cardBaseIndent) {
|
|
5537
5627
|
currentCard.details.push(trimmed);
|
|
5538
5628
|
currentCard.endLineNumber = lineNumber;
|
|
5539
5629
|
continue;
|
|
5540
5630
|
}
|
|
5541
|
-
if (
|
|
5631
|
+
if (indent > 0) {
|
|
5632
|
+
cardCounter++;
|
|
5633
|
+
const card = parseCardLine(
|
|
5634
|
+
trimmed,
|
|
5635
|
+
lineNumber,
|
|
5636
|
+
cardCounter,
|
|
5637
|
+
aliasMap,
|
|
5638
|
+
palette
|
|
5639
|
+
);
|
|
5640
|
+
cardBaseIndent = indent;
|
|
5641
|
+
currentCard = card;
|
|
5642
|
+
currentColumn.cards.push(card);
|
|
5643
|
+
continue;
|
|
5542
5644
|
}
|
|
5543
|
-
cardCounter++;
|
|
5544
|
-
const card = parseCardLine(
|
|
5545
|
-
trimmed,
|
|
5546
|
-
lineNumber,
|
|
5547
|
-
cardCounter,
|
|
5548
|
-
aliasMap,
|
|
5549
|
-
palette
|
|
5550
|
-
);
|
|
5551
|
-
currentCard = card;
|
|
5552
|
-
currentColumn.cards.push(card);
|
|
5553
5645
|
}
|
|
5554
5646
|
if (currentCard) {
|
|
5555
5647
|
}
|
|
@@ -5583,7 +5675,7 @@ function parseKanban(content, palette) {
|
|
|
5583
5675
|
}
|
|
5584
5676
|
}
|
|
5585
5677
|
if (result.columns.length === 0 && !result.error) {
|
|
5586
|
-
return fail(1, "No columns found. Use
|
|
5678
|
+
return fail(1, "No columns found. Use [Column Name] to define columns");
|
|
5587
5679
|
}
|
|
5588
5680
|
return result;
|
|
5589
5681
|
}
|
|
@@ -5620,14 +5712,16 @@ function parseCardLine(trimmed, lineNumber, counter, aliasMap, palette) {
|
|
|
5620
5712
|
color
|
|
5621
5713
|
};
|
|
5622
5714
|
}
|
|
5623
|
-
var COLUMN_RE2;
|
|
5715
|
+
var COLUMN_RE2, LEGACY_COLUMN_RE;
|
|
5624
5716
|
var init_parser5 = __esm({
|
|
5625
5717
|
"src/kanban/parser.ts"() {
|
|
5626
5718
|
"use strict";
|
|
5627
5719
|
init_diagnostics();
|
|
5720
|
+
init_colors();
|
|
5628
5721
|
init_tag_groups();
|
|
5629
5722
|
init_parsing();
|
|
5630
|
-
COLUMN_RE2 =
|
|
5723
|
+
COLUMN_RE2 = /^\[(.+?)\](?:\s*\(([^)]+)\))?\s*(?:\|\s*(.+))?$/;
|
|
5724
|
+
LEGACY_COLUMN_RE = /^==\s+(.+?)\s*(?:\[wip:\s*(\d+)\])?\s*==$/;
|
|
5631
5725
|
}
|
|
5632
5726
|
});
|
|
5633
5727
|
|
|
@@ -7212,7 +7306,7 @@ var init_parser9 = __esm({
|
|
|
7212
7306
|
TAG_GROUP_RE = /^tag\s*:\s*(\w[\w\s]*?)(?:\s+alias\s+(\w+))?\s*$/;
|
|
7213
7307
|
TAG_VALUE_RE = /^(\w[\w\s]*?)(?:\(([^)]+)\))?(\s+default)?\s*$/;
|
|
7214
7308
|
COMPONENT_RE = /^([a-zA-Z_][\w]*)(.*)$/;
|
|
7215
|
-
PIPE_META_RE =
|
|
7309
|
+
PIPE_META_RE = /[|,]\s*(\w+)\s*:\s*([^|,]+)/g;
|
|
7216
7310
|
PROPERTY_RE = /^([\w-]+)\s*:\s*(.+)$/;
|
|
7217
7311
|
PERCENT_RE = /^([\d.]+)%$/;
|
|
7218
7312
|
RANGE_RE = /^(\d+)-(\d+)$/;
|
|
@@ -9578,7 +9672,7 @@ function computeCardArchive(content, parsed, cardId) {
|
|
|
9578
9672
|
const trimmedEnd = withoutCard.length > 0 && withoutCard[withoutCard.length - 1].trim() === "" ? withoutCard : [...withoutCard, ""];
|
|
9579
9673
|
return [
|
|
9580
9674
|
...trimmedEnd,
|
|
9581
|
-
"
|
|
9675
|
+
"[Archive]",
|
|
9582
9676
|
...cardLines
|
|
9583
9677
|
].join("\n");
|
|
9584
9678
|
}
|
|
@@ -10457,7 +10551,7 @@ function drawCardinality(g, point, prevPoint, cardinality, color, useLabels) {
|
|
|
10457
10551
|
g.append("line").attr("x1", bx + px * spread).attr("y1", by + py * spread).attr("x2", bx - px * spread).attr("y2", by - py * spread).attr("stroke", color).attr("stroke-width", sw);
|
|
10458
10552
|
}
|
|
10459
10553
|
}
|
|
10460
|
-
function renderERDiagram(container, parsed, layout, palette, isDark, onClickItem, exportDims) {
|
|
10554
|
+
function renderERDiagram(container, parsed, layout, palette, isDark, onClickItem, exportDims, activeTagGroup) {
|
|
10461
10555
|
d3Selection5.select(container).selectAll(":not([data-d3-tooltip])").remove();
|
|
10462
10556
|
const width = exportDims?.width ?? container.clientWidth;
|
|
10463
10557
|
const height = exportDims?.height ?? container.clientHeight;
|
|
@@ -10527,8 +10621,16 @@ function renderERDiagram(container, parsed, layout, palette, isDark, onClickItem
|
|
|
10527
10621
|
}
|
|
10528
10622
|
for (let ni = 0; ni < layout.nodes.length; ni++) {
|
|
10529
10623
|
const node = layout.nodes[ni];
|
|
10530
|
-
const
|
|
10624
|
+
const tagColor = resolveTagColor(node.metadata, parsed.tagGroups, activeTagGroup ?? null);
|
|
10625
|
+
const nodeColor2 = node.color ?? tagColor ?? seriesColors2[ni % seriesColors2.length];
|
|
10531
10626
|
const nodeG = contentG.append("g").attr("transform", `translate(${node.x}, ${node.y})`).attr("class", "er-table").attr("data-line-number", String(node.lineNumber)).attr("data-node-id", node.id);
|
|
10627
|
+
if (activeTagGroup) {
|
|
10628
|
+
const tagKey = activeTagGroup.toLowerCase();
|
|
10629
|
+
const tagValue = node.metadata[tagKey];
|
|
10630
|
+
if (tagValue) {
|
|
10631
|
+
nodeG.attr(`data-tag-${tagKey}`, tagValue.toLowerCase());
|
|
10632
|
+
}
|
|
10633
|
+
}
|
|
10532
10634
|
if (onClickItem) {
|
|
10533
10635
|
nodeG.style("cursor", "pointer").on("click", () => {
|
|
10534
10636
|
onClickItem(node.lineNumber);
|
|
@@ -10560,6 +10662,35 @@ function renderERDiagram(container, parsed, layout, palette, isDark, onClickItem
|
|
|
10560
10662
|
}
|
|
10561
10663
|
}
|
|
10562
10664
|
}
|
|
10665
|
+
if (parsed.tagGroups.length > 0) {
|
|
10666
|
+
const LEGEND_Y_PAD = 16;
|
|
10667
|
+
const LEGEND_PILL_H = 22;
|
|
10668
|
+
const LEGEND_PILL_RX = 11;
|
|
10669
|
+
const LEGEND_PILL_PAD9 = 10;
|
|
10670
|
+
const LEGEND_GAP2 = 8;
|
|
10671
|
+
const LEGEND_FONT_SIZE2 = 11;
|
|
10672
|
+
const LEGEND_GROUP_GAP7 = 16;
|
|
10673
|
+
const legendG = svg.append("g").attr("class", "er-tag-legend");
|
|
10674
|
+
let legendX = DIAGRAM_PADDING5;
|
|
10675
|
+
let legendY = height - DIAGRAM_PADDING5;
|
|
10676
|
+
for (const group of parsed.tagGroups) {
|
|
10677
|
+
const groupG = legendG.append("g").attr("data-legend-group", group.name.toLowerCase());
|
|
10678
|
+
const labelText = groupG.append("text").attr("x", legendX).attr("y", legendY + LEGEND_PILL_H / 2).attr("dominant-baseline", "central").attr("fill", palette.textMuted).attr("font-size", LEGEND_FONT_SIZE2).attr("font-family", FONT_FAMILY).text(`${group.name}:`);
|
|
10679
|
+
const labelWidth = (labelText.node()?.getComputedTextLength?.() ?? group.name.length * 7) + 6;
|
|
10680
|
+
legendX += labelWidth;
|
|
10681
|
+
for (const entry of group.entries) {
|
|
10682
|
+
const pillG = groupG.append("g").attr("data-legend-entry", entry.value.toLowerCase()).style("cursor", "pointer");
|
|
10683
|
+
const tmpText = legendG.append("text").attr("font-size", LEGEND_FONT_SIZE2).attr("font-family", FONT_FAMILY).text(entry.value);
|
|
10684
|
+
const textW = tmpText.node()?.getComputedTextLength?.() ?? entry.value.length * 7;
|
|
10685
|
+
tmpText.remove();
|
|
10686
|
+
const pillW = textW + LEGEND_PILL_PAD9 * 2;
|
|
10687
|
+
pillG.append("rect").attr("x", legendX).attr("y", legendY).attr("width", pillW).attr("height", LEGEND_PILL_H).attr("rx", LEGEND_PILL_RX).attr("ry", LEGEND_PILL_RX).attr("fill", mix(entry.color, isDark ? palette.surface : palette.bg, 25)).attr("stroke", entry.color).attr("stroke-width", 1);
|
|
10688
|
+
pillG.append("text").attr("x", legendX + pillW / 2).attr("y", legendY + LEGEND_PILL_H / 2).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("fill", palette.text).attr("font-size", LEGEND_FONT_SIZE2).attr("font-family", FONT_FAMILY).text(entry.value);
|
|
10689
|
+
legendX += pillW + LEGEND_GAP2;
|
|
10690
|
+
}
|
|
10691
|
+
legendX += LEGEND_GROUP_GAP7;
|
|
10692
|
+
}
|
|
10693
|
+
}
|
|
10563
10694
|
}
|
|
10564
10695
|
function renderERDiagramForExport(content, theme, palette) {
|
|
10565
10696
|
const parsed = parseERDiagram(content, palette);
|
|
@@ -10605,6 +10736,7 @@ var init_renderer5 = __esm({
|
|
|
10605
10736
|
init_fonts();
|
|
10606
10737
|
init_color_utils();
|
|
10607
10738
|
init_palettes();
|
|
10739
|
+
init_tag_groups();
|
|
10608
10740
|
init_parser3();
|
|
10609
10741
|
init_layout4();
|
|
10610
10742
|
DIAGRAM_PADDING5 = 20;
|
|
@@ -15036,7 +15168,7 @@ function formatUptime(fraction) {
|
|
|
15036
15168
|
if (pct >= 99) return `${pct.toFixed(1)}%`;
|
|
15037
15169
|
return `${pct.toFixed(1)}%`;
|
|
15038
15170
|
}
|
|
15039
|
-
function layoutInfra(computed, selectedNodeId) {
|
|
15171
|
+
function layoutInfra(computed, selectedNodeId, collapsedNodes) {
|
|
15040
15172
|
if (computed.nodes.length === 0) {
|
|
15041
15173
|
return { nodes: [], edges: [], groups: [], options: {}, width: 0, height: 0 };
|
|
15042
15174
|
}
|
|
@@ -15057,9 +15189,10 @@ function layoutInfra(computed, selectedNodeId) {
|
|
|
15057
15189
|
const widthMap = /* @__PURE__ */ new Map();
|
|
15058
15190
|
const heightMap = /* @__PURE__ */ new Map();
|
|
15059
15191
|
for (const node of computed.nodes) {
|
|
15060
|
-
const
|
|
15192
|
+
const isNodeCollapsed = collapsedNodes?.has(node.id) ?? false;
|
|
15193
|
+
const expanded = !isNodeCollapsed && node.id === selectedNodeId;
|
|
15061
15194
|
const width = computeNodeWidth2(node, expanded, computed.options);
|
|
15062
|
-
const height = computeNodeHeight2(node, expanded, computed.options);
|
|
15195
|
+
const height = isNodeCollapsed ? NODE_HEADER_HEIGHT + NODE_PAD_BOTTOM : computeNodeHeight2(node, expanded, computed.options);
|
|
15063
15196
|
widthMap.set(node.id, width);
|
|
15064
15197
|
heightMap.set(node.id, height);
|
|
15065
15198
|
const inGroup = groupedNodeIds.has(node.id);
|
|
@@ -15632,10 +15765,27 @@ function renderEdgeLabels(svg, edges, palette, isDark, animate) {
|
|
|
15632
15765
|
}
|
|
15633
15766
|
}
|
|
15634
15767
|
}
|
|
15635
|
-
function
|
|
15768
|
+
function resolveActiveTagStroke(node, activeGroup, tagGroups, palette) {
|
|
15769
|
+
const tg = tagGroups.find((t) => t.name.toLowerCase() === activeGroup.toLowerCase());
|
|
15770
|
+
if (!tg) return null;
|
|
15771
|
+
const tagKey = (tg.alias ?? tg.name).toLowerCase();
|
|
15772
|
+
const tagVal = node.tags[tagKey];
|
|
15773
|
+
if (!tagVal) return null;
|
|
15774
|
+
const tv = tg.values.find((v) => v.name.toLowerCase() === tagVal.toLowerCase());
|
|
15775
|
+
if (!tv?.color) return null;
|
|
15776
|
+
return resolveColor(tv.color, palette);
|
|
15777
|
+
}
|
|
15778
|
+
function renderNodes(svg, nodes, palette, isDark, animate, selectedNodeId, activeGroup, diagramOptions, collapsedNodes, tagGroups) {
|
|
15636
15779
|
const mutedColor = palette.textMuted;
|
|
15637
15780
|
for (const node of nodes) {
|
|
15638
|
-
|
|
15781
|
+
let { fill: fill2, stroke: stroke2, textFill } = nodeColor(node, palette, isDark);
|
|
15782
|
+
if (activeGroup && tagGroups && !node.isEdge) {
|
|
15783
|
+
const tagStroke = resolveActiveTagStroke(node, activeGroup, tagGroups, palette);
|
|
15784
|
+
if (tagStroke) {
|
|
15785
|
+
stroke2 = tagStroke;
|
|
15786
|
+
fill2 = mix(palette.bg, tagStroke, isDark ? 88 : 94);
|
|
15787
|
+
}
|
|
15788
|
+
}
|
|
15639
15789
|
let cls = "infra-node";
|
|
15640
15790
|
if (animate && node.isEdge) {
|
|
15641
15791
|
cls += " infra-node-edge-throb";
|
|
@@ -15645,9 +15795,9 @@ function renderNodes(svg, nodes, palette, isDark, animate, selectedNodeId, activ
|
|
|
15645
15795
|
else if (severity === "overloaded") cls += " infra-node-overload";
|
|
15646
15796
|
else if (severity === "warning") cls += " infra-node-warning";
|
|
15647
15797
|
}
|
|
15648
|
-
const g = svg.append("g").attr("class", cls).attr("data-line-number", node.lineNumber).attr("data-infra-node", node.id);
|
|
15798
|
+
const g = svg.append("g").attr("class", cls).attr("data-line-number", node.lineNumber).attr("data-infra-node", node.id).attr("data-node-collapse", node.id).style("cursor", "pointer");
|
|
15649
15799
|
if (node.id.startsWith("[")) {
|
|
15650
|
-
g.attr("data-node-toggle", node.id)
|
|
15800
|
+
g.attr("data-node-toggle", node.id);
|
|
15651
15801
|
}
|
|
15652
15802
|
for (const [tagKey, tagVal] of Object.entries(node.tags)) {
|
|
15653
15803
|
g.attr(`data-tag-${tagKey.toLowerCase()}`, tagVal.toLowerCase());
|
|
@@ -15665,7 +15815,12 @@ function renderNodes(svg, nodes, palette, isDark, animate, selectedNodeId, activ
|
|
|
15665
15815
|
g.append("rect").attr("x", x).attr("y", y).attr("width", node.width).attr("height", node.height).attr("rx", NODE_BORDER_RADIUS).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-width", strokeWidth);
|
|
15666
15816
|
const headerCenterY = y + NODE_HEADER_HEIGHT2 / 2 + NODE_FONT_SIZE3 * 0.35;
|
|
15667
15817
|
g.append("text").attr("x", node.x).attr("y", headerCenterY).attr("text-anchor", "middle").attr("font-family", FONT_FAMILY).attr("font-size", NODE_FONT_SIZE3).attr("font-weight", "600").attr("fill", textFill).text(node.label);
|
|
15668
|
-
|
|
15818
|
+
const isNodeCollapsed = collapsedNodes?.has(node.id) ?? false;
|
|
15819
|
+
if (isNodeCollapsed) {
|
|
15820
|
+
const chevronY = y + node.height - 6;
|
|
15821
|
+
g.append("text").attr("x", node.x).attr("y", chevronY).attr("text-anchor", "middle").attr("font-family", FONT_FAMILY).attr("font-size", 8).attr("fill", textFill).attr("opacity", 0.5).text("\u25BC");
|
|
15822
|
+
}
|
|
15823
|
+
if (!isNodeCollapsed) {
|
|
15669
15824
|
const expanded = node.id === selectedNodeId;
|
|
15670
15825
|
const displayProps = !node.isEdge && expanded ? getDisplayProps(node, expanded, diagramOptions) : [];
|
|
15671
15826
|
const computedRows = getComputedRows(node, expanded);
|
|
@@ -15988,7 +16143,7 @@ function renderLegend3(rootSvg, legendGroups, totalWidth, legendY, palette, isDa
|
|
|
15988
16143
|
cursorX += fullW + LEGEND_GROUP_GAP5;
|
|
15989
16144
|
}
|
|
15990
16145
|
}
|
|
15991
|
-
function renderInfra(container, layout, palette, isDark, title, titleLineNumber, tagGroups, activeGroup, animate, playback, selectedNodeId, exportMode) {
|
|
16146
|
+
function renderInfra(container, layout, palette, isDark, title, titleLineNumber, tagGroups, activeGroup, animate, playback, selectedNodeId, exportMode, collapsedNodes) {
|
|
15992
16147
|
d3Selection9.select(container).selectAll(":not([data-d3-tooltip])").remove();
|
|
15993
16148
|
const legendGroups = computeInfraLegendGroups(layout.nodes, tagGroups ?? [], palette);
|
|
15994
16149
|
const hasLegend = legendGroups.length > 0 || !!playback;
|
|
@@ -16047,7 +16202,7 @@ function renderInfra(container, layout, palette, isDark, title, titleLineNumber,
|
|
|
16047
16202
|
}
|
|
16048
16203
|
renderGroups(svg, layout.groups, palette, isDark);
|
|
16049
16204
|
renderEdgePaths(svg, layout.edges, layout.nodes, palette, isDark, shouldAnimate);
|
|
16050
|
-
renderNodes(svg, layout.nodes, palette, isDark, shouldAnimate, selectedNodeId, activeGroup, layout.options);
|
|
16205
|
+
renderNodes(svg, layout.nodes, palette, isDark, shouldAnimate, selectedNodeId, activeGroup, layout.options, collapsedNodes, tagGroups ?? []);
|
|
16051
16206
|
if (shouldAnimate) {
|
|
16052
16207
|
renderRejectParticles(svg, layout.nodes);
|
|
16053
16208
|
}
|
|
@@ -17983,6 +18138,7 @@ function parseD3(content, palette) {
|
|
|
17983
18138
|
timelineGroups: [],
|
|
17984
18139
|
timelineEras: [],
|
|
17985
18140
|
timelineMarkers: [],
|
|
18141
|
+
timelineTagGroups: [],
|
|
17986
18142
|
timelineSort: "time",
|
|
17987
18143
|
timelineScale: true,
|
|
17988
18144
|
timelineSwimlanes: false,
|
|
@@ -18017,25 +18173,75 @@ function parseD3(content, palette) {
|
|
|
18017
18173
|
const freeformLines = [];
|
|
18018
18174
|
let currentArcGroup = null;
|
|
18019
18175
|
let currentTimelineGroup = null;
|
|
18176
|
+
let currentTimelineTagGroup = null;
|
|
18177
|
+
const timelineAliasMap = /* @__PURE__ */ new Map();
|
|
18020
18178
|
for (let i = 0; i < lines.length; i++) {
|
|
18021
|
-
const
|
|
18179
|
+
const rawLine = lines[i];
|
|
18180
|
+
const line10 = rawLine.trim();
|
|
18181
|
+
const indent = rawLine.length - rawLine.trimStart().length;
|
|
18022
18182
|
const lineNumber = i + 1;
|
|
18023
18183
|
if (!line10) continue;
|
|
18024
|
-
|
|
18025
|
-
|
|
18184
|
+
if (result.type === "timeline" && indent === 0) {
|
|
18185
|
+
const tagBlockMatch = matchTagBlockHeading(line10);
|
|
18186
|
+
if (tagBlockMatch) {
|
|
18187
|
+
if (tagBlockMatch.deprecated) {
|
|
18188
|
+
result.diagnostics.push(makeDgmoError(
|
|
18189
|
+
lineNumber,
|
|
18190
|
+
`'## ${tagBlockMatch.name}' is deprecated for tag groups \u2014 use 'tag: ${tagBlockMatch.name}' instead`,
|
|
18191
|
+
"warning"
|
|
18192
|
+
));
|
|
18193
|
+
}
|
|
18194
|
+
currentTimelineTagGroup = {
|
|
18195
|
+
name: tagBlockMatch.name,
|
|
18196
|
+
alias: tagBlockMatch.alias,
|
|
18197
|
+
entries: [],
|
|
18198
|
+
lineNumber
|
|
18199
|
+
};
|
|
18200
|
+
if (tagBlockMatch.alias) {
|
|
18201
|
+
timelineAliasMap.set(tagBlockMatch.alias.toLowerCase(), tagBlockMatch.name.toLowerCase());
|
|
18202
|
+
}
|
|
18203
|
+
result.timelineTagGroups.push(currentTimelineTagGroup);
|
|
18204
|
+
continue;
|
|
18205
|
+
}
|
|
18206
|
+
}
|
|
18207
|
+
if (currentTimelineTagGroup && indent > 0) {
|
|
18208
|
+
const trimmedEntry = line10;
|
|
18209
|
+
const isDefault = /\bdefault\s*$/.test(trimmedEntry);
|
|
18210
|
+
const entryText = isDefault ? trimmedEntry.replace(/\s+default\s*$/, "").trim() : trimmedEntry;
|
|
18211
|
+
const { label, color } = extractColor(entryText, palette);
|
|
18212
|
+
if (color) {
|
|
18213
|
+
if (isDefault) currentTimelineTagGroup.defaultValue = label;
|
|
18214
|
+
currentTimelineTagGroup.entries.push({ value: label, color, lineNumber });
|
|
18215
|
+
continue;
|
|
18216
|
+
}
|
|
18217
|
+
}
|
|
18218
|
+
if (currentTimelineTagGroup && indent === 0) {
|
|
18219
|
+
currentTimelineTagGroup = null;
|
|
18220
|
+
}
|
|
18221
|
+
const groupMatch = line10.match(/^\[(.+?)\](?:\s*\(([^)]+)\))?\s*$/);
|
|
18222
|
+
if (groupMatch) {
|
|
18026
18223
|
if (result.type === "arc") {
|
|
18027
|
-
const name =
|
|
18028
|
-
const color =
|
|
18224
|
+
const name = groupMatch[1].trim();
|
|
18225
|
+
const color = groupMatch[2] ? resolveColor(groupMatch[2].trim(), palette) : null;
|
|
18029
18226
|
result.arcNodeGroups.push({ name, nodes: [], color, lineNumber });
|
|
18030
18227
|
currentArcGroup = name;
|
|
18031
18228
|
} else if (result.type === "timeline") {
|
|
18032
|
-
const name =
|
|
18033
|
-
const color =
|
|
18229
|
+
const name = groupMatch[1].trim();
|
|
18230
|
+
const color = groupMatch[2] ? resolveColor(groupMatch[2].trim(), palette) : null;
|
|
18034
18231
|
result.timelineGroups.push({ name, color, lineNumber });
|
|
18035
18232
|
currentTimelineGroup = name;
|
|
18036
18233
|
}
|
|
18037
18234
|
continue;
|
|
18038
18235
|
}
|
|
18236
|
+
if (/^#{2,}\s+/.test(line10) && (result.type === "arc" || result.type === "timeline")) {
|
|
18237
|
+
const name = line10.replace(/^#{2,}\s+/, "").replace(/\s*\([^)]*\)\s*$/, "").trim();
|
|
18238
|
+
result.diagnostics.push(makeDgmoError(lineNumber, `'## ${name}' is no longer supported. Use '[${name}]' instead`, "warning"));
|
|
18239
|
+
continue;
|
|
18240
|
+
}
|
|
18241
|
+
if (indent === 0) {
|
|
18242
|
+
currentArcGroup = null;
|
|
18243
|
+
currentTimelineGroup = null;
|
|
18244
|
+
}
|
|
18039
18245
|
if (line10.startsWith("//")) {
|
|
18040
18246
|
continue;
|
|
18041
18247
|
}
|
|
@@ -18107,11 +18313,14 @@ function parseD3(content, palette) {
|
|
|
18107
18313
|
const amount = parseFloat(durationMatch[2]);
|
|
18108
18314
|
const unit = durationMatch[3];
|
|
18109
18315
|
const endDate = addDurationToDate(startDate, amount, unit);
|
|
18316
|
+
const segments = durationMatch[5].split("|");
|
|
18317
|
+
const metadata = segments.length > 1 ? parsePipeMetadata(["", ...segments.slice(1)], timelineAliasMap) : {};
|
|
18110
18318
|
result.timelineEvents.push({
|
|
18111
18319
|
date: startDate,
|
|
18112
18320
|
endDate,
|
|
18113
|
-
label:
|
|
18321
|
+
label: segments[0].trim(),
|
|
18114
18322
|
group: currentTimelineGroup,
|
|
18323
|
+
metadata,
|
|
18115
18324
|
lineNumber,
|
|
18116
18325
|
uncertain
|
|
18117
18326
|
});
|
|
@@ -18121,11 +18330,14 @@ function parseD3(content, palette) {
|
|
|
18121
18330
|
/^(\d{4}(?:-\d{2})?(?:-\d{2})?)\s*->\s*(\d{4}(?:-\d{2})?(?:-\d{2})?)(\?)?\s*:\s*(.+)$/
|
|
18122
18331
|
);
|
|
18123
18332
|
if (rangeMatch) {
|
|
18333
|
+
const segments = rangeMatch[4].split("|");
|
|
18334
|
+
const metadata = segments.length > 1 ? parsePipeMetadata(["", ...segments.slice(1)], timelineAliasMap) : {};
|
|
18124
18335
|
result.timelineEvents.push({
|
|
18125
18336
|
date: rangeMatch[1],
|
|
18126
18337
|
endDate: rangeMatch[2],
|
|
18127
|
-
label:
|
|
18338
|
+
label: segments[0].trim(),
|
|
18128
18339
|
group: currentTimelineGroup,
|
|
18340
|
+
metadata,
|
|
18129
18341
|
lineNumber,
|
|
18130
18342
|
uncertain: rangeMatch[3] === "?"
|
|
18131
18343
|
});
|
|
@@ -18135,11 +18347,14 @@ function parseD3(content, palette) {
|
|
|
18135
18347
|
/^(\d{4}(?:-\d{2})?(?:-\d{2})?)\s*:\s*(.+)$/
|
|
18136
18348
|
);
|
|
18137
18349
|
if (pointMatch) {
|
|
18350
|
+
const segments = pointMatch[2].split("|");
|
|
18351
|
+
const metadata = segments.length > 1 ? parsePipeMetadata(["", ...segments.slice(1)], timelineAliasMap) : {};
|
|
18138
18352
|
result.timelineEvents.push({
|
|
18139
18353
|
date: pointMatch[1],
|
|
18140
18354
|
endDate: null,
|
|
18141
|
-
label:
|
|
18355
|
+
label: segments[0].trim(),
|
|
18142
18356
|
group: currentTimelineGroup,
|
|
18357
|
+
metadata,
|
|
18143
18358
|
lineNumber
|
|
18144
18359
|
});
|
|
18145
18360
|
continue;
|
|
@@ -18402,7 +18617,7 @@ function parseD3(content, palette) {
|
|
|
18402
18617
|
}
|
|
18403
18618
|
if (result.arcNodeGroups.length > 0) {
|
|
18404
18619
|
if (result.arcOrder === "name" || result.arcOrder === "degree") {
|
|
18405
|
-
warn(1, `Cannot use "order: ${result.arcOrder}" with
|
|
18620
|
+
warn(1, `Cannot use "order: ${result.arcOrder}" with [Group] headers. Use "order: group" or remove group headers.`);
|
|
18406
18621
|
result.arcOrder = "group";
|
|
18407
18622
|
}
|
|
18408
18623
|
if (result.arcOrder === "appearance") {
|
|
@@ -18415,6 +18630,23 @@ function parseD3(content, palette) {
|
|
|
18415
18630
|
if (result.timelineEvents.length === 0) {
|
|
18416
18631
|
warn(1, 'No events found. Add events as "YYYY: description" or "YYYY->YYYY: description"');
|
|
18417
18632
|
}
|
|
18633
|
+
if (result.timelineTagGroups.length > 0) {
|
|
18634
|
+
validateTagValues(
|
|
18635
|
+
result.timelineEvents,
|
|
18636
|
+
result.timelineTagGroups,
|
|
18637
|
+
(line10, msg) => result.diagnostics.push(makeDgmoError(line10, msg, "warning")),
|
|
18638
|
+
suggest
|
|
18639
|
+
);
|
|
18640
|
+
for (const group of result.timelineTagGroups) {
|
|
18641
|
+
if (!group.defaultValue) continue;
|
|
18642
|
+
const key = group.name.toLowerCase();
|
|
18643
|
+
for (const event of result.timelineEvents) {
|
|
18644
|
+
if (!event.metadata[key]) {
|
|
18645
|
+
event.metadata[key] = group.defaultValue;
|
|
18646
|
+
}
|
|
18647
|
+
}
|
|
18648
|
+
}
|
|
18649
|
+
}
|
|
18418
18650
|
return result;
|
|
18419
18651
|
}
|
|
18420
18652
|
if (result.type === "venn") {
|
|
@@ -19173,7 +19405,7 @@ function buildEventTooltipHtml(ev) {
|
|
|
19173
19405
|
function buildEraTooltipHtml(era) {
|
|
19174
19406
|
return `<strong>${era.label}</strong><br>${formatDateLabel(era.startDate)} \u2192 ${formatDateLabel(era.endDate)}`;
|
|
19175
19407
|
}
|
|
19176
|
-
function renderTimeline(container, parsed, palette, isDark, onClickItem, exportDims) {
|
|
19408
|
+
function renderTimeline(container, parsed, palette, isDark, onClickItem, exportDims, activeTagGroup) {
|
|
19177
19409
|
d3Selection12.select(container).selectAll(":not([data-d3-tooltip])").remove();
|
|
19178
19410
|
const {
|
|
19179
19411
|
timelineEvents,
|
|
@@ -19201,6 +19433,10 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
19201
19433
|
groupColorMap.set(grp.name, grp.color ?? colors[i % colors.length]);
|
|
19202
19434
|
});
|
|
19203
19435
|
function eventColor(ev) {
|
|
19436
|
+
if (activeTagGroup) {
|
|
19437
|
+
const tagColor = resolveTagColor(ev.metadata, parsed.timelineTagGroups, activeTagGroup);
|
|
19438
|
+
if (tagColor) return tagColor;
|
|
19439
|
+
}
|
|
19204
19440
|
if (ev.group && groupColorMap.has(ev.group)) {
|
|
19205
19441
|
return groupColorMap.get(ev.group);
|
|
19206
19442
|
}
|
|
@@ -19271,10 +19507,36 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
19271
19507
|
}
|
|
19272
19508
|
function fadeReset(g) {
|
|
19273
19509
|
g.selectAll(
|
|
19274
|
-
".tl-event, .tl-legend-item, .tl-lane-header, .tl-marker"
|
|
19510
|
+
".tl-event, .tl-legend-item, .tl-lane-header, .tl-marker, .tl-tag-legend-entry"
|
|
19275
19511
|
).attr("opacity", 1);
|
|
19276
19512
|
g.selectAll(".tl-era").attr("opacity", 1);
|
|
19277
19513
|
}
|
|
19514
|
+
function fadeToTagValue(g, tagKey, tagValue) {
|
|
19515
|
+
const attrName = `data-tag-${tagKey}`;
|
|
19516
|
+
g.selectAll(".tl-event").each(function() {
|
|
19517
|
+
const el = d3Selection12.select(this);
|
|
19518
|
+
const val = el.attr(attrName);
|
|
19519
|
+
el.attr("opacity", val === tagValue ? 1 : FADE_OPACITY);
|
|
19520
|
+
});
|
|
19521
|
+
g.selectAll(".tl-legend-item, .tl-lane-header").attr(
|
|
19522
|
+
"opacity",
|
|
19523
|
+
FADE_OPACITY
|
|
19524
|
+
);
|
|
19525
|
+
g.selectAll(".tl-marker").attr("opacity", FADE_OPACITY);
|
|
19526
|
+
g.selectAll(".tl-tag-legend-entry").each(function() {
|
|
19527
|
+
const el = d3Selection12.select(this);
|
|
19528
|
+
const entryValue = el.attr("data-legend-entry");
|
|
19529
|
+
if (entryValue === "__group__") return;
|
|
19530
|
+
const entryGroup = el.attr("data-tag-group");
|
|
19531
|
+
el.attr("opacity", entryGroup === tagKey && entryValue === tagValue ? 1 : FADE_OPACITY);
|
|
19532
|
+
});
|
|
19533
|
+
}
|
|
19534
|
+
function setTagAttrs(evG, ev) {
|
|
19535
|
+
for (const [key, value] of Object.entries(ev.metadata)) {
|
|
19536
|
+
evG.attr(`data-tag-${key}`, value.toLowerCase());
|
|
19537
|
+
}
|
|
19538
|
+
}
|
|
19539
|
+
const tagLegendReserve = parsed.timelineTagGroups.length > 0 ? 36 : 0;
|
|
19278
19540
|
if (isVertical) {
|
|
19279
19541
|
if (timelineSort === "group" && timelineGroups.length > 0) {
|
|
19280
19542
|
const groupNames = timelineGroups.map((gr) => gr.name);
|
|
@@ -19286,7 +19548,7 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
19286
19548
|
const scaleMargin = timelineScale ? 40 : 0;
|
|
19287
19549
|
const markerMargin = timelineMarkers.length > 0 ? 30 : 0;
|
|
19288
19550
|
const margin = {
|
|
19289
|
-
top: 104 + markerMargin,
|
|
19551
|
+
top: 104 + markerMargin + tagLegendReserve,
|
|
19290
19552
|
right: 40 + scaleMargin,
|
|
19291
19553
|
bottom: 40,
|
|
19292
19554
|
left: 60 + scaleMargin
|
|
@@ -19362,6 +19624,7 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
19362
19624
|
}).on("click", () => {
|
|
19363
19625
|
if (onClickItem && ev.lineNumber) onClickItem(ev.lineNumber);
|
|
19364
19626
|
});
|
|
19627
|
+
setTagAttrs(evG, ev);
|
|
19365
19628
|
if (ev.endDate) {
|
|
19366
19629
|
const y2 = yScale(parseTimelineDate(ev.endDate));
|
|
19367
19630
|
const rectH = Math.max(y2 - y, 4);
|
|
@@ -19388,7 +19651,7 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
19388
19651
|
const scaleMargin = timelineScale ? 40 : 0;
|
|
19389
19652
|
const markerMargin = timelineMarkers.length > 0 ? 30 : 0;
|
|
19390
19653
|
const margin = {
|
|
19391
|
-
top: 104 + markerMargin,
|
|
19654
|
+
top: 104 + markerMargin + tagLegendReserve,
|
|
19392
19655
|
right: 200,
|
|
19393
19656
|
bottom: 40,
|
|
19394
19657
|
left: 60 + scaleMargin
|
|
@@ -19468,6 +19731,7 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
19468
19731
|
}).on("click", () => {
|
|
19469
19732
|
if (onClickItem && ev.lineNumber) onClickItem(ev.lineNumber);
|
|
19470
19733
|
});
|
|
19734
|
+
setTagAttrs(evG, ev);
|
|
19471
19735
|
if (ev.endDate) {
|
|
19472
19736
|
const y2 = yScale(parseTimelineDate(ev.endDate));
|
|
19473
19737
|
const rectH = Math.max(y2 - y, 4);
|
|
@@ -19520,7 +19784,7 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
19520
19784
|
const dynamicLeftMargin = Math.max(120, maxGroupNameLen * 7 + 30);
|
|
19521
19785
|
const baseTopMargin = title ? 50 : 20;
|
|
19522
19786
|
const margin = {
|
|
19523
|
-
top: baseTopMargin + (timelineScale ? 40 : 0) + markerMargin,
|
|
19787
|
+
top: baseTopMargin + (timelineScale ? 40 : 0) + markerMargin + tagLegendReserve,
|
|
19524
19788
|
right: 40,
|
|
19525
19789
|
bottom: 40 + scaleMargin,
|
|
19526
19790
|
left: dynamicLeftMargin
|
|
@@ -19623,6 +19887,7 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
19623
19887
|
}).on("click", () => {
|
|
19624
19888
|
if (onClickItem && ev.lineNumber) onClickItem(ev.lineNumber);
|
|
19625
19889
|
});
|
|
19890
|
+
setTagAttrs(evG, ev);
|
|
19626
19891
|
if (ev.endDate) {
|
|
19627
19892
|
const x2 = xScale(parseTimelineDate(ev.endDate));
|
|
19628
19893
|
const rectW = Math.max(x2 - x, 4);
|
|
@@ -19664,7 +19929,7 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
19664
19929
|
const scaleMargin = timelineScale ? 24 : 0;
|
|
19665
19930
|
const markerMargin = timelineMarkers.length > 0 ? 30 : 0;
|
|
19666
19931
|
const margin = {
|
|
19667
|
-
top: 104 + (timelineScale ? 40 : 0) + markerMargin,
|
|
19932
|
+
top: 104 + (timelineScale ? 40 : 0) + markerMargin + tagLegendReserve,
|
|
19668
19933
|
right: 40,
|
|
19669
19934
|
bottom: 40 + scaleMargin,
|
|
19670
19935
|
left: 60
|
|
@@ -19760,6 +20025,7 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
19760
20025
|
}).on("click", () => {
|
|
19761
20026
|
if (onClickItem && ev.lineNumber) onClickItem(ev.lineNumber);
|
|
19762
20027
|
});
|
|
20028
|
+
setTagAttrs(evG, ev);
|
|
19763
20029
|
if (ev.endDate) {
|
|
19764
20030
|
const x2 = xScale(parseTimelineDate(ev.endDate));
|
|
19765
20031
|
const rectW = Math.max(x2 - x, 4);
|
|
@@ -19795,6 +20061,124 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
19795
20061
|
}
|
|
19796
20062
|
});
|
|
19797
20063
|
}
|
|
20064
|
+
if (parsed.timelineTagGroups.length > 0) {
|
|
20065
|
+
const LG_HEIGHT = 28;
|
|
20066
|
+
const LG_PILL_PAD = 16;
|
|
20067
|
+
const LG_PILL_FONT_SIZE = 11;
|
|
20068
|
+
const LG_PILL_FONT_W = LG_PILL_FONT_SIZE * 0.6;
|
|
20069
|
+
const LG_CAPSULE_PAD = 4;
|
|
20070
|
+
const LG_DOT_R = 4;
|
|
20071
|
+
const LG_ENTRY_FONT_SIZE = 10;
|
|
20072
|
+
const LG_ENTRY_FONT_W = LG_ENTRY_FONT_SIZE * 0.6;
|
|
20073
|
+
const LG_ENTRY_DOT_GAP = 4;
|
|
20074
|
+
const LG_ENTRY_TRAIL = 8;
|
|
20075
|
+
const LG_GROUP_GAP = 12;
|
|
20076
|
+
const mainSvg = d3Selection12.select(container).select("svg");
|
|
20077
|
+
const mainG = mainSvg.select("g");
|
|
20078
|
+
if (!mainSvg.empty() && !mainG.empty()) {
|
|
20079
|
+
let drawLegend2 = function() {
|
|
20080
|
+
mainSvg.selectAll(".tl-tag-legend-group").remove();
|
|
20081
|
+
const totalW = legendGroups.reduce((s, lg) => {
|
|
20082
|
+
const isActive = currentActiveGroup != null && lg.group.name.toLowerCase() === currentActiveGroup.toLowerCase();
|
|
20083
|
+
return s + (isActive ? lg.expandedWidth : lg.minifiedWidth);
|
|
20084
|
+
}, 0) + (legendGroups.length - 1) * LG_GROUP_GAP;
|
|
20085
|
+
let cx = (width - totalW) / 2;
|
|
20086
|
+
for (const lg of legendGroups) {
|
|
20087
|
+
const isActive = currentActiveGroup != null && lg.group.name.toLowerCase() === currentActiveGroup.toLowerCase();
|
|
20088
|
+
const pillLabel = lg.group.name;
|
|
20089
|
+
const pillWidth = pillLabel.length * LG_PILL_FONT_W + LG_PILL_PAD;
|
|
20090
|
+
const gEl = mainSvg.append("g").attr("transform", `translate(${cx}, ${legendY})`).attr("class", "tl-tag-legend-group tl-tag-legend-entry").attr("data-legend-group", lg.group.name.toLowerCase()).attr("data-tag-group", lg.group.name.toLowerCase()).attr("data-legend-entry", "__group__").style("cursor", "pointer").on("click", () => {
|
|
20091
|
+
const groupKey = lg.group.name.toLowerCase();
|
|
20092
|
+
currentActiveGroup = currentActiveGroup === groupKey ? null : groupKey;
|
|
20093
|
+
drawLegend2();
|
|
20094
|
+
recolorEvents2();
|
|
20095
|
+
});
|
|
20096
|
+
if (isActive) {
|
|
20097
|
+
gEl.append("rect").attr("width", lg.expandedWidth).attr("height", LG_HEIGHT).attr("rx", LG_HEIGHT / 2).attr("fill", groupBg);
|
|
20098
|
+
}
|
|
20099
|
+
const pillXOff = isActive ? LG_CAPSULE_PAD : 0;
|
|
20100
|
+
const pillYOff = isActive ? LG_CAPSULE_PAD : 0;
|
|
20101
|
+
const pillH = LG_HEIGHT - (isActive ? LG_CAPSULE_PAD * 2 : 0);
|
|
20102
|
+
gEl.append("rect").attr("x", pillXOff).attr("y", pillYOff).attr("width", pillWidth).attr("height", pillH).attr("rx", pillH / 2).attr("fill", isActive ? palette.bg : groupBg);
|
|
20103
|
+
if (isActive) {
|
|
20104
|
+
gEl.append("rect").attr("x", pillXOff).attr("y", pillYOff).attr("width", pillWidth).attr("height", pillH).attr("rx", pillH / 2).attr("fill", "none").attr("stroke", mix(palette.textMuted, palette.bg, 50)).attr("stroke-width", 0.75);
|
|
20105
|
+
}
|
|
20106
|
+
gEl.append("text").attr("x", pillXOff + pillWidth / 2).attr("y", LG_HEIGHT / 2 + LG_PILL_FONT_SIZE / 2 - 2).attr("font-size", LG_PILL_FONT_SIZE).attr("font-weight", "500").attr("font-family", FONT_FAMILY).attr("fill", isActive ? palette.text : palette.textMuted).attr("text-anchor", "middle").text(pillLabel);
|
|
20107
|
+
if (isActive) {
|
|
20108
|
+
let entryX = pillXOff + pillWidth + 4;
|
|
20109
|
+
for (const entry of lg.group.entries) {
|
|
20110
|
+
const tagKey = lg.group.name.toLowerCase();
|
|
20111
|
+
const tagVal = entry.value.toLowerCase();
|
|
20112
|
+
const entryG = gEl.append("g").attr("class", "tl-tag-legend-entry").attr("data-tag-group", tagKey).attr("data-legend-entry", tagVal).style("cursor", "pointer").on("mouseenter", (event) => {
|
|
20113
|
+
event.stopPropagation();
|
|
20114
|
+
fadeToTagValue(mainG, tagKey, tagVal);
|
|
20115
|
+
mainSvg.selectAll(".tl-tag-legend-entry").each(function() {
|
|
20116
|
+
const el = d3Selection12.select(this);
|
|
20117
|
+
const ev = el.attr("data-legend-entry");
|
|
20118
|
+
if (ev === "__group__") return;
|
|
20119
|
+
const eg = el.attr("data-tag-group");
|
|
20120
|
+
el.attr("opacity", eg === tagKey && ev === tagVal ? 1 : FADE_OPACITY);
|
|
20121
|
+
});
|
|
20122
|
+
}).on("mouseleave", (event) => {
|
|
20123
|
+
event.stopPropagation();
|
|
20124
|
+
fadeReset(mainG);
|
|
20125
|
+
mainSvg.selectAll(".tl-tag-legend-entry").attr("opacity", 1);
|
|
20126
|
+
}).on("click", (event) => {
|
|
20127
|
+
event.stopPropagation();
|
|
20128
|
+
});
|
|
20129
|
+
entryG.append("circle").attr("cx", entryX + LG_DOT_R).attr("cy", LG_HEIGHT / 2).attr("r", LG_DOT_R).attr("fill", entry.color);
|
|
20130
|
+
const textX = entryX + LG_DOT_R * 2 + LG_ENTRY_DOT_GAP;
|
|
20131
|
+
entryG.append("text").attr("x", textX).attr("y", LG_HEIGHT / 2 + LG_ENTRY_FONT_SIZE / 2 - 1).attr("font-size", LG_ENTRY_FONT_SIZE).attr("font-family", FONT_FAMILY).attr("fill", palette.textMuted).text(entry.value);
|
|
20132
|
+
entryX = textX + entry.value.length * LG_ENTRY_FONT_W + LG_ENTRY_TRAIL;
|
|
20133
|
+
}
|
|
20134
|
+
}
|
|
20135
|
+
cx += (isActive ? lg.expandedWidth : lg.minifiedWidth) + LG_GROUP_GAP;
|
|
20136
|
+
}
|
|
20137
|
+
}, recolorEvents2 = function() {
|
|
20138
|
+
mainG.selectAll(".tl-event").each(function() {
|
|
20139
|
+
const el = d3Selection12.select(this);
|
|
20140
|
+
const lineNum = el.attr("data-line-number");
|
|
20141
|
+
const ev = lineNum ? eventByLine.get(lineNum) : void 0;
|
|
20142
|
+
if (!ev) return;
|
|
20143
|
+
let color;
|
|
20144
|
+
if (currentActiveGroup) {
|
|
20145
|
+
const tagColor = resolveTagColor(
|
|
20146
|
+
ev.metadata,
|
|
20147
|
+
parsed.timelineTagGroups,
|
|
20148
|
+
currentActiveGroup
|
|
20149
|
+
);
|
|
20150
|
+
color = tagColor ?? (ev.group && groupColorMap.has(ev.group) ? groupColorMap.get(ev.group) : textColor);
|
|
20151
|
+
} else {
|
|
20152
|
+
color = ev.group && groupColorMap.has(ev.group) ? groupColorMap.get(ev.group) : textColor;
|
|
20153
|
+
}
|
|
20154
|
+
el.selectAll("rect").attr("fill", color);
|
|
20155
|
+
el.selectAll("circle:not(.tl-event-point-outline)").attr("fill", color);
|
|
20156
|
+
});
|
|
20157
|
+
};
|
|
20158
|
+
var drawLegend = drawLegend2, recolorEvents = recolorEvents2;
|
|
20159
|
+
const legendY = title ? 50 : 10;
|
|
20160
|
+
const groupBg = isDark ? mix(palette.surface, palette.bg, 50) : mix(palette.surface, palette.bg, 30);
|
|
20161
|
+
const legendGroups = parsed.timelineTagGroups.map((g) => {
|
|
20162
|
+
const pillW = g.name.length * LG_PILL_FONT_W + LG_PILL_PAD;
|
|
20163
|
+
let entryX = LG_CAPSULE_PAD + pillW + 4;
|
|
20164
|
+
for (const entry of g.entries) {
|
|
20165
|
+
const textX = entryX + LG_DOT_R * 2 + LG_ENTRY_DOT_GAP;
|
|
20166
|
+
entryX = textX + entry.value.length * LG_ENTRY_FONT_W + LG_ENTRY_TRAIL;
|
|
20167
|
+
}
|
|
20168
|
+
return {
|
|
20169
|
+
group: g,
|
|
20170
|
+
minifiedWidth: pillW,
|
|
20171
|
+
expandedWidth: entryX + LG_CAPSULE_PAD
|
|
20172
|
+
};
|
|
20173
|
+
});
|
|
20174
|
+
let currentActiveGroup = activeTagGroup ?? null;
|
|
20175
|
+
const eventByLine = /* @__PURE__ */ new Map();
|
|
20176
|
+
for (const ev of timelineEvents) {
|
|
20177
|
+
eventByLine.set(String(ev.lineNumber), ev);
|
|
20178
|
+
}
|
|
20179
|
+
drawLegend2();
|
|
20180
|
+
}
|
|
20181
|
+
}
|
|
19798
20182
|
}
|
|
19799
20183
|
function getRotateFn(mode) {
|
|
19800
20184
|
if (mode === "mixed") return () => Math.random() > 0.5 ? 0 : 90;
|
|
@@ -20785,8 +21169,10 @@ var init_d3 = __esm({
|
|
|
20785
21169
|
init_branding();
|
|
20786
21170
|
init_colors();
|
|
20787
21171
|
init_palettes();
|
|
21172
|
+
init_color_utils();
|
|
20788
21173
|
init_diagnostics();
|
|
20789
21174
|
init_parsing();
|
|
21175
|
+
init_tag_groups();
|
|
20790
21176
|
DEFAULT_CLOUD_OPTIONS = {
|
|
20791
21177
|
rotate: "none",
|
|
20792
21178
|
max: 0,
|
|
@@ -21784,6 +22170,9 @@ function encodeDiagramUrl(dsl, options) {
|
|
|
21784
22170
|
if (options?.viewState?.activeTagGroup) {
|
|
21785
22171
|
hash += `&tag=${encodeURIComponent(options.viewState.activeTagGroup)}`;
|
|
21786
22172
|
}
|
|
22173
|
+
if (options?.viewState?.collapsedGroups?.length) {
|
|
22174
|
+
hash += `&cg=${encodeURIComponent(options.viewState.collapsedGroups.join(","))}`;
|
|
22175
|
+
}
|
|
21787
22176
|
return { url: `${baseUrl}?${hash}#${hash}` };
|
|
21788
22177
|
}
|
|
21789
22178
|
function decodeDiagramUrl(hash) {
|
|
@@ -21804,6 +22193,9 @@ function decodeDiagramUrl(hash) {
|
|
|
21804
22193
|
if (key === "tag" && val) {
|
|
21805
22194
|
viewState.activeTagGroup = val;
|
|
21806
22195
|
}
|
|
22196
|
+
if (key === "cg" && val) {
|
|
22197
|
+
viewState.collapsedGroups = val.split(",").filter(Boolean);
|
|
22198
|
+
}
|
|
21807
22199
|
}
|
|
21808
22200
|
if (payload.startsWith("dgmo=")) {
|
|
21809
22201
|
payload = payload.slice(5);
|