@diagrammo/dgmo 0.2.27 → 0.2.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/dgmo-chart/SKILL.md +107 -0
- package/.claude/skills/dgmo-flowchart/SKILL.md +61 -0
- package/.claude/skills/dgmo-generate/SKILL.md +58 -0
- package/.claude/skills/dgmo-sequence/SKILL.md +83 -0
- package/.cursorrules +117 -0
- package/.github/copilot-instructions.md +117 -0
- package/.windsurfrules +117 -0
- package/README.md +10 -3
- package/dist/cli.cjs +116 -108
- package/dist/index.cjs +543 -351
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +39 -24
- package/dist/index.d.ts +39 -24
- package/dist/index.js +540 -350
- package/dist/index.js.map +1 -1
- package/docs/ai-integration.md +125 -0
- package/docs/language-reference.md +784 -0
- package/package.json +10 -3
- package/src/c4/parser.ts +90 -74
- package/src/c4/renderer.ts +13 -12
- package/src/c4/types.ts +6 -4
- package/src/chart.ts +3 -2
- package/src/class/parser.ts +2 -10
- package/src/class/types.ts +1 -1
- package/src/cli.ts +130 -19
- package/src/d3.ts +1 -1
- package/src/dgmo-mermaid.ts +1 -1
- package/src/dgmo-router.ts +1 -1
- package/src/echarts.ts +33 -13
- package/src/er/parser.ts +34 -43
- package/src/er/types.ts +1 -1
- package/src/graph/flowchart-parser.ts +2 -25
- package/src/graph/types.ts +1 -1
- package/src/index.ts +5 -0
- package/src/initiative-status/parser.ts +36 -7
- package/src/initiative-status/types.ts +1 -1
- package/src/kanban/parser.ts +32 -53
- package/src/kanban/renderer.ts +9 -8
- package/src/kanban/types.ts +6 -14
- package/src/org/parser.ts +47 -87
- package/src/org/resolver.ts +11 -12
- package/src/sequence/parser.ts +97 -15
- package/src/sequence/renderer.ts +62 -69
- package/src/utils/arrows.ts +75 -0
- package/src/utils/inline-markdown.ts +75 -0
- package/src/utils/parsing.ts +67 -0
- package/src/utils/tag-groups.ts +76 -0
package/dist/index.cjs
CHANGED
|
@@ -1549,6 +1549,96 @@ var init_participant_inference = __esm({
|
|
|
1549
1549
|
}
|
|
1550
1550
|
});
|
|
1551
1551
|
|
|
1552
|
+
// src/utils/arrows.ts
|
|
1553
|
+
function parseArrow(line7) {
|
|
1554
|
+
const patterns = [
|
|
1555
|
+
{ re: BIDI_SYNC_LABELED_RE, async: false, bidirectional: true },
|
|
1556
|
+
{ re: BIDI_ASYNC_LABELED_RE, async: true, bidirectional: true },
|
|
1557
|
+
{ re: SYNC_LABELED_RE, async: false, bidirectional: false },
|
|
1558
|
+
{ re: ASYNC_LABELED_RE, async: true, bidirectional: false }
|
|
1559
|
+
];
|
|
1560
|
+
for (const { re, async: isAsync, bidirectional } of patterns) {
|
|
1561
|
+
const m = line7.match(re);
|
|
1562
|
+
if (!m) continue;
|
|
1563
|
+
const label = m[2].trim();
|
|
1564
|
+
if (!label) return null;
|
|
1565
|
+
for (const arrow of ARROW_CHARS) {
|
|
1566
|
+
if (label.includes(arrow)) {
|
|
1567
|
+
return {
|
|
1568
|
+
error: "Arrow characters (->, ~>) are not allowed inside labels"
|
|
1569
|
+
};
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
return {
|
|
1573
|
+
from: m[1],
|
|
1574
|
+
to: m[3],
|
|
1575
|
+
label,
|
|
1576
|
+
async: isAsync,
|
|
1577
|
+
bidirectional
|
|
1578
|
+
};
|
|
1579
|
+
}
|
|
1580
|
+
return null;
|
|
1581
|
+
}
|
|
1582
|
+
var BIDI_SYNC_LABELED_RE, BIDI_ASYNC_LABELED_RE, SYNC_LABELED_RE, ASYNC_LABELED_RE, ARROW_CHARS;
|
|
1583
|
+
var init_arrows = __esm({
|
|
1584
|
+
"src/utils/arrows.ts"() {
|
|
1585
|
+
"use strict";
|
|
1586
|
+
BIDI_SYNC_LABELED_RE = /^(\S+)\s+<-(.+)->\s+(\S+)$/;
|
|
1587
|
+
BIDI_ASYNC_LABELED_RE = /^(\S+)\s+<~(.+)~>\s+(\S+)$/;
|
|
1588
|
+
SYNC_LABELED_RE = /^(\S+)\s+-(.+)->\s+(\S+)$/;
|
|
1589
|
+
ASYNC_LABELED_RE = /^(\S+)\s+~(.+)~>\s+(\S+)$/;
|
|
1590
|
+
ARROW_CHARS = ["->", "~>", "<->", "<~>"];
|
|
1591
|
+
}
|
|
1592
|
+
});
|
|
1593
|
+
|
|
1594
|
+
// src/utils/parsing.ts
|
|
1595
|
+
function measureIndent(line7) {
|
|
1596
|
+
let indent = 0;
|
|
1597
|
+
for (const ch of line7) {
|
|
1598
|
+
if (ch === " ") indent++;
|
|
1599
|
+
else if (ch === " ") indent += 4;
|
|
1600
|
+
else break;
|
|
1601
|
+
}
|
|
1602
|
+
return indent;
|
|
1603
|
+
}
|
|
1604
|
+
function extractColor(label, palette) {
|
|
1605
|
+
const m = label.match(COLOR_SUFFIX_RE);
|
|
1606
|
+
if (!m) return { label };
|
|
1607
|
+
const colorName = m[1].trim();
|
|
1608
|
+
return {
|
|
1609
|
+
label: label.substring(0, m.index).trim(),
|
|
1610
|
+
color: resolveColor(colorName, palette)
|
|
1611
|
+
};
|
|
1612
|
+
}
|
|
1613
|
+
function parsePipeMetadata(segments, aliasMap = /* @__PURE__ */ new Map()) {
|
|
1614
|
+
const metadata = {};
|
|
1615
|
+
for (let j = 1; j < segments.length; j++) {
|
|
1616
|
+
for (const part of segments[j].split(",")) {
|
|
1617
|
+
const trimmedPart = part.trim();
|
|
1618
|
+
if (!trimmedPart) continue;
|
|
1619
|
+
const colonIdx = trimmedPart.indexOf(":");
|
|
1620
|
+
if (colonIdx > 0) {
|
|
1621
|
+
const rawKey = trimmedPart.substring(0, colonIdx).trim().toLowerCase();
|
|
1622
|
+
const key = aliasMap.get(rawKey) ?? rawKey;
|
|
1623
|
+
const value = trimmedPart.substring(colonIdx + 1).trim();
|
|
1624
|
+
metadata[key] = value;
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
return metadata;
|
|
1629
|
+
}
|
|
1630
|
+
var COLOR_SUFFIX_RE, CHART_TYPE_RE, TITLE_RE, OPTION_RE;
|
|
1631
|
+
var init_parsing = __esm({
|
|
1632
|
+
"src/utils/parsing.ts"() {
|
|
1633
|
+
"use strict";
|
|
1634
|
+
init_colors();
|
|
1635
|
+
COLOR_SUFFIX_RE = /\(([^)]+)\)\s*$/;
|
|
1636
|
+
CHART_TYPE_RE = /^chart\s*:\s*(.+)/i;
|
|
1637
|
+
TITLE_RE = /^title\s*:\s*(.+)/i;
|
|
1638
|
+
OPTION_RE = /^([a-z][a-z0-9-]*)\s*:\s*(.+)$/i;
|
|
1639
|
+
}
|
|
1640
|
+
});
|
|
1641
|
+
|
|
1552
1642
|
// src/sequence/parser.ts
|
|
1553
1643
|
var parser_exports = {};
|
|
1554
1644
|
__export(parser_exports, {
|
|
@@ -1590,15 +1680,6 @@ function parseReturnLabel(rawLabel) {
|
|
|
1590
1680
|
}
|
|
1591
1681
|
return { label: rawLabel };
|
|
1592
1682
|
}
|
|
1593
|
-
function measureIndent(line7) {
|
|
1594
|
-
let indent = 0;
|
|
1595
|
-
for (const ch of line7) {
|
|
1596
|
-
if (ch === " ") indent++;
|
|
1597
|
-
else if (ch === " ") indent += 4;
|
|
1598
|
-
else break;
|
|
1599
|
-
}
|
|
1600
|
-
return indent;
|
|
1601
|
-
}
|
|
1602
1683
|
function parseSequenceDgmo(content) {
|
|
1603
1684
|
const result = {
|
|
1604
1685
|
title: null,
|
|
@@ -1820,6 +1901,86 @@ function parseSequenceDgmo(content) {
|
|
|
1820
1901
|
pushError(lineNumber, "Use ~> for async messages: A ~> B: message");
|
|
1821
1902
|
continue;
|
|
1822
1903
|
}
|
|
1904
|
+
const labeledArrow = parseArrow(trimmed);
|
|
1905
|
+
if (labeledArrow && "error" in labeledArrow) {
|
|
1906
|
+
pushError(lineNumber, labeledArrow.error);
|
|
1907
|
+
continue;
|
|
1908
|
+
}
|
|
1909
|
+
if (labeledArrow) {
|
|
1910
|
+
contentStarted = true;
|
|
1911
|
+
const { from, to, label, async: isAsync2, bidirectional } = labeledArrow;
|
|
1912
|
+
lastMsgFrom = from;
|
|
1913
|
+
const msg = {
|
|
1914
|
+
from,
|
|
1915
|
+
to,
|
|
1916
|
+
label,
|
|
1917
|
+
returnLabel: void 0,
|
|
1918
|
+
lineNumber,
|
|
1919
|
+
...isAsync2 ? { async: true } : {},
|
|
1920
|
+
...bidirectional ? { bidirectional: true } : {}
|
|
1921
|
+
};
|
|
1922
|
+
result.messages.push(msg);
|
|
1923
|
+
currentContainer().push(msg);
|
|
1924
|
+
if (!result.participants.some((p) => p.id === from)) {
|
|
1925
|
+
result.participants.push({
|
|
1926
|
+
id: from,
|
|
1927
|
+
label: from,
|
|
1928
|
+
type: inferParticipantType(from),
|
|
1929
|
+
lineNumber
|
|
1930
|
+
});
|
|
1931
|
+
}
|
|
1932
|
+
if (!result.participants.some((p) => p.id === to)) {
|
|
1933
|
+
result.participants.push({
|
|
1934
|
+
id: to,
|
|
1935
|
+
label: to,
|
|
1936
|
+
type: inferParticipantType(to),
|
|
1937
|
+
lineNumber
|
|
1938
|
+
});
|
|
1939
|
+
}
|
|
1940
|
+
continue;
|
|
1941
|
+
}
|
|
1942
|
+
const bidiSyncMatch = trimmed.match(
|
|
1943
|
+
/^(\S+)\s*<->\s*([^\s:]+)\s*(?::\s*(.+))?$/
|
|
1944
|
+
);
|
|
1945
|
+
const bidiAsyncMatch = trimmed.match(
|
|
1946
|
+
/^(\S+)\s*<~>\s*([^\s:]+)\s*(?::\s*(.+))?$/
|
|
1947
|
+
);
|
|
1948
|
+
const bidiMatch = bidiSyncMatch || bidiAsyncMatch;
|
|
1949
|
+
if (bidiMatch) {
|
|
1950
|
+
contentStarted = true;
|
|
1951
|
+
const from = bidiMatch[1];
|
|
1952
|
+
const to = bidiMatch[2];
|
|
1953
|
+
lastMsgFrom = from;
|
|
1954
|
+
const rawLabel = bidiMatch[3]?.trim() || "";
|
|
1955
|
+
const isBidiAsync = !!bidiAsyncMatch;
|
|
1956
|
+
const msg = {
|
|
1957
|
+
from,
|
|
1958
|
+
to,
|
|
1959
|
+
label: rawLabel,
|
|
1960
|
+
lineNumber,
|
|
1961
|
+
bidirectional: true,
|
|
1962
|
+
...isBidiAsync ? { async: true } : {}
|
|
1963
|
+
};
|
|
1964
|
+
result.messages.push(msg);
|
|
1965
|
+
currentContainer().push(msg);
|
|
1966
|
+
if (!result.participants.some((p) => p.id === from)) {
|
|
1967
|
+
result.participants.push({
|
|
1968
|
+
id: from,
|
|
1969
|
+
label: from,
|
|
1970
|
+
type: inferParticipantType(from),
|
|
1971
|
+
lineNumber
|
|
1972
|
+
});
|
|
1973
|
+
}
|
|
1974
|
+
if (!result.participants.some((p) => p.id === to)) {
|
|
1975
|
+
result.participants.push({
|
|
1976
|
+
id: to,
|
|
1977
|
+
label: to,
|
|
1978
|
+
type: inferParticipantType(to),
|
|
1979
|
+
lineNumber
|
|
1980
|
+
});
|
|
1981
|
+
}
|
|
1982
|
+
continue;
|
|
1983
|
+
}
|
|
1823
1984
|
let isAsync = false;
|
|
1824
1985
|
const asyncArrowMatch = trimmed.match(
|
|
1825
1986
|
/^(\S+)\s*~>\s*([^\s:]+)\s*(?::\s*(.+))?$/
|
|
@@ -2057,6 +2218,8 @@ var init_parser = __esm({
|
|
|
2057
2218
|
"use strict";
|
|
2058
2219
|
init_participant_inference();
|
|
2059
2220
|
init_diagnostics();
|
|
2221
|
+
init_arrows();
|
|
2222
|
+
init_parsing();
|
|
2060
2223
|
VALID_PARTICIPANT_TYPES = /* @__PURE__ */ new Set([
|
|
2061
2224
|
"service",
|
|
2062
2225
|
"database",
|
|
@@ -2072,7 +2235,7 @@ var init_parser = __esm({
|
|
|
2072
2235
|
POSITION_ONLY_PATTERN = /^(\S+)\s+position\s+(-?\d+)$/i;
|
|
2073
2236
|
GROUP_HEADING_PATTERN = /^##\s+(.+?)(?:\(([^)]+)\))?\s*$/;
|
|
2074
2237
|
SECTION_PATTERN = /^==\s+(.+?)(?:\s*==)?\s*$/;
|
|
2075
|
-
ARROW_PATTERN = /\S+\s*(
|
|
2238
|
+
ARROW_PATTERN = /\S+\s*(?:<->|<~>|->|~>|-\S+->|~\S+~>|<-\S+->|<~\S+~>)\s*\S+/;
|
|
2076
2239
|
ARROW_RETURN_PATTERN = /^(.+?)\s*<-\s*(.+)$/;
|
|
2077
2240
|
UML_RETURN_PATTERN = /^(\w+\([^)]*\))\s*:\s*(.+)$/;
|
|
2078
2241
|
NOTE_SINGLE = /^note(?:\s+(right|left)\s+of\s+(\S+))?\s*:\s*(.+)$/i;
|
|
@@ -2086,27 +2249,9 @@ __export(flowchart_parser_exports, {
|
|
|
2086
2249
|
looksLikeFlowchart: () => looksLikeFlowchart,
|
|
2087
2250
|
parseFlowchart: () => parseFlowchart
|
|
2088
2251
|
});
|
|
2089
|
-
function measureIndent2(line7) {
|
|
2090
|
-
let indent = 0;
|
|
2091
|
-
for (const ch of line7) {
|
|
2092
|
-
if (ch === " ") indent++;
|
|
2093
|
-
else if (ch === " ") indent += 4;
|
|
2094
|
-
else break;
|
|
2095
|
-
}
|
|
2096
|
-
return indent;
|
|
2097
|
-
}
|
|
2098
2252
|
function nodeId(shape, label) {
|
|
2099
2253
|
return `${shape}:${label.toLowerCase().trim()}`;
|
|
2100
2254
|
}
|
|
2101
|
-
function extractColor(label, palette) {
|
|
2102
|
-
const m = label.match(COLOR_SUFFIX_RE);
|
|
2103
|
-
if (!m) return { label };
|
|
2104
|
-
const colorName = m[1].trim();
|
|
2105
|
-
return {
|
|
2106
|
-
label: label.substring(0, m.index).trim(),
|
|
2107
|
-
color: resolveColor(colorName, palette)
|
|
2108
|
-
};
|
|
2109
|
-
}
|
|
2110
2255
|
function parseNodeRef(text, palette) {
|
|
2111
2256
|
const t = text.trim();
|
|
2112
2257
|
if (!t) return null;
|
|
@@ -2221,7 +2366,8 @@ function parseFlowchart(content, palette) {
|
|
|
2221
2366
|
nodes: [],
|
|
2222
2367
|
edges: [],
|
|
2223
2368
|
options: {},
|
|
2224
|
-
diagnostics: []
|
|
2369
|
+
diagnostics: [],
|
|
2370
|
+
error: null
|
|
2225
2371
|
};
|
|
2226
2372
|
const fail = (line7, message) => {
|
|
2227
2373
|
const diag = makeDgmoError(line7, message);
|
|
@@ -2323,7 +2469,7 @@ function parseFlowchart(content, palette) {
|
|
|
2323
2469
|
const raw = lines[i];
|
|
2324
2470
|
const trimmed = raw.trim();
|
|
2325
2471
|
const lineNumber = i + 1;
|
|
2326
|
-
const indent =
|
|
2472
|
+
const indent = measureIndent(raw);
|
|
2327
2473
|
if (!trimmed) continue;
|
|
2328
2474
|
if (trimmed.startsWith("//")) continue;
|
|
2329
2475
|
const groupMatch = trimmed.match(GROUP_HEADING_RE);
|
|
@@ -2400,13 +2546,13 @@ function looksLikeFlowchart(content) {
|
|
|
2400
2546
|
/->[ \t]*[\[(<\/]/.test(content);
|
|
2401
2547
|
return shapeNearArrow;
|
|
2402
2548
|
}
|
|
2403
|
-
var
|
|
2549
|
+
var GROUP_HEADING_RE;
|
|
2404
2550
|
var init_flowchart_parser = __esm({
|
|
2405
2551
|
"src/graph/flowchart-parser.ts"() {
|
|
2406
2552
|
"use strict";
|
|
2407
2553
|
init_colors();
|
|
2408
2554
|
init_diagnostics();
|
|
2409
|
-
|
|
2555
|
+
init_parsing();
|
|
2410
2556
|
GROUP_HEADING_RE = /^##\s+(.+?)(?:\(([^)]+)\))?\s*$/;
|
|
2411
2557
|
}
|
|
2412
2558
|
});
|
|
@@ -2417,15 +2563,6 @@ __export(parser_exports2, {
|
|
|
2417
2563
|
looksLikeClassDiagram: () => looksLikeClassDiagram,
|
|
2418
2564
|
parseClassDiagram: () => parseClassDiagram
|
|
2419
2565
|
});
|
|
2420
|
-
function measureIndent3(line7) {
|
|
2421
|
-
let indent = 0;
|
|
2422
|
-
for (const ch of line7) {
|
|
2423
|
-
if (ch === " ") indent++;
|
|
2424
|
-
else if (ch === " ") indent += 4;
|
|
2425
|
-
else break;
|
|
2426
|
-
}
|
|
2427
|
-
return indent;
|
|
2428
|
-
}
|
|
2429
2566
|
function classId(name) {
|
|
2430
2567
|
return name.toLowerCase().trim();
|
|
2431
2568
|
}
|
|
@@ -2500,7 +2637,8 @@ function parseClassDiagram(content, palette) {
|
|
|
2500
2637
|
classes: [],
|
|
2501
2638
|
relationships: [],
|
|
2502
2639
|
options: {},
|
|
2503
|
-
diagnostics: []
|
|
2640
|
+
diagnostics: [],
|
|
2641
|
+
error: null
|
|
2504
2642
|
};
|
|
2505
2643
|
const fail = (line7, message) => {
|
|
2506
2644
|
const diag = makeDgmoError(line7, message);
|
|
@@ -2529,7 +2667,7 @@ function parseClassDiagram(content, palette) {
|
|
|
2529
2667
|
const raw = lines[i];
|
|
2530
2668
|
const trimmed = raw.trim();
|
|
2531
2669
|
const lineNumber = i + 1;
|
|
2532
|
-
const indent =
|
|
2670
|
+
const indent = measureIndent(raw);
|
|
2533
2671
|
if (!trimmed) {
|
|
2534
2672
|
if (indent === 0) currentClass = null;
|
|
2535
2673
|
continue;
|
|
@@ -2649,7 +2787,7 @@ function looksLikeClassDiagram(content) {
|
|
|
2649
2787
|
const trimmed = line7.trim();
|
|
2650
2788
|
if (!trimmed || trimmed.startsWith("//")) continue;
|
|
2651
2789
|
if (/^(chart|title)\s*:/i.test(trimmed)) continue;
|
|
2652
|
-
const indent =
|
|
2790
|
+
const indent = measureIndent(line7);
|
|
2653
2791
|
if (indent === 0) {
|
|
2654
2792
|
if (/^[A-Z][A-Za-z0-9_]*\s+\[(abstract|interface|enum)\]/i.test(trimmed)) {
|
|
2655
2793
|
hasModifier = true;
|
|
@@ -2680,6 +2818,7 @@ var init_parser2 = __esm({
|
|
|
2680
2818
|
"use strict";
|
|
2681
2819
|
init_colors();
|
|
2682
2820
|
init_diagnostics();
|
|
2821
|
+
init_parsing();
|
|
2683
2822
|
CLASS_DECL_RE = /^([A-Z][A-Za-z0-9_]*)(?:\s+\[(abstract|interface|enum)\])?(?:\s+\(([^)]+)\))?\s*$/;
|
|
2684
2823
|
REL_KEYWORD_RE = /^([A-Z][A-Za-z0-9_]*)\s+(extends|implements|contains|has|uses)\s+([A-Z][A-Za-z0-9_]*)(?:\s*:\s*(.+))?$/;
|
|
2685
2824
|
REL_ARROW_RE = /^([A-Z][A-Za-z0-9_]*)\s+(--\|>|\.\.\|>|\*--|o--|\.\.\>|->)\s+([A-Z][A-Za-z0-9_]*)(?:\s*:\s*(.+))?$/;
|
|
@@ -2711,22 +2850,14 @@ __export(parser_exports3, {
|
|
|
2711
2850
|
looksLikeERDiagram: () => looksLikeERDiagram,
|
|
2712
2851
|
parseERDiagram: () => parseERDiagram
|
|
2713
2852
|
});
|
|
2714
|
-
function measureIndent4(line7) {
|
|
2715
|
-
let indent = 0;
|
|
2716
|
-
for (const ch of line7) {
|
|
2717
|
-
if (ch === " ") indent++;
|
|
2718
|
-
else if (ch === " ") indent += 4;
|
|
2719
|
-
else break;
|
|
2720
|
-
}
|
|
2721
|
-
return indent;
|
|
2722
|
-
}
|
|
2723
2853
|
function tableId(name) {
|
|
2724
2854
|
return name.toLowerCase().trim();
|
|
2725
2855
|
}
|
|
2726
2856
|
function parseCardSide(token) {
|
|
2727
|
-
|
|
2857
|
+
if (token === "1" || token === "*" || token === "?") return token;
|
|
2858
|
+
return null;
|
|
2728
2859
|
}
|
|
2729
|
-
function parseRelationship(trimmed) {
|
|
2860
|
+
function parseRelationship(trimmed, lineNumber, pushError) {
|
|
2730
2861
|
const sym = trimmed.match(REL_SYMBOLIC_RE);
|
|
2731
2862
|
if (sym) {
|
|
2732
2863
|
const fromCard = parseCardSide(sym[2]);
|
|
@@ -2743,17 +2874,13 @@ function parseRelationship(trimmed) {
|
|
|
2743
2874
|
}
|
|
2744
2875
|
const kw = trimmed.match(REL_KEYWORD_RE2);
|
|
2745
2876
|
if (kw) {
|
|
2746
|
-
const
|
|
2747
|
-
const
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
to: toCard,
|
|
2754
|
-
label: kw[5]?.trim()
|
|
2755
|
-
};
|
|
2756
|
-
}
|
|
2877
|
+
const fromSym = KEYWORD_TO_SYMBOL[kw[2].toLowerCase()] ?? kw[2];
|
|
2878
|
+
const toSym = KEYWORD_TO_SYMBOL[kw[3].toLowerCase()] ?? kw[3];
|
|
2879
|
+
pushError(
|
|
2880
|
+
lineNumber,
|
|
2881
|
+
`Use symbolic cardinality (1--*, ?--1, *--*) instead of "${kw[2]}-to-${kw[3]}". Example: ${kw[1]} ${fromSym}--${toSym} ${kw[4]}`
|
|
2882
|
+
);
|
|
2883
|
+
return null;
|
|
2757
2884
|
}
|
|
2758
2885
|
return null;
|
|
2759
2886
|
}
|
|
@@ -2773,7 +2900,8 @@ function parseERDiagram(content, palette) {
|
|
|
2773
2900
|
options: {},
|
|
2774
2901
|
tables: [],
|
|
2775
2902
|
relationships: [],
|
|
2776
|
-
diagnostics: []
|
|
2903
|
+
diagnostics: [],
|
|
2904
|
+
error: null
|
|
2777
2905
|
};
|
|
2778
2906
|
const fail = (line7, message) => {
|
|
2779
2907
|
const diag = makeDgmoError(line7, message);
|
|
@@ -2781,6 +2909,11 @@ function parseERDiagram(content, palette) {
|
|
|
2781
2909
|
result.error = formatDgmoError(diag);
|
|
2782
2910
|
return result;
|
|
2783
2911
|
};
|
|
2912
|
+
const pushError = (line7, message) => {
|
|
2913
|
+
const diag = makeDgmoError(line7, message);
|
|
2914
|
+
result.diagnostics.push(diag);
|
|
2915
|
+
if (!result.error) result.error = formatDgmoError(diag);
|
|
2916
|
+
};
|
|
2784
2917
|
const tableMap = /* @__PURE__ */ new Map();
|
|
2785
2918
|
let currentTable = null;
|
|
2786
2919
|
let contentStarted = false;
|
|
@@ -2802,7 +2935,7 @@ function parseERDiagram(content, palette) {
|
|
|
2802
2935
|
const raw = lines[i];
|
|
2803
2936
|
const trimmed = raw.trim();
|
|
2804
2937
|
const lineNumber = i + 1;
|
|
2805
|
-
const indent =
|
|
2938
|
+
const indent = measureIndent(raw);
|
|
2806
2939
|
if (!trimmed) {
|
|
2807
2940
|
if (indent === 0) currentTable = null;
|
|
2808
2941
|
continue;
|
|
@@ -2851,7 +2984,7 @@ function parseERDiagram(content, palette) {
|
|
|
2851
2984
|
}
|
|
2852
2985
|
currentTable = null;
|
|
2853
2986
|
contentStarted = true;
|
|
2854
|
-
const rel = parseRelationship(trimmed);
|
|
2987
|
+
const rel = parseRelationship(trimmed, lineNumber, pushError);
|
|
2855
2988
|
if (rel) {
|
|
2856
2989
|
getOrCreateTable(rel.source, lineNumber);
|
|
2857
2990
|
getOrCreateTable(rel.target, lineNumber);
|
|
@@ -2904,7 +3037,7 @@ function looksLikeERDiagram(content) {
|
|
|
2904
3037
|
const trimmed = line7.trim();
|
|
2905
3038
|
if (!trimmed || trimmed.startsWith("//")) continue;
|
|
2906
3039
|
if (/^(chart|title|notation)\s*:/i.test(trimmed)) continue;
|
|
2907
|
-
const indent =
|
|
3040
|
+
const indent = measureIndent(line7);
|
|
2908
3041
|
if (indent > 0) {
|
|
2909
3042
|
if (/\[(pk|fk)\]/i.test(trimmed)) {
|
|
2910
3043
|
hasConstraint = true;
|
|
@@ -2913,7 +3046,7 @@ function looksLikeERDiagram(content) {
|
|
|
2913
3046
|
if (TABLE_DECL_RE.test(trimmed)) {
|
|
2914
3047
|
hasTableDecl = true;
|
|
2915
3048
|
}
|
|
2916
|
-
if (REL_SYMBOLIC_RE.test(trimmed)
|
|
3049
|
+
if (REL_SYMBOLIC_RE.test(trimmed)) {
|
|
2917
3050
|
hasRelationship = true;
|
|
2918
3051
|
}
|
|
2919
3052
|
}
|
|
@@ -2922,12 +3055,13 @@ function looksLikeERDiagram(content) {
|
|
|
2922
3055
|
if (hasRelationship && hasTableDecl && hasConstraint) return true;
|
|
2923
3056
|
return false;
|
|
2924
3057
|
}
|
|
2925
|
-
var TABLE_DECL_RE, COLUMN_RE, CONSTRAINT_MAP,
|
|
3058
|
+
var TABLE_DECL_RE, COLUMN_RE, CONSTRAINT_MAP, REL_SYMBOLIC_RE, REL_KEYWORD_RE2, KEYWORD_TO_SYMBOL;
|
|
2926
3059
|
var init_parser3 = __esm({
|
|
2927
3060
|
"src/er/parser.ts"() {
|
|
2928
3061
|
"use strict";
|
|
2929
3062
|
init_colors();
|
|
2930
3063
|
init_diagnostics();
|
|
3064
|
+
init_parsing();
|
|
2931
3065
|
TABLE_DECL_RE = /^([a-zA-Z_]\w*)(?:\s+\(([^)]+)\))?\s*$/;
|
|
2932
3066
|
COLUMN_RE = /^(\w+)(?:\s*:\s*(\w[\w()]*(?:\s*\[\])?))?(?:\s+\[([^\]]+)\])?\s*$/;
|
|
2933
3067
|
CONSTRAINT_MAP = {
|
|
@@ -2936,16 +3070,13 @@ var init_parser3 = __esm({
|
|
|
2936
3070
|
unique: "unique",
|
|
2937
3071
|
nullable: "nullable"
|
|
2938
3072
|
};
|
|
2939
|
-
|
|
3073
|
+
REL_SYMBOLIC_RE = /^([a-zA-Z_]\w*)\s+([1*?])\s*-{1,2}\s*([1*?])\s+([a-zA-Z_]\w*)(?:\s*:\s*(.+))?$/;
|
|
3074
|
+
REL_KEYWORD_RE2 = /^([a-zA-Z_]\w*)\s+(one|many|zero)[- ]to[- ](one|many|zero)\s+([a-zA-Z_]\w*)(?:\s*:\s*(.+))?$/i;
|
|
3075
|
+
KEYWORD_TO_SYMBOL = {
|
|
2940
3076
|
one: "1",
|
|
2941
3077
|
many: "*",
|
|
2942
|
-
"1": "1",
|
|
2943
|
-
"*": "*",
|
|
2944
|
-
"?": "?",
|
|
2945
3078
|
zero: "?"
|
|
2946
3079
|
};
|
|
2947
|
-
REL_SYMBOLIC_RE = /^([a-zA-Z_]\w*)\s+([1*?])\s*-{1,2}\s*([1*?])\s+([a-zA-Z_]\w*)(?:\s*:\s*(.+))?$/;
|
|
2948
|
-
REL_KEYWORD_RE2 = /^([a-zA-Z_]\w*)\s+(one|many|zero|1|\*|\?)[- ]to[- ](one|many|zero|1|\*|\?)\s+([a-zA-Z_]\w*)(?:\s*:\s*(.+))?$/i;
|
|
2949
3080
|
}
|
|
2950
3081
|
});
|
|
2951
3082
|
|
|
@@ -2955,7 +3086,8 @@ function parseChart(content, palette) {
|
|
|
2955
3086
|
const result = {
|
|
2956
3087
|
type: "bar",
|
|
2957
3088
|
data: [],
|
|
2958
|
-
diagnostics: []
|
|
3089
|
+
diagnostics: [],
|
|
3090
|
+
error: null
|
|
2959
3091
|
};
|
|
2960
3092
|
const fail = (line7, message) => {
|
|
2961
3093
|
const diag = makeDgmoError(line7, message);
|
|
@@ -2968,7 +3100,7 @@ function parseChart(content, palette) {
|
|
|
2968
3100
|
const lineNumber = i + 1;
|
|
2969
3101
|
if (!trimmed) continue;
|
|
2970
3102
|
if (/^#{2,}\s+/.test(trimmed)) continue;
|
|
2971
|
-
if (trimmed.startsWith("
|
|
3103
|
+
if (trimmed.startsWith("//")) continue;
|
|
2972
3104
|
const colonIndex = trimmed.indexOf(":");
|
|
2973
3105
|
if (colonIndex === -1) continue;
|
|
2974
3106
|
const key = trimmed.substring(0, colonIndex).trim().toLowerCase();
|
|
@@ -3126,7 +3258,8 @@ function parseEChart(content, palette) {
|
|
|
3126
3258
|
const result = {
|
|
3127
3259
|
type: "scatter",
|
|
3128
3260
|
data: [],
|
|
3129
|
-
diagnostics: []
|
|
3261
|
+
diagnostics: [],
|
|
3262
|
+
error: null
|
|
3130
3263
|
};
|
|
3131
3264
|
let currentCategory = "Default";
|
|
3132
3265
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -3146,7 +3279,7 @@ function parseEChart(content, palette) {
|
|
|
3146
3279
|
currentCategory = catName;
|
|
3147
3280
|
continue;
|
|
3148
3281
|
}
|
|
3149
|
-
if (trimmed.startsWith("
|
|
3282
|
+
if (trimmed.startsWith("//")) continue;
|
|
3150
3283
|
const categoryMatch = trimmed.match(/^\[(.+)\]$/);
|
|
3151
3284
|
if (categoryMatch) {
|
|
3152
3285
|
currentCategory = categoryMatch[1].trim();
|
|
@@ -3775,7 +3908,7 @@ function buildScatterOption(parsed, palette, textColor, axisLineColor, gridOpaci
|
|
|
3775
3908
|
}
|
|
3776
3909
|
},
|
|
3777
3910
|
grid: {
|
|
3778
|
-
left: parsed.ylabel ? "
|
|
3911
|
+
left: parsed.ylabel ? "12%" : "3%",
|
|
3779
3912
|
right: "4%",
|
|
3780
3913
|
bottom: hasCategories ? "15%" : parsed.xlabel ? "10%" : "3%",
|
|
3781
3914
|
top: parsed.title ? "15%" : "5%",
|
|
@@ -4047,17 +4180,26 @@ function resolveAxisLabels(parsed) {
|
|
|
4047
4180
|
yLabel: parsed.ylabel ?? (isHorizontal ? void 0 : parsed.label)
|
|
4048
4181
|
};
|
|
4049
4182
|
}
|
|
4050
|
-
function makeGridAxis(type, textColor, axisLineColor, splitLineColor, gridOpacity, label, data) {
|
|
4183
|
+
function makeGridAxis(type, textColor, axisLineColor, splitLineColor, gridOpacity, label, data, nameGapOverride) {
|
|
4184
|
+
const defaultGap = type === "value" ? 75 : 40;
|
|
4051
4185
|
return {
|
|
4052
4186
|
type,
|
|
4053
4187
|
...data && { data },
|
|
4054
4188
|
axisLine: { lineStyle: { color: axisLineColor } },
|
|
4055
|
-
axisLabel: {
|
|
4189
|
+
axisLabel: {
|
|
4190
|
+
color: textColor,
|
|
4191
|
+
fontSize: type === "category" && data ? data.length > 10 ? 11 : data.length > 5 ? 12 : 16 : 16,
|
|
4192
|
+
fontFamily: FONT_FAMILY,
|
|
4193
|
+
...type === "category" && {
|
|
4194
|
+
interval: 0,
|
|
4195
|
+
formatter: (value) => value.replace(/([a-z])([A-Z])/g, "$1\n$2").replace(/ /g, "\n")
|
|
4196
|
+
}
|
|
4197
|
+
},
|
|
4056
4198
|
splitLine: { lineStyle: { color: splitLineColor, opacity: gridOpacity } },
|
|
4057
4199
|
...label && {
|
|
4058
4200
|
name: label,
|
|
4059
4201
|
nameLocation: "middle",
|
|
4060
|
-
nameGap:
|
|
4202
|
+
nameGap: nameGapOverride ?? defaultGap,
|
|
4061
4203
|
nameTextStyle: { color: textColor, fontSize: 18, fontFamily: FONT_FAMILY }
|
|
4062
4204
|
}
|
|
4063
4205
|
};
|
|
@@ -4112,7 +4254,8 @@ function buildBarOption(parsed, textColor, axisLineColor, splitLineColor, gridOp
|
|
|
4112
4254
|
value: d.value,
|
|
4113
4255
|
itemStyle: { color: d.color ?? colors[i % colors.length] }
|
|
4114
4256
|
}));
|
|
4115
|
-
const
|
|
4257
|
+
const hCatGap = isHorizontal && yLabel ? Math.max(40, Math.max(...labels.map((l) => l.length)) * 8 + 16) : void 0;
|
|
4258
|
+
const categoryAxis = makeGridAxis("category", textColor, axisLineColor, splitLineColor, gridOpacity, isHorizontal ? yLabel : xLabel, labels, hCatGap);
|
|
4116
4259
|
const valueAxis = makeGridAxis("value", textColor, axisLineColor, splitLineColor, gridOpacity, isHorizontal ? xLabel : yLabel);
|
|
4117
4260
|
return {
|
|
4118
4261
|
backgroundColor: "transparent",
|
|
@@ -4124,7 +4267,7 @@ function buildBarOption(parsed, textColor, axisLineColor, splitLineColor, gridOp
|
|
|
4124
4267
|
axisPointer: { type: "shadow" }
|
|
4125
4268
|
},
|
|
4126
4269
|
grid: {
|
|
4127
|
-
left: yLabel ? "
|
|
4270
|
+
left: yLabel ? "12%" : "3%",
|
|
4128
4271
|
right: "4%",
|
|
4129
4272
|
bottom: xLabel ? "10%" : "3%",
|
|
4130
4273
|
top: parsed.title ? "15%" : "5%",
|
|
@@ -4159,7 +4302,7 @@ function buildLineOption(parsed, palette, textColor, axisLineColor, splitLineCol
|
|
|
4159
4302
|
axisPointer: { type: "line" }
|
|
4160
4303
|
},
|
|
4161
4304
|
grid: {
|
|
4162
|
-
left: yLabel ? "
|
|
4305
|
+
left: yLabel ? "12%" : "3%",
|
|
4163
4306
|
right: "4%",
|
|
4164
4307
|
bottom: xLabel ? "10%" : "3%",
|
|
4165
4308
|
top: parsed.title ? "15%" : "5%",
|
|
@@ -4221,7 +4364,7 @@ function buildMultiLineOption(parsed, textColor, axisLineColor, splitLineColor,
|
|
|
4221
4364
|
textStyle: { color: textColor }
|
|
4222
4365
|
},
|
|
4223
4366
|
grid: {
|
|
4224
|
-
left: yLabel ? "
|
|
4367
|
+
left: yLabel ? "12%" : "3%",
|
|
4225
4368
|
right: "4%",
|
|
4226
4369
|
bottom: "15%",
|
|
4227
4370
|
top: parsed.title ? "15%" : "5%",
|
|
@@ -4247,7 +4390,7 @@ function buildAreaOption(parsed, palette, textColor, axisLineColor, splitLineCol
|
|
|
4247
4390
|
axisPointer: { type: "line" }
|
|
4248
4391
|
},
|
|
4249
4392
|
grid: {
|
|
4250
|
-
left: yLabel ? "
|
|
4393
|
+
left: yLabel ? "12%" : "3%",
|
|
4251
4394
|
right: "4%",
|
|
4252
4395
|
bottom: xLabel ? "10%" : "3%",
|
|
4253
4396
|
top: parsed.title ? "15%" : "5%",
|
|
@@ -4444,7 +4587,8 @@ function buildBarStackedOption(parsed, textColor, axisLineColor, splitLineColor,
|
|
|
4444
4587
|
}
|
|
4445
4588
|
};
|
|
4446
4589
|
});
|
|
4447
|
-
const
|
|
4590
|
+
const hCatGap = isHorizontal && yLabel ? Math.max(40, Math.max(...labels.map((l) => l.length)) * 8 + 16) : void 0;
|
|
4591
|
+
const categoryAxis = makeGridAxis("category", textColor, axisLineColor, splitLineColor, gridOpacity, isHorizontal ? yLabel : xLabel, labels, hCatGap);
|
|
4448
4592
|
const valueAxis = makeGridAxis("value", textColor, axisLineColor, splitLineColor, gridOpacity, isHorizontal ? xLabel : yLabel);
|
|
4449
4593
|
return {
|
|
4450
4594
|
backgroundColor: "transparent",
|
|
@@ -4461,7 +4605,7 @@ function buildBarStackedOption(parsed, textColor, axisLineColor, splitLineColor,
|
|
|
4461
4605
|
textStyle: { color: textColor }
|
|
4462
4606
|
},
|
|
4463
4607
|
grid: {
|
|
4464
|
-
left: yLabel ? "
|
|
4608
|
+
left: yLabel ? "12%" : "3%",
|
|
4465
4609
|
right: "4%",
|
|
4466
4610
|
bottom: "15%",
|
|
4467
4611
|
top: parsed.title ? "15%" : "5%",
|
|
@@ -4540,35 +4684,51 @@ var init_echarts = __esm({
|
|
|
4540
4684
|
}
|
|
4541
4685
|
});
|
|
4542
4686
|
|
|
4687
|
+
// src/utils/tag-groups.ts
|
|
4688
|
+
function isTagBlockHeading(trimmed) {
|
|
4689
|
+
return TAG_BLOCK_RE.test(trimmed) || GROUP_HEADING_RE2.test(trimmed);
|
|
4690
|
+
}
|
|
4691
|
+
function matchTagBlockHeading(trimmed) {
|
|
4692
|
+
const tagMatch = trimmed.match(TAG_BLOCK_RE);
|
|
4693
|
+
if (tagMatch) {
|
|
4694
|
+
return {
|
|
4695
|
+
name: tagMatch[1].trim(),
|
|
4696
|
+
alias: tagMatch[2] || void 0,
|
|
4697
|
+
colorHint: tagMatch[3] || void 0,
|
|
4698
|
+
deprecated: false
|
|
4699
|
+
};
|
|
4700
|
+
}
|
|
4701
|
+
const groupMatch = trimmed.match(GROUP_HEADING_RE2);
|
|
4702
|
+
if (groupMatch) {
|
|
4703
|
+
return {
|
|
4704
|
+
name: groupMatch[1].trim(),
|
|
4705
|
+
alias: groupMatch[2] || void 0,
|
|
4706
|
+
colorHint: groupMatch[3] || void 0,
|
|
4707
|
+
deprecated: true
|
|
4708
|
+
};
|
|
4709
|
+
}
|
|
4710
|
+
return null;
|
|
4711
|
+
}
|
|
4712
|
+
var TAG_BLOCK_RE, GROUP_HEADING_RE2;
|
|
4713
|
+
var init_tag_groups = __esm({
|
|
4714
|
+
"src/utils/tag-groups.ts"() {
|
|
4715
|
+
"use strict";
|
|
4716
|
+
TAG_BLOCK_RE = /^tag:\s+(.+?)(?:\s+alias\s+(\w+))?(?:\s*\(([^)]+)\))?\s*$/i;
|
|
4717
|
+
GROUP_HEADING_RE2 = /^##\s+(.+?)(?:\s+alias\s+(\w+))?(?:\s*\(([^)]+)\))?\s*$/;
|
|
4718
|
+
}
|
|
4719
|
+
});
|
|
4720
|
+
|
|
4543
4721
|
// src/org/parser.ts
|
|
4544
4722
|
var parser_exports4 = {};
|
|
4545
4723
|
__export(parser_exports4, {
|
|
4546
4724
|
looksLikeOrg: () => looksLikeOrg,
|
|
4547
4725
|
parseOrg: () => parseOrg
|
|
4548
4726
|
});
|
|
4549
|
-
function measureIndent5(line7) {
|
|
4550
|
-
let indent = 0;
|
|
4551
|
-
for (const ch of line7) {
|
|
4552
|
-
if (ch === " ") indent++;
|
|
4553
|
-
else if (ch === " ") indent += 4;
|
|
4554
|
-
else break;
|
|
4555
|
-
}
|
|
4556
|
-
return indent;
|
|
4557
|
-
}
|
|
4558
|
-
function extractColor2(label, palette) {
|
|
4559
|
-
const m = label.match(COLOR_SUFFIX_RE2);
|
|
4560
|
-
if (!m) return { label };
|
|
4561
|
-
const colorName = m[1].trim();
|
|
4562
|
-
return {
|
|
4563
|
-
label: label.substring(0, m.index).trim(),
|
|
4564
|
-
color: resolveColor(colorName, palette)
|
|
4565
|
-
};
|
|
4566
|
-
}
|
|
4567
4727
|
function looksLikeOrg(content) {
|
|
4568
4728
|
for (const line7 of content.split("\n")) {
|
|
4569
4729
|
const trimmed = line7.trim();
|
|
4570
4730
|
if (!trimmed || trimmed.startsWith("//")) continue;
|
|
4571
|
-
if (
|
|
4731
|
+
if (isTagBlockHeading(trimmed)) return true;
|
|
4572
4732
|
}
|
|
4573
4733
|
return false;
|
|
4574
4734
|
}
|
|
@@ -4593,6 +4753,9 @@ function parseOrg(content, palette) {
|
|
|
4593
4753
|
result.diagnostics.push(diag);
|
|
4594
4754
|
if (!result.error) result.error = formatDgmoError(diag);
|
|
4595
4755
|
};
|
|
4756
|
+
const pushWarning = (line7, message) => {
|
|
4757
|
+
result.diagnostics.push(makeDgmoError(line7, message, "warning"));
|
|
4758
|
+
};
|
|
4596
4759
|
if (!content || !content.trim()) {
|
|
4597
4760
|
return fail(0, "No content provided");
|
|
4598
4761
|
}
|
|
@@ -4636,42 +4799,43 @@ function parseOrg(content, palette) {
|
|
|
4636
4799
|
continue;
|
|
4637
4800
|
}
|
|
4638
4801
|
}
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
if (optMatch && !trimmed.startsWith("##")) {
|
|
4642
|
-
const key = optMatch[1].trim().toLowerCase();
|
|
4643
|
-
if (key !== "chart" && key !== "title") {
|
|
4644
|
-
result.options[key] = optMatch[2].trim();
|
|
4645
|
-
continue;
|
|
4646
|
-
}
|
|
4647
|
-
}
|
|
4648
|
-
}
|
|
4649
|
-
const groupMatch = trimmed.match(GROUP_HEADING_RE2);
|
|
4650
|
-
if (groupMatch) {
|
|
4802
|
+
const tagBlockMatch = matchTagBlockHeading(trimmed);
|
|
4803
|
+
if (tagBlockMatch) {
|
|
4651
4804
|
if (contentStarted) {
|
|
4652
|
-
pushError(lineNumber, "Tag groups
|
|
4805
|
+
pushError(lineNumber, "Tag groups must appear before org content");
|
|
4653
4806
|
continue;
|
|
4654
4807
|
}
|
|
4655
|
-
|
|
4656
|
-
|
|
4808
|
+
if (tagBlockMatch.deprecated) {
|
|
4809
|
+
pushWarning(lineNumber, `'## ${tagBlockMatch.name}' is deprecated for tag groups \u2014 use 'tag: ${tagBlockMatch.name}' instead`);
|
|
4810
|
+
}
|
|
4657
4811
|
currentTagGroup = {
|
|
4658
|
-
name:
|
|
4659
|
-
alias,
|
|
4812
|
+
name: tagBlockMatch.name,
|
|
4813
|
+
alias: tagBlockMatch.alias,
|
|
4660
4814
|
entries: [],
|
|
4661
4815
|
lineNumber
|
|
4662
4816
|
};
|
|
4663
|
-
if (alias) {
|
|
4664
|
-
aliasMap.set(alias.toLowerCase(),
|
|
4817
|
+
if (tagBlockMatch.alias) {
|
|
4818
|
+
aliasMap.set(tagBlockMatch.alias.toLowerCase(), tagBlockMatch.name.toLowerCase());
|
|
4665
4819
|
}
|
|
4666
4820
|
result.tagGroups.push(currentTagGroup);
|
|
4667
4821
|
continue;
|
|
4668
4822
|
}
|
|
4823
|
+
if (!contentStarted && !currentTagGroup && measureIndent(line7) === 0) {
|
|
4824
|
+
const optMatch = trimmed.match(OPTION_RE);
|
|
4825
|
+
if (optMatch) {
|
|
4826
|
+
const key = optMatch[1].trim().toLowerCase();
|
|
4827
|
+
if (key !== "chart" && key !== "title") {
|
|
4828
|
+
result.options[key] = optMatch[2].trim();
|
|
4829
|
+
continue;
|
|
4830
|
+
}
|
|
4831
|
+
}
|
|
4832
|
+
}
|
|
4669
4833
|
if (currentTagGroup && !contentStarted) {
|
|
4670
|
-
const indent2 =
|
|
4834
|
+
const indent2 = measureIndent(line7);
|
|
4671
4835
|
if (indent2 > 0) {
|
|
4672
4836
|
const isDefault = /\bdefault\s*$/.test(trimmed);
|
|
4673
4837
|
const entryText = isDefault ? trimmed.replace(/\s+default\s*$/, "").trim() : trimmed;
|
|
4674
|
-
const { label, color } =
|
|
4838
|
+
const { label, color } = extractColor(entryText, palette);
|
|
4675
4839
|
if (!color) {
|
|
4676
4840
|
pushError(lineNumber, `Expected 'Value(color)' in tag group '${currentTagGroup.name}'`);
|
|
4677
4841
|
continue;
|
|
@@ -4690,12 +4854,12 @@ function parseOrg(content, palette) {
|
|
|
4690
4854
|
}
|
|
4691
4855
|
contentStarted = true;
|
|
4692
4856
|
currentTagGroup = null;
|
|
4693
|
-
const indent =
|
|
4857
|
+
const indent = measureIndent(line7);
|
|
4694
4858
|
const containerMatch = trimmed.match(CONTAINER_RE);
|
|
4695
4859
|
const metadataMatch = trimmed.includes("|") ? null : trimmed.match(METADATA_RE);
|
|
4696
4860
|
if (containerMatch) {
|
|
4697
4861
|
const rawLabel = containerMatch[1].trim();
|
|
4698
|
-
const { label, color } =
|
|
4862
|
+
const { label, color } = extractColor(rawLabel, palette);
|
|
4699
4863
|
containerCounter++;
|
|
4700
4864
|
const node = {
|
|
4701
4865
|
id: `container-${containerCounter}`,
|
|
@@ -4740,24 +4904,8 @@ function parseOrg(content, palette) {
|
|
|
4740
4904
|
function parseNodeLabel(trimmed, _indent, lineNumber, palette, counter, aliasMap = /* @__PURE__ */ new Map()) {
|
|
4741
4905
|
const segments = trimmed.split("|").map((s) => s.trim());
|
|
4742
4906
|
let rawLabel = segments[0];
|
|
4743
|
-
const { label, color } =
|
|
4744
|
-
const metadata =
|
|
4745
|
-
const metaParts = [];
|
|
4746
|
-
for (let j = 1; j < segments.length; j++) {
|
|
4747
|
-
for (const part of segments[j].split(",")) {
|
|
4748
|
-
const trimmedPart = part.trim();
|
|
4749
|
-
if (trimmedPart) metaParts.push(trimmedPart);
|
|
4750
|
-
}
|
|
4751
|
-
}
|
|
4752
|
-
for (const part of metaParts) {
|
|
4753
|
-
const colonIdx = part.indexOf(":");
|
|
4754
|
-
if (colonIdx > 0) {
|
|
4755
|
-
const rawKey = part.substring(0, colonIdx).trim().toLowerCase();
|
|
4756
|
-
const key = aliasMap.get(rawKey) ?? rawKey;
|
|
4757
|
-
const value = part.substring(colonIdx + 1).trim();
|
|
4758
|
-
metadata[key] = value;
|
|
4759
|
-
}
|
|
4760
|
-
}
|
|
4907
|
+
const { label, color } = extractColor(rawLabel, palette);
|
|
4908
|
+
const metadata = parsePipeMetadata(segments, aliasMap);
|
|
4761
4909
|
return {
|
|
4762
4910
|
id: `node-${counter}`,
|
|
4763
4911
|
label,
|
|
@@ -4795,19 +4943,15 @@ function findMetadataParent(indent, indentStack) {
|
|
|
4795
4943
|
}
|
|
4796
4944
|
return null;
|
|
4797
4945
|
}
|
|
4798
|
-
var
|
|
4946
|
+
var CONTAINER_RE, METADATA_RE;
|
|
4799
4947
|
var init_parser4 = __esm({
|
|
4800
4948
|
"src/org/parser.ts"() {
|
|
4801
4949
|
"use strict";
|
|
4802
|
-
init_colors();
|
|
4803
4950
|
init_diagnostics();
|
|
4804
|
-
|
|
4805
|
-
|
|
4951
|
+
init_tag_groups();
|
|
4952
|
+
init_parsing();
|
|
4806
4953
|
CONTAINER_RE = /^\[([^\]]+)\]$/;
|
|
4807
4954
|
METADATA_RE = /^([^:]+):\s*(.+)$/;
|
|
4808
|
-
CHART_TYPE_RE = /^chart\s*:\s*(.+)/i;
|
|
4809
|
-
TITLE_RE = /^title\s*:\s*(.+)/i;
|
|
4810
|
-
OPTION_RE = /^([a-z][a-z0-9-]*)\s*:\s*(.+)$/i;
|
|
4811
4955
|
}
|
|
4812
4956
|
});
|
|
4813
4957
|
|
|
@@ -4816,31 +4960,14 @@ var parser_exports5 = {};
|
|
|
4816
4960
|
__export(parser_exports5, {
|
|
4817
4961
|
parseKanban: () => parseKanban
|
|
4818
4962
|
});
|
|
4819
|
-
function measureIndent6(line7) {
|
|
4820
|
-
let indent = 0;
|
|
4821
|
-
for (const ch of line7) {
|
|
4822
|
-
if (ch === " ") indent++;
|
|
4823
|
-
else if (ch === " ") indent += 4;
|
|
4824
|
-
else break;
|
|
4825
|
-
}
|
|
4826
|
-
return indent;
|
|
4827
|
-
}
|
|
4828
|
-
function extractColor3(label, palette) {
|
|
4829
|
-
const m = label.match(COLOR_SUFFIX_RE3);
|
|
4830
|
-
if (!m) return { label };
|
|
4831
|
-
const colorName = m[1].trim();
|
|
4832
|
-
return {
|
|
4833
|
-
label: label.substring(0, m.index).trim(),
|
|
4834
|
-
color: resolveColor(colorName, palette)
|
|
4835
|
-
};
|
|
4836
|
-
}
|
|
4837
4963
|
function parseKanban(content, palette) {
|
|
4838
4964
|
const result = {
|
|
4839
4965
|
type: "kanban",
|
|
4840
4966
|
columns: [],
|
|
4841
4967
|
tagGroups: [],
|
|
4842
4968
|
options: {},
|
|
4843
|
-
diagnostics: []
|
|
4969
|
+
diagnostics: [],
|
|
4970
|
+
error: null
|
|
4844
4971
|
};
|
|
4845
4972
|
const fail = (line7, message) => {
|
|
4846
4973
|
const diag = makeDgmoError(line7, message);
|
|
@@ -4873,7 +5000,7 @@ function parseKanban(content, palette) {
|
|
|
4873
5000
|
}
|
|
4874
5001
|
if (trimmed.startsWith("//")) continue;
|
|
4875
5002
|
if (!contentStarted && !currentTagGroup) {
|
|
4876
|
-
const chartMatch = trimmed.match(
|
|
5003
|
+
const chartMatch = trimmed.match(CHART_TYPE_RE);
|
|
4877
5004
|
if (chartMatch) {
|
|
4878
5005
|
const chartType = chartMatch[1].trim().toLowerCase();
|
|
4879
5006
|
if (chartType !== "kanban") {
|
|
@@ -4897,16 +5024,35 @@ function parseKanban(content, palette) {
|
|
|
4897
5024
|
}
|
|
4898
5025
|
}
|
|
4899
5026
|
if (!contentStarted && !currentTagGroup) {
|
|
4900
|
-
const titleMatch = trimmed.match(
|
|
5027
|
+
const titleMatch = trimmed.match(TITLE_RE);
|
|
4901
5028
|
if (titleMatch) {
|
|
4902
5029
|
result.title = titleMatch[1].trim();
|
|
4903
5030
|
result.titleLineNumber = lineNumber;
|
|
4904
5031
|
continue;
|
|
4905
5032
|
}
|
|
4906
5033
|
}
|
|
4907
|
-
if (!contentStarted
|
|
4908
|
-
const
|
|
4909
|
-
if (
|
|
5034
|
+
if (!contentStarted) {
|
|
5035
|
+
const tagBlockMatch = matchTagBlockHeading(trimmed);
|
|
5036
|
+
if (tagBlockMatch) {
|
|
5037
|
+
if (tagBlockMatch.deprecated) {
|
|
5038
|
+
warn(lineNumber, `'## ${tagBlockMatch.name}' is deprecated for tag groups \u2014 use 'tag: ${tagBlockMatch.name}' instead`);
|
|
5039
|
+
}
|
|
5040
|
+
currentTagGroup = {
|
|
5041
|
+
name: tagBlockMatch.name,
|
|
5042
|
+
alias: tagBlockMatch.alias,
|
|
5043
|
+
entries: [],
|
|
5044
|
+
lineNumber
|
|
5045
|
+
};
|
|
5046
|
+
if (tagBlockMatch.alias) {
|
|
5047
|
+
aliasMap.set(tagBlockMatch.alias.toLowerCase(), tagBlockMatch.name.toLowerCase());
|
|
5048
|
+
}
|
|
5049
|
+
result.tagGroups.push(currentTagGroup);
|
|
5050
|
+
continue;
|
|
5051
|
+
}
|
|
5052
|
+
}
|
|
5053
|
+
if (!contentStarted && !currentTagGroup && measureIndent(line7) === 0) {
|
|
5054
|
+
const optMatch = trimmed.match(OPTION_RE);
|
|
5055
|
+
if (optMatch && !COLUMN_RE2.test(trimmed)) {
|
|
4910
5056
|
const key = optMatch[1].trim().toLowerCase();
|
|
4911
5057
|
if (key !== "chart" && key !== "title") {
|
|
4912
5058
|
result.options[key] = optMatch[2].trim();
|
|
@@ -4914,28 +5060,12 @@ function parseKanban(content, palette) {
|
|
|
4914
5060
|
}
|
|
4915
5061
|
}
|
|
4916
5062
|
}
|
|
4917
|
-
const groupMatch = trimmed.match(GROUP_HEADING_RE3);
|
|
4918
|
-
if (groupMatch && !contentStarted) {
|
|
4919
|
-
const groupName = groupMatch[1].trim();
|
|
4920
|
-
const alias = groupMatch[2] || void 0;
|
|
4921
|
-
currentTagGroup = {
|
|
4922
|
-
name: groupName,
|
|
4923
|
-
alias,
|
|
4924
|
-
entries: [],
|
|
4925
|
-
lineNumber
|
|
4926
|
-
};
|
|
4927
|
-
if (alias) {
|
|
4928
|
-
aliasMap.set(alias.toLowerCase(), groupName.toLowerCase());
|
|
4929
|
-
}
|
|
4930
|
-
result.tagGroups.push(currentTagGroup);
|
|
4931
|
-
continue;
|
|
4932
|
-
}
|
|
4933
5063
|
if (currentTagGroup && !contentStarted) {
|
|
4934
|
-
const indent2 =
|
|
5064
|
+
const indent2 = measureIndent(line7);
|
|
4935
5065
|
if (indent2 > 0) {
|
|
4936
5066
|
const isDefault = /\bdefault\s*$/.test(trimmed);
|
|
4937
5067
|
const entryText = isDefault ? trimmed.replace(/\s+default\s*$/, "").trim() : trimmed;
|
|
4938
|
-
const { label, color } =
|
|
5068
|
+
const { label, color } = extractColor(entryText, palette);
|
|
4939
5069
|
if (!color) {
|
|
4940
5070
|
warn(
|
|
4941
5071
|
lineNumber,
|
|
@@ -4969,7 +5099,7 @@ function parseKanban(content, palette) {
|
|
|
4969
5099
|
columnCounter++;
|
|
4970
5100
|
const rawColName = columnMatch[1].trim();
|
|
4971
5101
|
const wipStr = columnMatch[2];
|
|
4972
|
-
const { label: colName, color: colColor } =
|
|
5102
|
+
const { label: colName, color: colColor } = extractColor(
|
|
4973
5103
|
rawColName,
|
|
4974
5104
|
palette
|
|
4975
5105
|
);
|
|
@@ -4991,7 +5121,7 @@ function parseKanban(content, palette) {
|
|
|
4991
5121
|
warn(lineNumber, "Card line found before any column");
|
|
4992
5122
|
continue;
|
|
4993
5123
|
}
|
|
4994
|
-
const indent =
|
|
5124
|
+
const indent = measureIndent(line7);
|
|
4995
5125
|
if (indent > 0 && currentCard) {
|
|
4996
5126
|
currentCard.details.push(trimmed);
|
|
4997
5127
|
currentCard.endLineNumber = lineNumber;
|
|
@@ -5056,7 +5186,7 @@ function parseCardLine(trimmed, lineNumber, counter, aliasMap, palette) {
|
|
|
5056
5186
|
} else {
|
|
5057
5187
|
rawTitle = trimmed;
|
|
5058
5188
|
}
|
|
5059
|
-
const { label: title, color } =
|
|
5189
|
+
const { label: title, color } = extractColor(rawTitle, palette);
|
|
5060
5190
|
const tags = {};
|
|
5061
5191
|
if (tagsStr) {
|
|
5062
5192
|
for (const part of tagsStr.split(",")) {
|
|
@@ -5079,18 +5209,14 @@ function parseCardLine(trimmed, lineNumber, counter, aliasMap, palette) {
|
|
|
5079
5209
|
color
|
|
5080
5210
|
};
|
|
5081
5211
|
}
|
|
5082
|
-
var
|
|
5212
|
+
var COLUMN_RE2;
|
|
5083
5213
|
var init_parser5 = __esm({
|
|
5084
5214
|
"src/kanban/parser.ts"() {
|
|
5085
5215
|
"use strict";
|
|
5086
|
-
init_colors();
|
|
5087
5216
|
init_diagnostics();
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
OPTION_RE2 = /^([a-z][a-z0-9-]*)\s*:\s*(.+)$/i;
|
|
5091
|
-
GROUP_HEADING_RE3 = /^##\s+(.+?)(?:\s+alias\s+(\w+))?(?:\s*\(([^)]+)\))?\s*$/;
|
|
5217
|
+
init_tag_groups();
|
|
5218
|
+
init_parsing();
|
|
5092
5219
|
COLUMN_RE2 = /^==\s+(.+?)\s*(?:\[wip:\s*(\d+)\])?\s*==$/;
|
|
5093
|
-
COLOR_SUFFIX_RE3 = /\(([^)]+)\)\s*$/;
|
|
5094
5220
|
}
|
|
5095
5221
|
});
|
|
5096
5222
|
|
|
@@ -5099,24 +5225,6 @@ var parser_exports6 = {};
|
|
|
5099
5225
|
__export(parser_exports6, {
|
|
5100
5226
|
parseC4: () => parseC4
|
|
5101
5227
|
});
|
|
5102
|
-
function measureIndent7(line7) {
|
|
5103
|
-
let indent = 0;
|
|
5104
|
-
for (const ch of line7) {
|
|
5105
|
-
if (ch === " ") indent++;
|
|
5106
|
-
else if (ch === " ") indent += 4;
|
|
5107
|
-
else break;
|
|
5108
|
-
}
|
|
5109
|
-
return indent;
|
|
5110
|
-
}
|
|
5111
|
-
function extractColor4(label, palette) {
|
|
5112
|
-
const m = label.match(COLOR_SUFFIX_RE4);
|
|
5113
|
-
if (!m) return { label };
|
|
5114
|
-
const colorName = m[1].trim();
|
|
5115
|
-
return {
|
|
5116
|
-
label: label.substring(0, m.index).trim(),
|
|
5117
|
-
color: resolveColor(colorName, palette)
|
|
5118
|
-
};
|
|
5119
|
-
}
|
|
5120
5228
|
function participantTypeToC4Shape(pType) {
|
|
5121
5229
|
switch (pType) {
|
|
5122
5230
|
case "database":
|
|
@@ -5173,23 +5281,6 @@ function parseRelationshipBody(body) {
|
|
|
5173
5281
|
}
|
|
5174
5282
|
return { target, label: rest };
|
|
5175
5283
|
}
|
|
5176
|
-
function parsePipeMetadata(segments, aliasMap) {
|
|
5177
|
-
const metadata = {};
|
|
5178
|
-
for (let j = 1; j < segments.length; j++) {
|
|
5179
|
-
for (const part of segments[j].split(",")) {
|
|
5180
|
-
const trimmedPart = part.trim();
|
|
5181
|
-
if (!trimmedPart) continue;
|
|
5182
|
-
const colonIdx = trimmedPart.indexOf(":");
|
|
5183
|
-
if (colonIdx > 0) {
|
|
5184
|
-
const rawKey = trimmedPart.substring(0, colonIdx).trim().toLowerCase();
|
|
5185
|
-
const key = aliasMap.get(rawKey) ?? rawKey;
|
|
5186
|
-
const value = trimmedPart.substring(colonIdx + 1).trim();
|
|
5187
|
-
metadata[key] = value;
|
|
5188
|
-
}
|
|
5189
|
-
}
|
|
5190
|
-
}
|
|
5191
|
-
return metadata;
|
|
5192
|
-
}
|
|
5193
5284
|
function parseC4(content, palette) {
|
|
5194
5285
|
const result = {
|
|
5195
5286
|
title: null,
|
|
@@ -5235,7 +5326,7 @@ function parseC4(content, palette) {
|
|
|
5235
5326
|
}
|
|
5236
5327
|
if (trimmed.startsWith("//")) continue;
|
|
5237
5328
|
if (!contentStarted) {
|
|
5238
|
-
const chartMatch = trimmed.match(
|
|
5329
|
+
const chartMatch = trimmed.match(CHART_TYPE_RE);
|
|
5239
5330
|
if (chartMatch) {
|
|
5240
5331
|
const chartType = chartMatch[1].trim().toLowerCase();
|
|
5241
5332
|
if (chartType !== "c4") {
|
|
@@ -5249,49 +5340,50 @@ function parseC4(content, palette) {
|
|
|
5249
5340
|
}
|
|
5250
5341
|
}
|
|
5251
5342
|
if (!contentStarted) {
|
|
5252
|
-
const titleMatch = trimmed.match(
|
|
5343
|
+
const titleMatch = trimmed.match(TITLE_RE);
|
|
5253
5344
|
if (titleMatch) {
|
|
5254
5345
|
result.title = titleMatch[1].trim();
|
|
5255
5346
|
result.titleLineNumber = lineNumber;
|
|
5256
5347
|
continue;
|
|
5257
5348
|
}
|
|
5258
5349
|
}
|
|
5259
|
-
|
|
5260
|
-
|
|
5261
|
-
if (optMatch && !trimmed.startsWith("##")) {
|
|
5262
|
-
const key = optMatch[1].trim().toLowerCase();
|
|
5263
|
-
if (key !== "chart" && key !== "title") {
|
|
5264
|
-
result.options[key] = optMatch[2].trim();
|
|
5265
|
-
continue;
|
|
5266
|
-
}
|
|
5267
|
-
}
|
|
5268
|
-
}
|
|
5269
|
-
const groupMatch = trimmed.match(GROUP_HEADING_RE4);
|
|
5270
|
-
if (groupMatch) {
|
|
5350
|
+
const tagBlockMatch = matchTagBlockHeading(trimmed);
|
|
5351
|
+
if (tagBlockMatch) {
|
|
5271
5352
|
if (contentStarted) {
|
|
5272
|
-
pushError(lineNumber, "Tag groups
|
|
5353
|
+
pushError(lineNumber, "Tag groups must appear before content");
|
|
5273
5354
|
continue;
|
|
5274
5355
|
}
|
|
5275
|
-
|
|
5276
|
-
|
|
5356
|
+
if (tagBlockMatch.deprecated) {
|
|
5357
|
+
pushError(lineNumber, `'## ${tagBlockMatch.name}' is deprecated for tag groups \u2014 use 'tag: ${tagBlockMatch.name}' instead`, "warning");
|
|
5358
|
+
}
|
|
5277
5359
|
currentTagGroup = {
|
|
5278
|
-
name:
|
|
5279
|
-
alias,
|
|
5360
|
+
name: tagBlockMatch.name,
|
|
5361
|
+
alias: tagBlockMatch.alias,
|
|
5280
5362
|
entries: [],
|
|
5281
5363
|
lineNumber
|
|
5282
5364
|
};
|
|
5283
|
-
if (alias) {
|
|
5284
|
-
aliasMap.set(alias.toLowerCase(),
|
|
5365
|
+
if (tagBlockMatch.alias) {
|
|
5366
|
+
aliasMap.set(tagBlockMatch.alias.toLowerCase(), tagBlockMatch.name.toLowerCase());
|
|
5285
5367
|
}
|
|
5286
5368
|
result.tagGroups.push(currentTagGroup);
|
|
5287
5369
|
continue;
|
|
5288
5370
|
}
|
|
5371
|
+
if (!contentStarted && !currentTagGroup && measureIndent(line7) === 0) {
|
|
5372
|
+
const optMatch = trimmed.match(OPTION_RE);
|
|
5373
|
+
if (optMatch) {
|
|
5374
|
+
const key = optMatch[1].trim().toLowerCase();
|
|
5375
|
+
if (key !== "chart" && key !== "title") {
|
|
5376
|
+
result.options[key] = optMatch[2].trim();
|
|
5377
|
+
continue;
|
|
5378
|
+
}
|
|
5379
|
+
}
|
|
5380
|
+
}
|
|
5289
5381
|
if (currentTagGroup && !contentStarted) {
|
|
5290
|
-
const indent2 =
|
|
5382
|
+
const indent2 = measureIndent(line7);
|
|
5291
5383
|
if (indent2 > 0) {
|
|
5292
5384
|
const isDefault = /\bdefault\s*$/.test(trimmed);
|
|
5293
5385
|
const entryText = isDefault ? trimmed.replace(/\s+default\s*$/, "").trim() : trimmed;
|
|
5294
|
-
const { label, color } =
|
|
5386
|
+
const { label, color } = extractColor(entryText, palette);
|
|
5295
5387
|
if (!color) {
|
|
5296
5388
|
pushError(
|
|
5297
5389
|
lineNumber,
|
|
@@ -5316,7 +5408,7 @@ function parseC4(content, palette) {
|
|
|
5316
5408
|
if (!sawChartType) {
|
|
5317
5409
|
return fail(lineNumber, 'Missing "chart: c4" header');
|
|
5318
5410
|
}
|
|
5319
|
-
const indent =
|
|
5411
|
+
const indent = measureIndent(line7);
|
|
5320
5412
|
if (inDeployment) {
|
|
5321
5413
|
while (deployStack.length > 0) {
|
|
5322
5414
|
const top = deployStack[deployStack.length - 1];
|
|
@@ -5411,6 +5503,45 @@ function parseC4(content, palette) {
|
|
|
5411
5503
|
}
|
|
5412
5504
|
continue;
|
|
5413
5505
|
}
|
|
5506
|
+
{
|
|
5507
|
+
const labeledPatterns = [
|
|
5508
|
+
{ re: C4_LABELED_BIDI_SYNC_RE, arrowType: "bidirectional" },
|
|
5509
|
+
{ re: C4_LABELED_BIDI_ASYNC_RE, arrowType: "bidirectional-async" },
|
|
5510
|
+
{ re: C4_LABELED_SYNC_RE, arrowType: "sync" },
|
|
5511
|
+
{ re: C4_LABELED_ASYNC_RE, arrowType: "async" }
|
|
5512
|
+
];
|
|
5513
|
+
let labeledHandled = false;
|
|
5514
|
+
for (const { re, arrowType } of labeledPatterns) {
|
|
5515
|
+
const m = trimmed.match(re);
|
|
5516
|
+
if (!m) continue;
|
|
5517
|
+
const rawLabel = m[1].trim();
|
|
5518
|
+
const targetBody = m[2].trim();
|
|
5519
|
+
if (!rawLabel) break;
|
|
5520
|
+
let label = rawLabel;
|
|
5521
|
+
let technology;
|
|
5522
|
+
const techMatch = rawLabel.match(/\[([^\]]+)\]\s*$/);
|
|
5523
|
+
if (techMatch) {
|
|
5524
|
+
label = rawLabel.substring(0, techMatch.index).trim() || void 0;
|
|
5525
|
+
technology = techMatch[1].trim();
|
|
5526
|
+
}
|
|
5527
|
+
const rel = {
|
|
5528
|
+
target: targetBody,
|
|
5529
|
+
label,
|
|
5530
|
+
technology,
|
|
5531
|
+
arrowType,
|
|
5532
|
+
lineNumber
|
|
5533
|
+
};
|
|
5534
|
+
const parentEntry = findParentElement(indent, stack);
|
|
5535
|
+
if (parentEntry) {
|
|
5536
|
+
parentEntry.element.relationships.push(rel);
|
|
5537
|
+
} else {
|
|
5538
|
+
result.relationships.push(rel);
|
|
5539
|
+
}
|
|
5540
|
+
labeledHandled = true;
|
|
5541
|
+
break;
|
|
5542
|
+
}
|
|
5543
|
+
if (labeledHandled) continue;
|
|
5544
|
+
}
|
|
5414
5545
|
const relMatch = trimmed.match(RELATIONSHIP_RE);
|
|
5415
5546
|
if (relMatch) {
|
|
5416
5547
|
const arrowType = parseArrowType(relMatch[1]);
|
|
@@ -5600,22 +5731,22 @@ function validateDeploymentRefs(result, knownNames, pushWarning) {
|
|
|
5600
5731
|
}
|
|
5601
5732
|
walkDeploy(result.deployment);
|
|
5602
5733
|
}
|
|
5603
|
-
var
|
|
5734
|
+
var CONTAINER_RE2, ELEMENT_RE, IS_A_RE, RELATIONSHIP_RE, C4_LABELED_SYNC_RE, C4_LABELED_ASYNC_RE, C4_LABELED_BIDI_SYNC_RE, C4_LABELED_BIDI_ASYNC_RE, SECTION_HEADER_RE, CONTAINER_REF_RE, METADATA_RE2, VALID_ELEMENT_TYPES, VALID_SHAPES, ALL_CHART_TYPES;
|
|
5604
5735
|
var init_parser6 = __esm({
|
|
5605
5736
|
"src/c4/parser.ts"() {
|
|
5606
5737
|
"use strict";
|
|
5607
|
-
init_colors();
|
|
5608
5738
|
init_diagnostics();
|
|
5739
|
+
init_tag_groups();
|
|
5609
5740
|
init_participant_inference();
|
|
5610
|
-
|
|
5611
|
-
TITLE_RE3 = /^title\s*:\s*(.+)/i;
|
|
5612
|
-
OPTION_RE3 = /^([a-z][a-z0-9-]*)\s*:\s*(.+)$/i;
|
|
5613
|
-
GROUP_HEADING_RE4 = /^##\s+(.+?)(?:\s+alias\s+(\w+))?(?:\s*\(([^)]+)\))?\s*$/;
|
|
5614
|
-
COLOR_SUFFIX_RE4 = /\(([^)]+)\)\s*$/;
|
|
5741
|
+
init_parsing();
|
|
5615
5742
|
CONTAINER_RE2 = /^\[([^\]]+)\]$/;
|
|
5616
5743
|
ELEMENT_RE = /^(person|system|container|component)\s+(.+)$/i;
|
|
5617
5744
|
IS_A_RE = /\s+is\s+a(?:n)?\s+(\w+)\s*$/i;
|
|
5618
5745
|
RELATIONSHIP_RE = /^(<?-?>|<?~?>)\s+(.+)$/;
|
|
5746
|
+
C4_LABELED_SYNC_RE = /^-(.+)->\s+(.+)$/;
|
|
5747
|
+
C4_LABELED_ASYNC_RE = /^~(.+)~>\s+(.+)$/;
|
|
5748
|
+
C4_LABELED_BIDI_SYNC_RE = /^<-(.+)->\s+(.+)$/;
|
|
5749
|
+
C4_LABELED_BIDI_ASYNC_RE = /^<~(.+)~>\s+(.+)$/;
|
|
5619
5750
|
SECTION_HEADER_RE = /^(containers|components|deployment)\s*:\s*$/i;
|
|
5620
5751
|
CONTAINER_REF_RE = /^container\s+(.+)$/i;
|
|
5621
5752
|
METADATA_RE2 = /^([^:]+):\s*(.+)$/;
|
|
@@ -5676,13 +5807,13 @@ function looksLikeInitiativeStatus(content) {
|
|
|
5676
5807
|
let hasIndentedArrow = false;
|
|
5677
5808
|
for (const line7 of lines) {
|
|
5678
5809
|
const trimmed = line7.trim();
|
|
5679
|
-
if (!trimmed || trimmed.startsWith("
|
|
5810
|
+
if (!trimmed || trimmed.startsWith("//")) continue;
|
|
5680
5811
|
if (trimmed.match(/^chart\s*:/i)) continue;
|
|
5681
5812
|
if (trimmed.match(/^title\s*:/i)) continue;
|
|
5682
5813
|
if (trimmed.includes("->")) hasArrow = true;
|
|
5683
5814
|
if (/\|\s*(done|wip|todo|na)\s*$/i.test(trimmed)) hasStatus = true;
|
|
5684
5815
|
const isIndented = line7.length > 0 && line7 !== trimmed && /^\s/.test(line7);
|
|
5685
|
-
if (isIndented && trimmed.startsWith("->")) hasIndentedArrow = true;
|
|
5816
|
+
if (isIndented && (trimmed.startsWith("->") || /^-[^>].*->/.test(trimmed))) hasIndentedArrow = true;
|
|
5686
5817
|
if (hasArrow && hasStatus) return true;
|
|
5687
5818
|
}
|
|
5688
5819
|
return hasIndentedArrow;
|
|
@@ -5706,7 +5837,7 @@ function parseInitiativeStatus(content) {
|
|
|
5706
5837
|
groups: [],
|
|
5707
5838
|
options: {},
|
|
5708
5839
|
diagnostics: [],
|
|
5709
|
-
error:
|
|
5840
|
+
error: null
|
|
5710
5841
|
};
|
|
5711
5842
|
const lines = content.split("\n");
|
|
5712
5843
|
const nodeLabels = /* @__PURE__ */ new Set();
|
|
@@ -5716,7 +5847,7 @@ function parseInitiativeStatus(content) {
|
|
|
5716
5847
|
const lineNum = i + 1;
|
|
5717
5848
|
const raw = lines[i];
|
|
5718
5849
|
const trimmed = raw.trim();
|
|
5719
|
-
if (!trimmed || trimmed.startsWith("
|
|
5850
|
+
if (!trimmed || trimmed.startsWith("//")) continue;
|
|
5720
5851
|
const chartMatch = trimmed.match(/^chart\s*:\s*(.+)/i);
|
|
5721
5852
|
if (chartMatch) {
|
|
5722
5853
|
const chartType = chartMatch[1].trim().toLowerCase();
|
|
@@ -5749,7 +5880,7 @@ function parseInitiativeStatus(content) {
|
|
|
5749
5880
|
}
|
|
5750
5881
|
if (trimmed.includes("->")) {
|
|
5751
5882
|
let edgeText = trimmed;
|
|
5752
|
-
if (trimmed.startsWith("->")) {
|
|
5883
|
+
if (trimmed.startsWith("->") || /^-[^>].*->/.test(trimmed)) {
|
|
5753
5884
|
if (!lastNodeLabel) {
|
|
5754
5885
|
result.diagnostics.push(
|
|
5755
5886
|
makeDgmoError(lineNum, "Indented edge has no preceding node to use as source", "warning")
|
|
@@ -5815,6 +5946,27 @@ function parseNodeLine(trimmed, lineNum, diagnostics) {
|
|
|
5815
5946
|
return { label: trimmed, status: "na", shape: inferParticipantType(trimmed), lineNumber: lineNum };
|
|
5816
5947
|
}
|
|
5817
5948
|
function parseEdgeLine(trimmed, lineNum, diagnostics) {
|
|
5949
|
+
const labeledMatch = trimmed.match(/^(\S+)\s+-(.+)->\s+(.+)$/);
|
|
5950
|
+
if (labeledMatch) {
|
|
5951
|
+
const source2 = labeledMatch[1];
|
|
5952
|
+
const label2 = labeledMatch[2].trim();
|
|
5953
|
+
let targetRest = labeledMatch[3].trim();
|
|
5954
|
+
if (label2) {
|
|
5955
|
+
let status2 = "na";
|
|
5956
|
+
const lastPipe2 = targetRest.lastIndexOf("|");
|
|
5957
|
+
if (lastPipe2 >= 0) {
|
|
5958
|
+
const statusRaw = targetRest.slice(lastPipe2 + 1).trim();
|
|
5959
|
+
status2 = parseStatus(statusRaw, lineNum, diagnostics);
|
|
5960
|
+
targetRest = targetRest.slice(0, lastPipe2).trim();
|
|
5961
|
+
}
|
|
5962
|
+
const target2 = targetRest.trim();
|
|
5963
|
+
if (!target2) {
|
|
5964
|
+
diagnostics.push(makeDgmoError(lineNum, "Edge is missing target"));
|
|
5965
|
+
return null;
|
|
5966
|
+
}
|
|
5967
|
+
return { source: source2, target: target2, label: label2, status: status2, lineNumber: lineNum };
|
|
5968
|
+
}
|
|
5969
|
+
}
|
|
5818
5970
|
const arrowIdx = trimmed.indexOf("->");
|
|
5819
5971
|
if (arrowIdx < 0) return null;
|
|
5820
5972
|
const source = trimmed.slice(0, arrowIdx).trim();
|
|
@@ -5869,7 +6021,7 @@ function parseDgmoChartType(content) {
|
|
|
5869
6021
|
const lines = content.split("\n");
|
|
5870
6022
|
for (const line7 of lines) {
|
|
5871
6023
|
const trimmed = line7.trim();
|
|
5872
|
-
if (!trimmed || trimmed.startsWith("
|
|
6024
|
+
if (!trimmed || trimmed.startsWith("//"))
|
|
5873
6025
|
continue;
|
|
5874
6026
|
const match = trimmed.match(/^chart\s*:\s*(.+)/i);
|
|
5875
6027
|
if (match) return match[1].trim().toLowerCase();
|
|
@@ -7131,6 +7283,58 @@ var init_renderer = __esm({
|
|
|
7131
7283
|
}
|
|
7132
7284
|
});
|
|
7133
7285
|
|
|
7286
|
+
// src/utils/inline-markdown.ts
|
|
7287
|
+
function parseInlineMarkdown(text) {
|
|
7288
|
+
const spans = [];
|
|
7289
|
+
const regex = /\*\*(.+?)\*\*|__(.+?)__|\*(.+?)\*|_(.+?)_|`(.+?)`|\[(.+?)\]\((.+?)\)|(https?:\/\/[^\s)>\]]+|www\.[^\s)>\]]+)|([^*_`[]+?(?=https?:\/\/|www\.|$)|[^*_`[]+)/g;
|
|
7290
|
+
let match;
|
|
7291
|
+
while ((match = regex.exec(text)) !== null) {
|
|
7292
|
+
if (match[1]) spans.push({ text: match[1], bold: true });
|
|
7293
|
+
else if (match[2]) spans.push({ text: match[2], bold: true });
|
|
7294
|
+
else if (match[3]) spans.push({ text: match[3], italic: true });
|
|
7295
|
+
else if (match[4]) spans.push({ text: match[4], italic: true });
|
|
7296
|
+
else if (match[5]) spans.push({ text: match[5], code: true });
|
|
7297
|
+
else if (match[6]) spans.push({ text: match[6], href: match[7] });
|
|
7298
|
+
else if (match[8]) {
|
|
7299
|
+
const url = match[8];
|
|
7300
|
+
const href = url.startsWith("www.") ? `https://${url}` : url;
|
|
7301
|
+
spans.push({ text: url, href });
|
|
7302
|
+
} else if (match[9]) spans.push({ text: match[9] });
|
|
7303
|
+
}
|
|
7304
|
+
return spans;
|
|
7305
|
+
}
|
|
7306
|
+
function truncateBareUrl(url) {
|
|
7307
|
+
const stripped = url.replace(/^https?:\/\//, "").replace(/^www\./, "");
|
|
7308
|
+
if (stripped.length <= BARE_URL_MAX_DISPLAY) return stripped;
|
|
7309
|
+
return stripped.slice(0, BARE_URL_MAX_DISPLAY - 1) + "\u2026";
|
|
7310
|
+
}
|
|
7311
|
+
function renderInlineText(textEl, text, palette, fontSize) {
|
|
7312
|
+
const spans = parseInlineMarkdown(text);
|
|
7313
|
+
for (const span of spans) {
|
|
7314
|
+
if (span.href) {
|
|
7315
|
+
const isBareUrl = span.text === span.href || `https://${span.text}` === span.href;
|
|
7316
|
+
const display = isBareUrl ? truncateBareUrl(span.text) : span.text;
|
|
7317
|
+
const a = textEl.append("a").attr("href", span.href);
|
|
7318
|
+
a.append("tspan").text(display).attr("fill", palette.primary).style("text-decoration", "underline");
|
|
7319
|
+
} else {
|
|
7320
|
+
const tspan = textEl.append("tspan").text(span.text);
|
|
7321
|
+
if (span.bold) tspan.attr("font-weight", "bold");
|
|
7322
|
+
if (span.italic) tspan.attr("font-style", "italic");
|
|
7323
|
+
if (span.code) {
|
|
7324
|
+
tspan.attr("font-family", "monospace");
|
|
7325
|
+
if (fontSize) tspan.attr("font-size", fontSize - 1);
|
|
7326
|
+
}
|
|
7327
|
+
}
|
|
7328
|
+
}
|
|
7329
|
+
}
|
|
7330
|
+
var BARE_URL_MAX_DISPLAY;
|
|
7331
|
+
var init_inline_markdown = __esm({
|
|
7332
|
+
"src/utils/inline-markdown.ts"() {
|
|
7333
|
+
"use strict";
|
|
7334
|
+
BARE_URL_MAX_DISPLAY = 35;
|
|
7335
|
+
}
|
|
7336
|
+
});
|
|
7337
|
+
|
|
7134
7338
|
// src/kanban/mutations.ts
|
|
7135
7339
|
function computeCardMove(content, parsed, cardId, targetColumnId, targetIndex) {
|
|
7136
7340
|
let sourceCard = null;
|
|
@@ -7452,7 +7656,8 @@ function renderKanban(container, parsed, palette, isDark, _onNavigateToLine, exp
|
|
|
7452
7656
|
const cx = colLayout.x + cardLayout.x;
|
|
7453
7657
|
const cy = colLayout.y + cardLayout.y;
|
|
7454
7658
|
cg.append("rect").attr("x", cx).attr("y", cy).attr("width", cardLayout.width).attr("height", cardLayout.height).attr("rx", CARD_RADIUS2).attr("fill", cardFill).attr("stroke", cardStroke).attr("stroke-width", CARD_STROKE_WIDTH);
|
|
7455
|
-
cg.append("text").attr("x", cx + CARD_PADDING_X).attr("y", cy + CARD_PADDING_Y + CARD_TITLE_FONT_SIZE).attr("font-size", CARD_TITLE_FONT_SIZE).attr("font-weight", "500").attr("fill", palette.text)
|
|
7659
|
+
const titleEl = cg.append("text").attr("x", cx + CARD_PADDING_X).attr("y", cy + CARD_PADDING_Y + CARD_TITLE_FONT_SIZE).attr("font-size", CARD_TITLE_FONT_SIZE).attr("font-weight", "500").attr("fill", palette.text);
|
|
7660
|
+
renderInlineText(titleEl, card.title, palette, CARD_TITLE_FONT_SIZE);
|
|
7456
7661
|
if (hasMeta) {
|
|
7457
7662
|
const separatorY = cy + CARD_HEADER_HEIGHT;
|
|
7458
7663
|
cg.append("line").attr("x1", cx).attr("y1", separatorY).attr("x2", cx + cardLayout.width).attr("y2", separatorY).attr("stroke", cardStroke).attr("stroke-opacity", 0.3).attr("stroke-width", 1);
|
|
@@ -7464,7 +7669,8 @@ function renderKanban(container, parsed, palette, isDark, _onNavigateToLine, exp
|
|
|
7464
7669
|
metaY += CARD_META_LINE_HEIGHT;
|
|
7465
7670
|
}
|
|
7466
7671
|
for (const detail of card.details) {
|
|
7467
|
-
cg.append("text").attr("x", cx + CARD_PADDING_X).attr("y", metaY).attr("font-size", CARD_META_FONT_SIZE).attr("fill", palette.textMuted)
|
|
7672
|
+
const detailEl = cg.append("text").attr("x", cx + CARD_PADDING_X).attr("y", metaY).attr("font-size", CARD_META_FONT_SIZE).attr("fill", palette.textMuted);
|
|
7673
|
+
renderInlineText(detailEl, detail, palette, CARD_META_FONT_SIZE);
|
|
7468
7674
|
metaY += CARD_META_LINE_HEIGHT;
|
|
7469
7675
|
}
|
|
7470
7676
|
}
|
|
@@ -7490,6 +7696,7 @@ var init_renderer2 = __esm({
|
|
|
7490
7696
|
"use strict";
|
|
7491
7697
|
d3Selection2 = __toESM(require("d3-selection"), 1);
|
|
7492
7698
|
init_fonts();
|
|
7699
|
+
init_inline_markdown();
|
|
7493
7700
|
init_parser5();
|
|
7494
7701
|
init_mutations();
|
|
7495
7702
|
DIAGRAM_PADDING2 = 20;
|
|
@@ -10635,7 +10842,8 @@ function renderC4Context(container, parsed, layout, palette, isDark, onClickItem
|
|
|
10635
10842
|
const contentWidth = w - CARD_H_PAD3 * 2;
|
|
10636
10843
|
const lines = wrapText2(node.description, contentWidth, DESC_CHAR_WIDTH2);
|
|
10637
10844
|
for (const line7 of lines) {
|
|
10638
|
-
nodeG.append("text").attr("x", 0).attr("y", yPos + DESC_FONT_SIZE / 2).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("fill", palette.textMuted).attr("font-size", DESC_FONT_SIZE)
|
|
10845
|
+
const textEl = nodeG.append("text").attr("x", 0).attr("y", yPos + DESC_FONT_SIZE / 2).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("fill", palette.textMuted).attr("font-size", DESC_FONT_SIZE);
|
|
10846
|
+
renderInlineText(textEl, line7, palette, DESC_FONT_SIZE);
|
|
10639
10847
|
yPos += DESC_LINE_HEIGHT2;
|
|
10640
10848
|
}
|
|
10641
10849
|
}
|
|
@@ -11121,7 +11329,8 @@ function renderC4Containers(container, parsed, layout, palette, isDark, onClickI
|
|
|
11121
11329
|
const contentWidth = w - CARD_H_PAD3 * 2;
|
|
11122
11330
|
const lines = wrapText2(node.description, contentWidth, DESC_CHAR_WIDTH2);
|
|
11123
11331
|
for (const line7 of lines) {
|
|
11124
|
-
nodeG.append("text").attr("x", 0).attr("y", yPos + DESC_FONT_SIZE / 2).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("fill", palette.textMuted).attr("font-size", DESC_FONT_SIZE)
|
|
11332
|
+
const textEl = nodeG.append("text").attr("x", 0).attr("y", yPos + DESC_FONT_SIZE / 2).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("fill", palette.textMuted).attr("font-size", DESC_FONT_SIZE);
|
|
11333
|
+
renderInlineText(textEl, line7, palette, DESC_FONT_SIZE);
|
|
11125
11334
|
yPos += DESC_LINE_HEIGHT2;
|
|
11126
11335
|
}
|
|
11127
11336
|
}
|
|
@@ -11144,7 +11353,8 @@ function renderC4Containers(container, parsed, layout, palette, isDark, onClickI
|
|
|
11144
11353
|
const contentWidth = w - CARD_H_PAD3 * 2;
|
|
11145
11354
|
const lines = wrapText2(node.description, contentWidth, DESC_CHAR_WIDTH2);
|
|
11146
11355
|
for (const line7 of lines) {
|
|
11147
|
-
nodeG.append("text").attr("x", 0).attr("y", yPos + DESC_FONT_SIZE / 2).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("fill", palette.textMuted).attr("font-size", DESC_FONT_SIZE)
|
|
11356
|
+
const textEl = nodeG.append("text").attr("x", 0).attr("y", yPos + DESC_FONT_SIZE / 2).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("fill", palette.textMuted).attr("font-size", DESC_FONT_SIZE);
|
|
11357
|
+
renderInlineText(textEl, line7, palette, DESC_FONT_SIZE);
|
|
11148
11358
|
yPos += DESC_LINE_HEIGHT2;
|
|
11149
11359
|
}
|
|
11150
11360
|
}
|
|
@@ -11265,6 +11475,7 @@ var init_renderer6 = __esm({
|
|
|
11265
11475
|
d3Selection6 = __toESM(require("d3-selection"), 1);
|
|
11266
11476
|
d3Shape4 = __toESM(require("d3-shape"), 1);
|
|
11267
11477
|
init_fonts();
|
|
11478
|
+
init_inline_markdown();
|
|
11268
11479
|
init_parser6();
|
|
11269
11480
|
init_layout5();
|
|
11270
11481
|
DIAGRAM_PADDING6 = 20;
|
|
@@ -11762,49 +11973,6 @@ __export(renderer_exports7, {
|
|
|
11762
11973
|
renderSequenceDiagram: () => renderSequenceDiagram,
|
|
11763
11974
|
truncateBareUrl: () => truncateBareUrl
|
|
11764
11975
|
});
|
|
11765
|
-
function parseInlineMarkdown(text) {
|
|
11766
|
-
const spans = [];
|
|
11767
|
-
const regex = /\*\*(.+?)\*\*|__(.+?)__|\*(.+?)\*|_(.+?)_|`(.+?)`|\[(.+?)\]\((.+?)\)|(https?:\/\/[^\s)>\]]+|www\.[^\s)>\]]+)|([^*_`[]+?(?=https?:\/\/|www\.|$)|[^*_`[]+)/g;
|
|
11768
|
-
let match;
|
|
11769
|
-
while ((match = regex.exec(text)) !== null) {
|
|
11770
|
-
if (match[1]) spans.push({ text: match[1], bold: true });
|
|
11771
|
-
else if (match[2]) spans.push({ text: match[2], bold: true });
|
|
11772
|
-
else if (match[3]) spans.push({ text: match[3], italic: true });
|
|
11773
|
-
else if (match[4]) spans.push({ text: match[4], italic: true });
|
|
11774
|
-
else if (match[5]) spans.push({ text: match[5], code: true });
|
|
11775
|
-
else if (match[6]) spans.push({ text: match[6], href: match[7] });
|
|
11776
|
-
else if (match[8]) {
|
|
11777
|
-
const url = match[8];
|
|
11778
|
-
const href = url.startsWith("www.") ? `https://${url}` : url;
|
|
11779
|
-
spans.push({ text: url, href });
|
|
11780
|
-
} else if (match[9]) spans.push({ text: match[9] });
|
|
11781
|
-
}
|
|
11782
|
-
return spans;
|
|
11783
|
-
}
|
|
11784
|
-
function truncateBareUrl(url) {
|
|
11785
|
-
const stripped = url.replace(/^https?:\/\//, "").replace(/^www\./, "");
|
|
11786
|
-
if (stripped.length <= BARE_URL_MAX_DISPLAY) return stripped;
|
|
11787
|
-
return stripped.slice(0, BARE_URL_MAX_DISPLAY - 1) + "\u2026";
|
|
11788
|
-
}
|
|
11789
|
-
function renderInlineText(textEl, text, palette, fontSize) {
|
|
11790
|
-
const spans = parseInlineMarkdown(text);
|
|
11791
|
-
for (const span of spans) {
|
|
11792
|
-
if (span.href) {
|
|
11793
|
-
const isBareUrl = span.text === span.href || `https://${span.text}` === span.href;
|
|
11794
|
-
const display = isBareUrl ? truncateBareUrl(span.text) : span.text;
|
|
11795
|
-
const a = textEl.append("a").attr("href", span.href);
|
|
11796
|
-
a.append("tspan").text(display).attr("fill", palette.primary).style("text-decoration", "underline");
|
|
11797
|
-
} else {
|
|
11798
|
-
const tspan = textEl.append("tspan").text(span.text);
|
|
11799
|
-
if (span.bold) tspan.attr("font-weight", "bold");
|
|
11800
|
-
if (span.italic) tspan.attr("font-style", "italic");
|
|
11801
|
-
if (span.code) {
|
|
11802
|
-
tspan.attr("font-family", "monospace");
|
|
11803
|
-
if (fontSize) tspan.attr("font-size", fontSize - 1);
|
|
11804
|
-
}
|
|
11805
|
-
}
|
|
11806
|
-
}
|
|
11807
|
-
}
|
|
11808
11976
|
function wrapTextLines(text, maxChars) {
|
|
11809
11977
|
const rawLines = text.split("\n");
|
|
11810
11978
|
const wrapped = [];
|
|
@@ -11985,8 +12153,12 @@ function buildRenderSequence(messages) {
|
|
|
11985
12153
|
to: msg.to,
|
|
11986
12154
|
label: msg.label,
|
|
11987
12155
|
messageIndex: mi,
|
|
11988
|
-
...msg.async ? { async: true } : {}
|
|
12156
|
+
...msg.async ? { async: true } : {},
|
|
12157
|
+
...msg.bidirectional ? { bidirectional: true } : {}
|
|
11989
12158
|
});
|
|
12159
|
+
if (msg.bidirectional) {
|
|
12160
|
+
continue;
|
|
12161
|
+
}
|
|
11990
12162
|
if (msg.async) {
|
|
11991
12163
|
continue;
|
|
11992
12164
|
}
|
|
@@ -12478,6 +12650,14 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
|
|
|
12478
12650
|
"points",
|
|
12479
12651
|
`0,0 ${ARROWHEAD_SIZE},${ARROWHEAD_SIZE / 2} 0,${ARROWHEAD_SIZE}`
|
|
12480
12652
|
).attr("fill", "none").attr("stroke", palette.text).attr("stroke-width", 1.2);
|
|
12653
|
+
defs.append("marker").attr("id", "seq-arrowhead-reverse").attr("viewBox", `0 0 ${ARROWHEAD_SIZE} ${ARROWHEAD_SIZE}`).attr("refX", 0).attr("refY", ARROWHEAD_SIZE / 2).attr("markerWidth", ARROWHEAD_SIZE).attr("markerHeight", ARROWHEAD_SIZE).attr("orient", "auto").append("polygon").attr(
|
|
12654
|
+
"points",
|
|
12655
|
+
`${ARROWHEAD_SIZE},0 0,${ARROWHEAD_SIZE / 2} ${ARROWHEAD_SIZE},${ARROWHEAD_SIZE}`
|
|
12656
|
+
).attr("fill", palette.text);
|
|
12657
|
+
defs.append("marker").attr("id", "seq-arrowhead-async-reverse").attr("viewBox", `0 0 ${ARROWHEAD_SIZE} ${ARROWHEAD_SIZE}`).attr("refX", 0).attr("refY", ARROWHEAD_SIZE / 2).attr("markerWidth", ARROWHEAD_SIZE).attr("markerHeight", ARROWHEAD_SIZE).attr("orient", "auto").append("polyline").attr(
|
|
12658
|
+
"points",
|
|
12659
|
+
`${ARROWHEAD_SIZE},0 0,${ARROWHEAD_SIZE / 2} ${ARROWHEAD_SIZE},${ARROWHEAD_SIZE}`
|
|
12660
|
+
).attr("fill", "none").attr("stroke", palette.text).attr("stroke-width", 1.2);
|
|
12481
12661
|
if (title) {
|
|
12482
12662
|
const titleEl = svg.append("text").attr("class", "chart-title").attr("x", svgWidth / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", palette.text).attr("font-size", 20).attr("font-weight", "bold").text(title);
|
|
12483
12663
|
if (parsed.titleLineNumber) {
|
|
@@ -12758,10 +12938,17 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
|
|
|
12758
12938
|
const x1 = arrowEdgeX(step.from, i, goingRight ? "right" : "left");
|
|
12759
12939
|
const x2 = arrowEdgeX(step.to, i, goingRight ? "left" : "right");
|
|
12760
12940
|
const markerRef = step.async ? "url(#seq-arrowhead-async)" : "url(#seq-arrowhead)";
|
|
12761
|
-
|
|
12941
|
+
const markerStartRef = step.bidirectional ? step.async ? "url(#seq-arrowhead-async-reverse)" : "url(#seq-arrowhead-reverse)" : null;
|
|
12942
|
+
const line7 = svg.append("line").attr("x1", x1).attr("y1", y).attr("x2", x2).attr("y2", y).attr("stroke", palette.text).attr("stroke-width", 1.2).attr("marker-end", markerRef).attr("class", "message-arrow").attr(
|
|
12762
12943
|
"data-line-number",
|
|
12763
12944
|
String(messages[step.messageIndex].lineNumber)
|
|
12764
12945
|
).attr("data-msg-index", String(step.messageIndex)).attr("data-step-index", String(i));
|
|
12946
|
+
if (markerStartRef) {
|
|
12947
|
+
line7.attr("marker-start", markerStartRef);
|
|
12948
|
+
}
|
|
12949
|
+
if (step.bidirectional && step.async) {
|
|
12950
|
+
line7.attr("stroke-dasharray", "6 4");
|
|
12951
|
+
}
|
|
12765
12952
|
if (step.label) {
|
|
12766
12953
|
const midX = (x1 + x2) / 2;
|
|
12767
12954
|
const labelEl = svg.append("text").attr("x", midX).attr("y", y - 8).attr("text-anchor", "middle").attr("fill", palette.text).attr("font-size", 12).attr("class", "message-label").attr(
|
|
@@ -12949,12 +13136,13 @@ function renderParticipant(svg, participant, cx, cy, palette, isDark) {
|
|
|
12949
13136
|
isActor ? PARTICIPANT_BOX_HEIGHT + 14 : PARTICIPANT_BOX_HEIGHT / 2 + 5
|
|
12950
13137
|
).attr("text-anchor", "middle").attr("fill", palette.text).attr("font-size", 13).attr("font-weight", 500).text(participant.label);
|
|
12951
13138
|
}
|
|
12952
|
-
var d3Selection8, PARTICIPANT_GAP, PARTICIPANT_BOX_WIDTH, PARTICIPANT_BOX_HEIGHT, TOP_MARGIN, TITLE_HEIGHT4, PARTICIPANT_Y_OFFSET, SERVICE_BORDER_RADIUS, MESSAGE_START_OFFSET, LIFELINE_TAIL, ARROWHEAD_SIZE, NOTE_MAX_W, NOTE_FOLD, NOTE_PAD_H, NOTE_PAD_V, NOTE_FONT_SIZE, NOTE_LINE_H, NOTE_GAP, NOTE_CHAR_W, NOTE_CHARS_PER_LINE, COLLAPSED_NOTE_H, COLLAPSED_NOTE_W,
|
|
13139
|
+
var d3Selection8, PARTICIPANT_GAP, PARTICIPANT_BOX_WIDTH, PARTICIPANT_BOX_HEIGHT, TOP_MARGIN, TITLE_HEIGHT4, PARTICIPANT_Y_OFFSET, SERVICE_BORDER_RADIUS, MESSAGE_START_OFFSET, LIFELINE_TAIL, ARROWHEAD_SIZE, NOTE_MAX_W, NOTE_FOLD, NOTE_PAD_H, NOTE_PAD_V, NOTE_FONT_SIZE, NOTE_LINE_H, NOTE_GAP, NOTE_CHAR_W, NOTE_CHARS_PER_LINE, COLLAPSED_NOTE_H, COLLAPSED_NOTE_W, fill, stroke, SW, W, H;
|
|
12953
13140
|
var init_renderer7 = __esm({
|
|
12954
13141
|
"src/sequence/renderer.ts"() {
|
|
12955
13142
|
"use strict";
|
|
12956
13143
|
d3Selection8 = __toESM(require("d3-selection"), 1);
|
|
12957
13144
|
init_colors();
|
|
13145
|
+
init_inline_markdown();
|
|
12958
13146
|
init_fonts();
|
|
12959
13147
|
init_parser();
|
|
12960
13148
|
PARTICIPANT_GAP = 160;
|
|
@@ -12978,7 +13166,6 @@ var init_renderer7 = __esm({
|
|
|
12978
13166
|
NOTE_CHARS_PER_LINE = Math.floor((NOTE_MAX_W - NOTE_PAD_H * 2 - NOTE_FOLD) / NOTE_CHAR_W);
|
|
12979
13167
|
COLLAPSED_NOTE_H = 20;
|
|
12980
13168
|
COLLAPSED_NOTE_W = 40;
|
|
12981
|
-
BARE_URL_MAX_DISPLAY = 35;
|
|
12982
13169
|
fill = (palette, isDark) => mix8(palette.primary, isDark ? palette.surface : palette.bg, isDark ? 15 : 30);
|
|
12983
13170
|
stroke = (palette) => palette.textMuted;
|
|
12984
13171
|
SW = 1.5;
|
|
@@ -13108,7 +13295,7 @@ function parseD3(content, palette) {
|
|
|
13108
13295
|
}
|
|
13109
13296
|
continue;
|
|
13110
13297
|
}
|
|
13111
|
-
if (line7.startsWith("
|
|
13298
|
+
if (line7.startsWith("//")) {
|
|
13112
13299
|
continue;
|
|
13113
13300
|
}
|
|
13114
13301
|
if (result.type === "arc") {
|
|
@@ -16281,6 +16468,7 @@ __export(index_exports, {
|
|
|
16281
16468
|
parseERDiagram: () => parseERDiagram,
|
|
16282
16469
|
parseFlowchart: () => parseFlowchart,
|
|
16283
16470
|
parseInitiativeStatus: () => parseInitiativeStatus,
|
|
16471
|
+
parseInlineMarkdown: () => parseInlineMarkdown,
|
|
16284
16472
|
parseKanban: () => parseKanban,
|
|
16285
16473
|
parseOrg: () => parseOrg,
|
|
16286
16474
|
parseQuadrant: () => parseQuadrant,
|
|
@@ -16324,7 +16512,8 @@ __export(index_exports, {
|
|
|
16324
16512
|
shade: () => shade,
|
|
16325
16513
|
solarizedPalette: () => solarizedPalette,
|
|
16326
16514
|
tint: () => tint,
|
|
16327
|
-
tokyoNightPalette: () => tokyoNightPalette
|
|
16515
|
+
tokyoNightPalette: () => tokyoNightPalette,
|
|
16516
|
+
truncateBareUrl: () => truncateBareUrl
|
|
16328
16517
|
});
|
|
16329
16518
|
module.exports = __toCommonJS(index_exports);
|
|
16330
16519
|
init_diagnostics();
|
|
@@ -16405,7 +16594,7 @@ function parseQuadrant(content) {
|
|
|
16405
16594
|
for (let i = 0; i < lines.length; i++) {
|
|
16406
16595
|
const line7 = lines[i].trim();
|
|
16407
16596
|
const lineNumber = i + 1;
|
|
16408
|
-
if (!line7 || line7.startsWith("
|
|
16597
|
+
if (!line7 || line7.startsWith("//")) continue;
|
|
16409
16598
|
if (/^chart\s*:/i.test(line7)) continue;
|
|
16410
16599
|
const titleMatch = line7.match(/^title\s*:\s*(.+)/i);
|
|
16411
16600
|
if (titleMatch) {
|
|
@@ -16535,6 +16724,7 @@ init_renderer3();
|
|
|
16535
16724
|
init_parser3();
|
|
16536
16725
|
init_layout3();
|
|
16537
16726
|
init_renderer4();
|
|
16727
|
+
init_inline_markdown();
|
|
16538
16728
|
init_parser4();
|
|
16539
16729
|
init_layout();
|
|
16540
16730
|
init_renderer();
|
|
@@ -16551,12 +16741,12 @@ init_collapse();
|
|
|
16551
16741
|
|
|
16552
16742
|
// src/org/resolver.ts
|
|
16553
16743
|
init_diagnostics();
|
|
16744
|
+
init_tag_groups();
|
|
16554
16745
|
var MAX_DEPTH = 10;
|
|
16555
16746
|
var IMPORT_RE = /^(\s+)import:\s+(.+\.dgmo)\s*$/i;
|
|
16556
16747
|
var TAGS_RE = /^tags:\s+(.+\.dgmo)\s*$/i;
|
|
16557
16748
|
var HEADER_RE = /^(chart|title)\s*:/i;
|
|
16558
|
-
var
|
|
16559
|
-
var GROUP_HEADING_RE5 = /^##\s+/;
|
|
16749
|
+
var OPTION_RE2 = /^[a-z][a-z0-9-]*\s*:/i;
|
|
16560
16750
|
function dirname(filePath) {
|
|
16561
16751
|
const last = filePath.lastIndexOf("/");
|
|
16562
16752
|
return last > 0 ? filePath.substring(0, last) : "/";
|
|
@@ -16577,9 +16767,9 @@ function extractTagGroups(lines) {
|
|
|
16577
16767
|
let current = null;
|
|
16578
16768
|
for (const line7 of lines) {
|
|
16579
16769
|
const trimmed = line7.trim();
|
|
16580
|
-
|
|
16581
|
-
|
|
16582
|
-
const name =
|
|
16770
|
+
const headingMatch = matchTagBlockHeading(trimmed);
|
|
16771
|
+
if (headingMatch) {
|
|
16772
|
+
const name = headingMatch.name.toLowerCase();
|
|
16583
16773
|
current = { name, lines: [line7] };
|
|
16584
16774
|
blocks.push(current);
|
|
16585
16775
|
} else if (current) {
|
|
@@ -16621,7 +16811,7 @@ function parseFileHeader(lines) {
|
|
|
16621
16811
|
tagsDirective = tagsMatch[1].trim();
|
|
16622
16812
|
continue;
|
|
16623
16813
|
}
|
|
16624
|
-
if (
|
|
16814
|
+
if (OPTION_RE2.test(trimmed) && !isTagBlockHeading(trimmed) && !lines[i].match(/^\s/)) {
|
|
16625
16815
|
const key = trimmed.split(":")[0].trim().toLowerCase();
|
|
16626
16816
|
if (key !== "chart" && key !== "title" && !trimmed.includes("|")) {
|
|
16627
16817
|
continue;
|
|
@@ -16651,7 +16841,7 @@ async function resolveFile(content, filePath, readFileFn, diagnostics, ancestorC
|
|
|
16651
16841
|
headerLines.push(lines[i]);
|
|
16652
16842
|
continue;
|
|
16653
16843
|
}
|
|
16654
|
-
if (
|
|
16844
|
+
if (isTagBlockHeading(trimmed)) continue;
|
|
16655
16845
|
if (lines[i] !== trimmed) continue;
|
|
16656
16846
|
const tagsMatch = trimmed.match(TAGS_RE);
|
|
16657
16847
|
if (tagsMatch) {
|
|
@@ -16683,7 +16873,7 @@ async function resolveFile(content, filePath, readFileFn, diagnostics, ancestorC
|
|
|
16683
16873
|
const importMatch = line7.match(IMPORT_RE);
|
|
16684
16874
|
if (!importMatch) {
|
|
16685
16875
|
const trimmed = line7.trim();
|
|
16686
|
-
if (
|
|
16876
|
+
if (isTagBlockHeading(trimmed) || inlineTagGroups.length > 0 && isTagGroupEntry(line7, bodyLines, i)) {
|
|
16687
16877
|
continue;
|
|
16688
16878
|
}
|
|
16689
16879
|
resolvedBodyLines.push(line7);
|
|
@@ -16778,7 +16968,7 @@ function findBodyStart(lines) {
|
|
|
16778
16968
|
if (inTagGroup) inTagGroup = false;
|
|
16779
16969
|
continue;
|
|
16780
16970
|
}
|
|
16781
|
-
if (
|
|
16971
|
+
if (isTagBlockHeading(trimmed)) {
|
|
16782
16972
|
inTagGroup = true;
|
|
16783
16973
|
continue;
|
|
16784
16974
|
}
|
|
@@ -16790,7 +16980,7 @@ function findBodyStart(lines) {
|
|
|
16790
16980
|
}
|
|
16791
16981
|
if (HEADER_RE.test(trimmed)) continue;
|
|
16792
16982
|
if (TAGS_RE.test(trimmed)) continue;
|
|
16793
|
-
if (
|
|
16983
|
+
if (OPTION_RE2.test(trimmed) && !isTagBlockHeading(trimmed) && !lines[i].match(/^\s/) && !trimmed.includes("|")) {
|
|
16794
16984
|
const key = trimmed.split(":")[0].trim().toLowerCase();
|
|
16795
16985
|
if (key !== "chart" && key !== "title") {
|
|
16796
16986
|
continue;
|
|
@@ -16805,7 +16995,7 @@ function isTagGroupEntry(line7, allLines, index) {
|
|
|
16805
16995
|
for (let i = index - 1; i >= 0; i--) {
|
|
16806
16996
|
const prev = allLines[i].trim();
|
|
16807
16997
|
if (prev === "" || prev.startsWith("//")) continue;
|
|
16808
|
-
if (
|
|
16998
|
+
if (isTagBlockHeading(prev)) return true;
|
|
16809
16999
|
if (allLines[i].match(/^\s+/)) continue;
|
|
16810
17000
|
return false;
|
|
16811
17001
|
}
|
|
@@ -16960,6 +17150,7 @@ init_branding();
|
|
|
16960
17150
|
parseERDiagram,
|
|
16961
17151
|
parseFlowchart,
|
|
16962
17152
|
parseInitiativeStatus,
|
|
17153
|
+
parseInlineMarkdown,
|
|
16963
17154
|
parseKanban,
|
|
16964
17155
|
parseOrg,
|
|
16965
17156
|
parseQuadrant,
|
|
@@ -17003,6 +17194,7 @@ init_branding();
|
|
|
17003
17194
|
shade,
|
|
17004
17195
|
solarizedPalette,
|
|
17005
17196
|
tint,
|
|
17006
|
-
tokyoNightPalette
|
|
17197
|
+
tokyoNightPalette,
|
|
17198
|
+
truncateBareUrl
|
|
17007
17199
|
});
|
|
17008
17200
|
//# sourceMappingURL=index.cjs.map
|