@diagrammo/dgmo 0.84.0 → 0.85.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/advanced.d.ts +11 -0
- package/dist/advanced.js +6 -6
- package/dist/block.js +5 -5
- package/dist/chart-meta.js +2 -2
- package/dist/{chunk-QZRYCRT7.js → chunk-ADAGWVWJ.js} +5 -5
- package/dist/{chunk-ECIXBEG2.js → chunk-JVRDKR5R.js} +1 -1
- package/dist/{chunk-AYA6C64M.js → chunk-NJS62BAG.js} +83 -26
- package/dist/{chunk-VKGQX6P2.js → chunk-OZTDXMRQ.js} +1 -1
- package/dist/{chunk-KABGWUND.js → chunk-T327J6CE.js} +4 -2
- package/dist/{chunk-6EV2F6W7.js → chunk-VPASQOR3.js} +68 -46
- package/dist/{dgmo-router-YW4SBNYB.js → dgmo-router-VILEOWQ2.js} +3 -3
- package/dist/index.js +5 -5
- package/dist/{parser-6PHQJO42.js → parser-PVIWHVGY.js} +1 -1
- package/dist/{renderer-QZW4RCZW.js → renderer-5A6VWIVX.js} +4 -4
- package/dist/{renderer-GWNSV76V.js → renderer-DRLLZZ6P.js} +2 -2
- package/docs/language-reference.md +12 -0
- package/gallery/fixtures/sequence-groups-nested.dgmo +50 -0
- package/package.json +1 -1
package/dist/advanced.d.ts
CHANGED
|
@@ -1034,8 +1034,19 @@ declare function isSequenceNote(el: SequenceElement): el is SequenceNote;
|
|
|
1034
1034
|
*/
|
|
1035
1035
|
interface SequenceGroup {
|
|
1036
1036
|
readonly name: string;
|
|
1037
|
+
/**
|
|
1038
|
+
* Every participant under this group, nested ones included, in source
|
|
1039
|
+
* order. Transitive so a frame — outer or inner — can size itself from one
|
|
1040
|
+
* list; `parent` is what distinguishes the two. Members of a nested group
|
|
1041
|
+
* are contiguous inside their parent's list because the source order that
|
|
1042
|
+
* built it is the order they were written in.
|
|
1043
|
+
*/
|
|
1037
1044
|
readonly participantIds: readonly ParticipantId[];
|
|
1038
1045
|
readonly lineNumber: number;
|
|
1046
|
+
/** Name of the enclosing group, when this one is indented inside another. */
|
|
1047
|
+
readonly parent?: string;
|
|
1048
|
+
/** 0 for a top-level group, 1 for one nested inside it. Capped at MAX_GROUP_DEPTH - 1. */
|
|
1049
|
+
readonly depth: number;
|
|
1039
1050
|
/** Pipe-delimited tag metadata (e.g. `[Backend | t: Product]`) */
|
|
1040
1051
|
readonly metadata?: Readonly<Record<string, string>>;
|
|
1041
1052
|
/** Whether this group is collapsed by default */
|
package/dist/advanced.js
CHANGED
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
computeActivations,
|
|
17
17
|
groupMessagesBySection,
|
|
18
18
|
renderSequenceDiagram
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-NJS62BAG.js";
|
|
20
20
|
import {
|
|
21
21
|
renderRing,
|
|
22
22
|
renderRingForExport
|
|
@@ -320,8 +320,8 @@ import {
|
|
|
320
320
|
renderSlopeChart,
|
|
321
321
|
renderVenn,
|
|
322
322
|
renderWordCloud
|
|
323
|
-
} from "./chunk-
|
|
324
|
-
import "./chunk-
|
|
323
|
+
} from "./chunk-ADAGWVWJ.js";
|
|
324
|
+
import "./chunk-OZTDXMRQ.js";
|
|
325
325
|
import {
|
|
326
326
|
CHART_TYPE_DESCRIPTIONS,
|
|
327
327
|
chartTypeParsers,
|
|
@@ -331,7 +331,7 @@ import {
|
|
|
331
331
|
knownChartTypeIds,
|
|
332
332
|
parseDgmo,
|
|
333
333
|
parseVisualization
|
|
334
|
-
} from "./chunk-
|
|
334
|
+
} from "./chunk-T327J6CE.js";
|
|
335
335
|
import "./chunk-EOYPX6SF.js";
|
|
336
336
|
import {
|
|
337
337
|
normalizePlace,
|
|
@@ -527,7 +527,7 @@ import {
|
|
|
527
527
|
} from "./chunk-RE27AX7O.js";
|
|
528
528
|
import {
|
|
529
529
|
parseDgmoChartType
|
|
530
|
-
} from "./chunk-
|
|
530
|
+
} from "./chunk-JVRDKR5R.js";
|
|
531
531
|
import {
|
|
532
532
|
allTasks,
|
|
533
533
|
parseRaci
|
|
@@ -548,7 +548,7 @@ import {
|
|
|
548
548
|
isSequenceNote,
|
|
549
549
|
looksLikeSequence,
|
|
550
550
|
parseSequenceDgmo
|
|
551
|
-
} from "./chunk-
|
|
551
|
+
} from "./chunk-VPASQOR3.js";
|
|
552
552
|
import {
|
|
553
553
|
RULE_COUNT,
|
|
554
554
|
inferParticipantType
|
package/dist/block.js
CHANGED
|
@@ -4,12 +4,12 @@ import {
|
|
|
4
4
|
} from "./chunk-D3K4U3ZM.js";
|
|
5
5
|
import {
|
|
6
6
|
render
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-ADAGWVWJ.js";
|
|
8
8
|
import {
|
|
9
9
|
docsLink,
|
|
10
10
|
renderErrorCard
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-OZTDXMRQ.js";
|
|
12
|
+
import "./chunk-T327J6CE.js";
|
|
13
13
|
import "./chunk-EOYPX6SF.js";
|
|
14
14
|
import "./chunk-WP2RLGDI.js";
|
|
15
15
|
import "./chunk-A2RUBBVT.js";
|
|
@@ -68,7 +68,7 @@ import "./chunk-KAO7JL4I.js";
|
|
|
68
68
|
import {
|
|
69
69
|
encodeDiagramUrl
|
|
70
70
|
} from "./chunk-RE27AX7O.js";
|
|
71
|
-
import "./chunk-
|
|
71
|
+
import "./chunk-JVRDKR5R.js";
|
|
72
72
|
import "./chunk-3RYBTEF5.js";
|
|
73
73
|
import "./chunk-UNNJCSSQ.js";
|
|
74
74
|
import "./chunk-3TYUXC7D.js";
|
|
@@ -77,7 +77,7 @@ import "./chunk-EQW6HOP4.js";
|
|
|
77
77
|
import {
|
|
78
78
|
scanMonthNameDates
|
|
79
79
|
} from "./chunk-DAOFNU6J.js";
|
|
80
|
-
import "./chunk-
|
|
80
|
+
import "./chunk-VPASQOR3.js";
|
|
81
81
|
import "./chunk-C3Z4DX3V.js";
|
|
82
82
|
import "./chunk-JRUEIRJB.js";
|
|
83
83
|
import "./chunk-7TF3QOOD.js";
|
package/dist/chart-meta.js
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from "./chunk-RE27AX7O.js";
|
|
11
11
|
import {
|
|
12
12
|
parseDgmoChartType
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-JVRDKR5R.js";
|
|
14
14
|
import {
|
|
15
15
|
parseRaci
|
|
16
16
|
} from "./chunk-3RYBTEF5.js";
|
|
@@ -19,7 +19,7 @@ import "./chunk-3TYUXC7D.js";
|
|
|
19
19
|
import "./chunk-HMWZQ53A.js";
|
|
20
20
|
import "./chunk-EQW6HOP4.js";
|
|
21
21
|
import "./chunk-DAOFNU6J.js";
|
|
22
|
-
import "./chunk-
|
|
22
|
+
import "./chunk-VPASQOR3.js";
|
|
23
23
|
import "./chunk-C3Z4DX3V.js";
|
|
24
24
|
import "./chunk-JRUEIRJB.js";
|
|
25
25
|
import "./chunk-7TF3QOOD.js";
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
parseVenn,
|
|
9
9
|
parseVisualization,
|
|
10
10
|
parseWordcloud
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-T327J6CE.js";
|
|
12
12
|
import {
|
|
13
13
|
MAP_DX
|
|
14
14
|
} from "./chunk-EOYPX6SF.js";
|
|
@@ -1951,7 +1951,7 @@ function resolveArcChordOverride(content, detectedType, palette) {
|
|
|
1951
1951
|
}
|
|
1952
1952
|
async function renderForExport(content, theme, palette, viewState, options) {
|
|
1953
1953
|
const exportMode = options?.exportMode ?? false;
|
|
1954
|
-
const { parseDgmoChartType } = await import("./dgmo-router-
|
|
1954
|
+
const { parseDgmoChartType } = await import("./dgmo-router-VILEOWQ2.js");
|
|
1955
1955
|
const detectedTypeRaw = parseDgmoChartType(content);
|
|
1956
1956
|
const override = resolveArcChordOverride(content, detectedTypeRaw, palette);
|
|
1957
1957
|
const renderContent = override?.content ?? content;
|
|
@@ -2877,7 +2877,7 @@ async function exportTreemap(ctx) {
|
|
|
2877
2877
|
async function exportLiveLink(ctx) {
|
|
2878
2878
|
const { content, theme, palette } = ctx;
|
|
2879
2879
|
const { parseLiveLink } = await import("./parser-6TXNMXNB.js");
|
|
2880
|
-
const { renderLiveLinkCard } = await import("./renderer-
|
|
2880
|
+
const { renderLiveLinkCard } = await import("./renderer-5A6VWIVX.js");
|
|
2881
2881
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2882
2882
|
return renderLiveLinkCard(parseLiveLink(content), effectivePalette, theme);
|
|
2883
2883
|
}
|
|
@@ -3087,8 +3087,8 @@ async function exportVisualization(ctx) {
|
|
|
3087
3087
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
3088
3088
|
const isDark = ctx.isDark;
|
|
3089
3089
|
const container = createExportContainer(ctx.width, ctx.height);
|
|
3090
|
-
const { parseSequenceDgmo } = await import("./parser-
|
|
3091
|
-
const { renderSequenceDiagram } = await import("./renderer-
|
|
3090
|
+
const { parseSequenceDgmo } = await import("./parser-PVIWHVGY.js");
|
|
3091
|
+
const { renderSequenceDiagram } = await import("./renderer-DRLLZZ6P.js");
|
|
3092
3092
|
const seqParsed = parseSequenceDgmo(content, effectivePalette);
|
|
3093
3093
|
if (seqParsed.error || seqParsed.participants.length === 0) return "";
|
|
3094
3094
|
const collapsedSections = viewState?.cs ? new Set(viewState.cs) : void 0;
|
|
@@ -43,7 +43,7 @@ import {
|
|
|
43
43
|
isSequenceBlock,
|
|
44
44
|
isSequenceNote,
|
|
45
45
|
isSequenceSection
|
|
46
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-VPASQOR3.js";
|
|
47
47
|
import {
|
|
48
48
|
resolveActiveTagGroup,
|
|
49
49
|
tagAttrKey
|
|
@@ -74,12 +74,28 @@ function applyCollapseProjection(parsed, collapsedGroups) {
|
|
|
74
74
|
collapsedGroupIds: /* @__PURE__ */ new Map()
|
|
75
75
|
};
|
|
76
76
|
}
|
|
77
|
+
const byName = new Map(parsed.groups.map((g) => [g.name, g]));
|
|
78
|
+
const insideCollapsed = (group) => {
|
|
79
|
+
let parentName = group.parent;
|
|
80
|
+
const seen = /* @__PURE__ */ new Set();
|
|
81
|
+
while (parentName !== void 0 && !seen.has(parentName)) {
|
|
82
|
+
seen.add(parentName);
|
|
83
|
+
const ancestor = byName.get(parentName);
|
|
84
|
+
if (!ancestor) return false;
|
|
85
|
+
if (collapsedGroups.has(ancestor.lineNumber)) return true;
|
|
86
|
+
parentName = ancestor.parent;
|
|
87
|
+
}
|
|
88
|
+
return false;
|
|
89
|
+
};
|
|
77
90
|
const memberToGroup = /* @__PURE__ */ new Map();
|
|
78
91
|
const collapsedGroupNames = /* @__PURE__ */ new Set();
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
92
|
+
const byDepth = [...parsed.groups].sort((a, b) => a.depth - b.depth);
|
|
93
|
+
for (const group of byDepth) {
|
|
94
|
+
if (!collapsedGroups.has(group.lineNumber)) continue;
|
|
95
|
+
if (insideCollapsed(group)) continue;
|
|
96
|
+
collapsedGroupNames.add(group.name);
|
|
97
|
+
for (const memberId of group.participantIds) {
|
|
98
|
+
if (!memberToGroup.has(memberId)) {
|
|
83
99
|
memberToGroup.set(memberId, group.name);
|
|
84
100
|
}
|
|
85
101
|
}
|
|
@@ -114,9 +130,14 @@ function applyCollapseProjection(parsed, collapsedGroups) {
|
|
|
114
130
|
to: remap(msg.to)
|
|
115
131
|
}));
|
|
116
132
|
const elements = remapElements(parsed.elements, memberToGroup);
|
|
117
|
-
const groups = parsed.groups.filter(
|
|
118
|
-
|
|
119
|
-
|
|
133
|
+
const groups = parsed.groups.filter((g) => !collapsedGroups.has(g.lineNumber) && !insideCollapsed(g)).map((g) => {
|
|
134
|
+
const remapped = [];
|
|
135
|
+
for (const id of g.participantIds) {
|
|
136
|
+
const to = memberToGroup.get(id) ?? id;
|
|
137
|
+
if (!remapped.includes(to)) remapped.push(to);
|
|
138
|
+
}
|
|
139
|
+
return { ...g, participantIds: remapped };
|
|
140
|
+
});
|
|
120
141
|
return {
|
|
121
142
|
participants,
|
|
122
143
|
messages,
|
|
@@ -163,7 +184,7 @@ function remapElements(elements, memberToGroup) {
|
|
|
163
184
|
|
|
164
185
|
// src/sequence/tag-resolution.ts
|
|
165
186
|
function propagateGroupTags(participantMeta, groups) {
|
|
166
|
-
for (const group of groups) {
|
|
187
|
+
for (const group of [...groups].sort((a, b) => b.depth - a.depth)) {
|
|
167
188
|
if (!group.metadata) continue;
|
|
168
189
|
for (const id of group.participantIds) {
|
|
169
190
|
const meta = participantMeta.get(id);
|
|
@@ -592,6 +613,7 @@ function applyPositionOverrides(participants) {
|
|
|
592
613
|
function applyGroupOrdering(participants, groups, messages = []) {
|
|
593
614
|
const idToGroup = /* @__PURE__ */ new Map();
|
|
594
615
|
for (const group of groups) {
|
|
616
|
+
if (group.parent !== void 0) continue;
|
|
595
617
|
for (const id of group.participantIds) {
|
|
596
618
|
idToGroup.set(id, group);
|
|
597
619
|
}
|
|
@@ -672,6 +694,7 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
|
|
|
672
694
|
if (groups.length > 0) {
|
|
673
695
|
const pToG = /* @__PURE__ */ new Map();
|
|
674
696
|
for (let gi = 0; gi < groups.length; gi++) {
|
|
697
|
+
if (groups[gi].parent !== void 0) continue;
|
|
675
698
|
for (const pid of groups[gi].participantIds) pToG.set(pid, gi);
|
|
676
699
|
}
|
|
677
700
|
const LOOSE = -1;
|
|
@@ -1063,7 +1086,11 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
|
|
|
1063
1086
|
for (const region of sectionRegions) {
|
|
1064
1087
|
sectionMsgCounts.set(region.section.lineNumber, region.msgIndices.length);
|
|
1065
1088
|
}
|
|
1089
|
+
const sEdgePad = ctx.aesthetic(20);
|
|
1066
1090
|
const GROUP_PADDING_X = 15;
|
|
1091
|
+
const GROUP_NEST_INSET_X = 6;
|
|
1092
|
+
const GROUP_NEST_MIN_PAD_X = 4;
|
|
1093
|
+
const GROUP_NEST_INSET_Y = 6;
|
|
1067
1094
|
const GROUP_PADDING_TOP = 22;
|
|
1068
1095
|
const GROUP_PADDING_BOTTOM = 8;
|
|
1069
1096
|
const GROUP_LABEL_SIZE = 11;
|
|
@@ -1108,11 +1135,13 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
|
|
|
1108
1135
|
titleBaselineY: ctx.structural(TITLE_Y),
|
|
1109
1136
|
titleFontSize: ctx.text(TITLE_FONT_SIZE)
|
|
1110
1137
|
});
|
|
1111
|
-
const
|
|
1138
|
+
const maxGroupDepth = parsed.groups.reduce((d, g) => Math.max(d, g.depth), 0);
|
|
1139
|
+
const groupOffset = parsed.groups.length > 0 ? (maxGroupDepth + 1) * GROUP_PADDING_TOP + GROUP_LABEL_SIZE : 0;
|
|
1140
|
+
const groupBottomPad = (depth) => GROUP_PADDING_BOTTOM + (maxGroupDepth - depth) * GROUP_NEST_INSET_Y;
|
|
1112
1141
|
const participantStartY = sTopMargin + titleOffset + (header.inline ? 0 : legendTopSpace) + sParticipantYOffset + groupOffset;
|
|
1113
1142
|
const lifelineStartY0 = participantStartY + sBoxH;
|
|
1114
1143
|
const hasActors = participants.some((p) => p.type === "actor");
|
|
1115
|
-
const messageStartOffset = sMsgStartOffset + (hasActors ? 20 : 0) + (parsed.groups.length > 0 ?
|
|
1144
|
+
const messageStartOffset = sMsgStartOffset + (hasActors ? 20 : 0) + (parsed.groups.length > 0 ? groupBottomPad(0) : 0);
|
|
1116
1145
|
const stepYPositions = [];
|
|
1117
1146
|
const sectionYPositions = /* @__PURE__ */ new Map();
|
|
1118
1147
|
let layoutEndY;
|
|
@@ -1219,13 +1248,16 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
|
|
|
1219
1248
|
sWithinGap = sGap * 0.88;
|
|
1220
1249
|
sBetweenGap = (totalGaps * sGap - numWithinGaps * sWithinGap) / numGroupGaps;
|
|
1221
1250
|
}
|
|
1251
|
+
const edgeProjection = (id) => {
|
|
1252
|
+
if (!id) return sBoxW / 2;
|
|
1253
|
+
const framed = parsed.groups.some(
|
|
1254
|
+
(g) => g.participantIds.includes(id)
|
|
1255
|
+
);
|
|
1256
|
+
return framed ? sBoxW / 2 + GROUP_PADDING_X : sBoxW / 2;
|
|
1257
|
+
};
|
|
1222
1258
|
const rightmostId = participants[participants.length - 1]?.id;
|
|
1223
|
-
let rightProjection =
|
|
1259
|
+
let rightProjection = edgeProjection(rightmostId);
|
|
1224
1260
|
if (rightmostId) {
|
|
1225
|
-
if (parsed.groups.some(
|
|
1226
|
-
(g) => g.participantIds.includes(rightmostId)
|
|
1227
|
-
))
|
|
1228
|
-
rightProjection = Math.max(rightProjection, sBoxW / 2 + GROUP_PADDING_X);
|
|
1229
1261
|
for (const step of renderSteps) {
|
|
1230
1262
|
if (step.from === step.to && step.from === rightmostId) {
|
|
1231
1263
|
const selfProj = sActivationWidth + sSelfCallWidth;
|
|
@@ -1253,8 +1285,11 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
|
|
|
1253
1285
|
if (elements && hasBlockWithRightmost(elements))
|
|
1254
1286
|
rightProjection = Math.max(rightProjection, sBoxW / 2 + blockFramePadX);
|
|
1255
1287
|
}
|
|
1256
|
-
let rightMargin = Math.max(rightProjection +
|
|
1257
|
-
let leftMargin =
|
|
1288
|
+
let rightMargin = Math.max(rightProjection + sEdgePad, sGap / 2);
|
|
1289
|
+
let leftMargin = Math.max(
|
|
1290
|
+
edgeProjection(participants[0]?.id) + sEdgePad,
|
|
1291
|
+
sGap / 2
|
|
1292
|
+
);
|
|
1258
1293
|
const diagramWidth = Math.max(0, participants.length - 1) * sGap;
|
|
1259
1294
|
let totalWidth = Math.max(
|
|
1260
1295
|
leftMargin + diagramWidth + rightMargin,
|
|
@@ -1392,6 +1427,7 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
|
|
|
1392
1427
|
collapsedGroupNames.add(group.name);
|
|
1393
1428
|
collapsedGroupMeta.set(group.name, {
|
|
1394
1429
|
lineNumber: group.lineNumber,
|
|
1430
|
+
depth: group.depth,
|
|
1395
1431
|
participantIds: group.participantIds,
|
|
1396
1432
|
...group.metadata !== void 0 && { metadata: group.metadata }
|
|
1397
1433
|
});
|
|
@@ -1414,14 +1450,35 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
|
|
|
1414
1450
|
const hasExpandedGroup = groups.some(
|
|
1415
1451
|
(g) => g.participantIds.some((id) => participantX.has(id))
|
|
1416
1452
|
);
|
|
1417
|
-
|
|
1453
|
+
const framedGroups = [...groups].sort((a, b) => a.depth - b.depth);
|
|
1454
|
+
const allColumnXs = [...participantX.values()].sort((a, b) => a - b);
|
|
1455
|
+
const frameExtents = /* @__PURE__ */ new Map();
|
|
1456
|
+
for (const group of framedGroups) {
|
|
1418
1457
|
if (group.participantIds.length === 0) continue;
|
|
1419
1458
|
const memberXs = group.participantIds.map((id) => participantX.get(id)).filter((x) => x !== void 0);
|
|
1420
1459
|
if (memberXs.length === 0) continue;
|
|
1421
|
-
const
|
|
1422
|
-
const
|
|
1423
|
-
const
|
|
1424
|
-
|
|
1460
|
+
const firstX = Math.min(...memberXs);
|
|
1461
|
+
const lastX = Math.max(...memberXs);
|
|
1462
|
+
const padX = Math.max(
|
|
1463
|
+
GROUP_NEST_MIN_PAD_X,
|
|
1464
|
+
GROUP_PADDING_X - group.depth * GROUP_NEST_INSET_X
|
|
1465
|
+
);
|
|
1466
|
+
let minX = firstX - sBoxW / 2 - padX;
|
|
1467
|
+
let maxX = lastX + sBoxW / 2 + padX;
|
|
1468
|
+
if (group.depth > 0) {
|
|
1469
|
+
const prevX = allColumnXs.filter((x) => x < firstX).pop();
|
|
1470
|
+
const nextX = allColumnXs.find((x) => x > lastX);
|
|
1471
|
+
if (prevX !== void 0) minX = (prevX + firstX) / 2;
|
|
1472
|
+
if (nextX !== void 0) maxX = (lastX + nextX) / 2;
|
|
1473
|
+
const parent = group.parent ? frameExtents.get(group.parent) : void 0;
|
|
1474
|
+
if (parent) {
|
|
1475
|
+
minX = Math.max(minX, parent.minX + GROUP_NEST_MIN_PAD_X);
|
|
1476
|
+
maxX = Math.min(maxX, parent.maxX - GROUP_NEST_MIN_PAD_X);
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
frameExtents.set(group.name, { minX, maxX });
|
|
1480
|
+
const boxY = participantStartY - (maxGroupDepth + 1 - group.depth) * GROUP_PADDING_TOP;
|
|
1481
|
+
const boxH = sBoxH + (participantStartY - boxY) + groupBottomPad(group.depth);
|
|
1425
1482
|
const groupTagValue = tagKey && group.metadata?.[tagKey];
|
|
1426
1483
|
const groupTagColor = getTagColor(groupTagValue || void 0);
|
|
1427
1484
|
const fillColor = groupTagColor ? mix(groupTagColor, themeBaseBg(palette, isDark), isDark ? 15 : 20) : isDark ? palette.surface : palette.bg;
|
|
@@ -1496,8 +1553,8 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
|
|
|
1496
1553
|
const drillColor = effectiveTagColor ?? mix(palette.textMuted, themeBaseBg(palette, isDark), 55);
|
|
1497
1554
|
const drillBarH = ctx.structural(COLLAPSE_BAR_HEIGHT);
|
|
1498
1555
|
const boxW = sBoxW;
|
|
1499
|
-
const padTop = hasExpandedGroup ? GROUP_PADDING_TOP : 0;
|
|
1500
|
-
const padBottom = hasExpandedGroup ?
|
|
1556
|
+
const padTop = hasExpandedGroup ? (maxGroupDepth + 1 - meta.depth) * GROUP_PADDING_TOP : 0;
|
|
1557
|
+
const padBottom = hasExpandedGroup ? groupBottomPad(meta.depth) : 0;
|
|
1501
1558
|
const fullH = sBoxH + padTop + padBottom;
|
|
1502
1559
|
const clipId = `clip-drill-group-${participant.id.replace(/[^a-zA-Z0-9-]/g, "-")}`;
|
|
1503
1560
|
const participantG = svg.select(
|
|
@@ -1515,7 +1572,7 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
|
|
|
1515
1572
|
participantG.append("clipPath").attr("id", clipId).append("rect").attr("x", -boxW / 2).attr("y", -padTop).attr("width", boxW).attr("height", fullH).attr("rx", 6);
|
|
1516
1573
|
participantG.append("rect").attr("class", "sequence-drill-bar").attr("x", -boxW / 2).attr("y", -padTop + fullH - drillBarH).attr("width", boxW).attr("height", drillBarH).attr("fill", drillColor).attr("clip-path", `url(#${clipId})`);
|
|
1517
1574
|
}
|
|
1518
|
-
const llY = isCollapsedGroup ? lifelineStartY + (hasExpandedGroup ?
|
|
1575
|
+
const llY = isCollapsedGroup ? lifelineStartY + (hasExpandedGroup ? groupBottomPad(collapsedGroupMeta.get(participant.id)?.depth ?? 0) : 0) : participant.type === "actor" ? lifelineStartY + ACTOR_LABEL_CLEARANCE : lifelineStartY;
|
|
1519
1576
|
const llColor = effectiveTagColor || palette.textMuted;
|
|
1520
1577
|
for (const [segTop, segBottom] of lifelineSegments(
|
|
1521
1578
|
cx,
|
|
@@ -96,7 +96,7 @@ import {
|
|
|
96
96
|
} from "./chunk-BAZT6CIF.js";
|
|
97
97
|
import {
|
|
98
98
|
parseDgmoChartType
|
|
99
|
-
} from "./chunk-
|
|
99
|
+
} from "./chunk-JVRDKR5R.js";
|
|
100
100
|
import {
|
|
101
101
|
parseRaci
|
|
102
102
|
} from "./chunk-3RYBTEF5.js";
|
|
@@ -114,8 +114,9 @@ import {
|
|
|
114
114
|
toInternal
|
|
115
115
|
} from "./chunk-DAOFNU6J.js";
|
|
116
116
|
import {
|
|
117
|
+
SEQUENCE_DIAGNOSTICS,
|
|
117
118
|
parseSequenceDgmo
|
|
118
|
-
} from "./chunk-
|
|
119
|
+
} from "./chunk-VPASQOR3.js";
|
|
119
120
|
import {
|
|
120
121
|
parseFlowchart
|
|
121
122
|
} from "./chunk-JRUEIRJB.js";
|
|
@@ -1608,6 +1609,7 @@ var REGISTRY = [
|
|
|
1608
1609
|
...PERT_DIAGNOSTICS,
|
|
1609
1610
|
...GRAPH_DIAGNOSTICS,
|
|
1610
1611
|
...COLOR_DIAGNOSTICS,
|
|
1612
|
+
...SEQUENCE_DIAGNOSTICS,
|
|
1611
1613
|
...SKETCH_DIAGNOSTICS,
|
|
1612
1614
|
...FAMILY_DIAGNOSTICS,
|
|
1613
1615
|
...ALIAS_DIAGNOSTICS
|
|
@@ -41,6 +41,22 @@ import {
|
|
|
41
41
|
suggest
|
|
42
42
|
} from "./chunk-BYU54C3S.js";
|
|
43
43
|
|
|
44
|
+
// src/sequence/diagnostics.ts
|
|
45
|
+
var SEQUENCE_DIAGNOSTIC_CODES = {
|
|
46
|
+
GROUP_DEPTH: "E_SEQ_GROUP_DEPTH"
|
|
47
|
+
};
|
|
48
|
+
var SEQUENCE_DIAGNOSTICS = [
|
|
49
|
+
{
|
|
50
|
+
code: SEQUENCE_DIAGNOSTIC_CODES.GROUP_DEPTH,
|
|
51
|
+
severity: "error",
|
|
52
|
+
chartType: "sequence",
|
|
53
|
+
title: "Group nested too deep",
|
|
54
|
+
message: (p) => `Group "${String(p.label ?? "?")}" is nested ${String(p.depth ?? "?")} levels deep \u2014 participant groups nest to depth ${String(p.max ?? "?")}; its participants join the group above it`,
|
|
55
|
+
hint: "Move the inner [Group] up a level \u2014 two levels of bracket is the bound.",
|
|
56
|
+
example: "sequence\n[Monolith]\n [Linux]\n [Container]\n App"
|
|
57
|
+
}
|
|
58
|
+
];
|
|
59
|
+
|
|
44
60
|
// src/sequence/parser.ts
|
|
45
61
|
var KNOWN_SEQ_OPTIONS = /* @__PURE__ */ new Set(["active-tag"]);
|
|
46
62
|
var KNOWN_SEQ_BOOLEANS = /* @__PURE__ */ new Set([
|
|
@@ -70,6 +86,7 @@ function isSequenceNote(el) {
|
|
|
70
86
|
}
|
|
71
87
|
var IS_A_PATTERN = /^([^:]+?)\s+is\s+an?\s+(\w+)(?:\s+(.+))?$/i;
|
|
72
88
|
var COLORED_PARTICIPANT_PATTERN = /^(\S+?)\((red|orange|yellow|green|blue|purple|teal|cyan|gray|black|white)\)\s*$/;
|
|
89
|
+
var MAX_GROUP_DEPTH = 2;
|
|
73
90
|
var GROUP_HEADING_PATTERN = /^\[([^\]|]+?)(?:\(([^)]+)\))?\]\s*(.*)$/;
|
|
74
91
|
var GROUP_HEADING_FALLBACK = /^\[([^\]]+)\]\s*(.*)$/;
|
|
75
92
|
var SECTION_PATTERN = /^==\s+(.+?)(?:\s*==)?\s*$/;
|
|
@@ -218,8 +235,8 @@ function parseSequenceDgmo(content, palette) {
|
|
|
218
235
|
return nameAliasMap.resolve(trimmed) ?? trimmed;
|
|
219
236
|
};
|
|
220
237
|
const fail = makeFail(result);
|
|
221
|
-
const pushError = (line, message) => {
|
|
222
|
-
const diag = makeDgmoError(line, message);
|
|
238
|
+
const pushError = (line, message, code) => {
|
|
239
|
+
const diag = makeDgmoError(line, message, "error", code);
|
|
223
240
|
result.diagnostics.push(diag);
|
|
224
241
|
if (!result.error) result.error = formatDgmoError(diag);
|
|
225
242
|
};
|
|
@@ -249,7 +266,31 @@ function parseSequenceDgmo(content, palette) {
|
|
|
249
266
|
}
|
|
250
267
|
break;
|
|
251
268
|
}
|
|
252
|
-
|
|
269
|
+
const groupStack = [];
|
|
270
|
+
const activeGroup = () => groupStack.length > 0 ? groupStack[groupStack.length - 1].group : null;
|
|
271
|
+
const closeGroupsTo = (indent) => {
|
|
272
|
+
while (groupStack.length > 0 && groupStack[groupStack.length - 1].indent >= indent) {
|
|
273
|
+
groupStack.pop();
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
const joinActiveGroup = (key, id, lineNumber) => {
|
|
277
|
+
const innermost = activeGroup();
|
|
278
|
+
if (!innermost || innermost.participantIds.includes(key)) return;
|
|
279
|
+
const existingGroup = participantGroupMap.get(key);
|
|
280
|
+
if (existingGroup) {
|
|
281
|
+
pushError(
|
|
282
|
+
lineNumber,
|
|
283
|
+
`Participant '${id}' is already in group '${existingGroup}' \u2014 participants can only belong to one group`
|
|
284
|
+
);
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
for (const frame of groupStack) {
|
|
288
|
+
if (!frame.group.participantIds.includes(key)) {
|
|
289
|
+
frame.group.participantIds.push(key);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
participantGroupMap.set(key, innermost.name);
|
|
293
|
+
};
|
|
253
294
|
const participantIds = /* @__PURE__ */ new Set();
|
|
254
295
|
const idByKey = /* @__PURE__ */ new Map();
|
|
255
296
|
const addParticipant = (name, lineNumber, extras) => {
|
|
@@ -364,7 +405,7 @@ function parseSequenceDgmo(content, palette) {
|
|
|
364
405
|
const lineNumber = i + 1;
|
|
365
406
|
nameAliasMap.at(lineNumber);
|
|
366
407
|
if (!trimmed) {
|
|
367
|
-
|
|
408
|
+
closeGroupsTo(0);
|
|
368
409
|
currentTagGroup = null;
|
|
369
410
|
continue;
|
|
370
411
|
}
|
|
@@ -407,14 +448,29 @@ function parseSequenceDgmo(content, palette) {
|
|
|
407
448
|
);
|
|
408
449
|
}
|
|
409
450
|
contentStarted = true;
|
|
410
|
-
|
|
451
|
+
const headingIndent = measureIndent(raw);
|
|
452
|
+
closeGroupsTo(headingIndent);
|
|
453
|
+
const depth = groupStack.length;
|
|
454
|
+
if (depth >= MAX_GROUP_DEPTH) {
|
|
455
|
+
pushError(
|
|
456
|
+
lineNumber,
|
|
457
|
+
`Group '${groupName}' is nested ${String(depth + 1)} levels deep \u2014 participant groups nest to depth ${String(MAX_GROUP_DEPTH)}; its participants join the group above it`,
|
|
458
|
+
SEQUENCE_DIAGNOSTIC_CODES.GROUP_DEPTH
|
|
459
|
+
);
|
|
460
|
+
continue;
|
|
461
|
+
}
|
|
462
|
+
const parentGroup = activeGroup();
|
|
463
|
+
const group = {
|
|
411
464
|
name: groupName,
|
|
412
465
|
participantIds: [],
|
|
413
466
|
lineNumber,
|
|
467
|
+
depth,
|
|
468
|
+
...parentGroup ? { parent: parentGroup.name } : {},
|
|
414
469
|
...groupMeta ? { metadata: groupMeta } : {},
|
|
415
470
|
...isCollapsed ? { collapsed: true } : {}
|
|
416
471
|
};
|
|
417
|
-
result.groups.push(
|
|
472
|
+
result.groups.push(group);
|
|
473
|
+
groupStack.push({ group, indent: headingIndent });
|
|
418
474
|
continue;
|
|
419
475
|
}
|
|
420
476
|
if (trimmed.startsWith("[")) {
|
|
@@ -431,9 +487,7 @@ function parseSequenceDgmo(content, palette) {
|
|
|
431
487
|
continue;
|
|
432
488
|
}
|
|
433
489
|
}
|
|
434
|
-
|
|
435
|
-
activeGroup = null;
|
|
436
|
-
}
|
|
490
|
+
closeGroupsTo(measureIndent(raw));
|
|
437
491
|
if (trimmed.startsWith("//")) continue;
|
|
438
492
|
if (trimmed.startsWith("#")) {
|
|
439
493
|
pushError(lineNumber, "Use // for comments");
|
|
@@ -623,18 +677,7 @@ function parseSequenceDgmo(content, palette) {
|
|
|
623
677
|
...position !== void 0 && { position },
|
|
624
678
|
...isAMeta !== void 0 && { metadata: isAMeta }
|
|
625
679
|
});
|
|
626
|
-
|
|
627
|
-
const existingGroup = participantGroupMap.get(key);
|
|
628
|
-
if (existingGroup) {
|
|
629
|
-
pushError(
|
|
630
|
-
lineNumber,
|
|
631
|
-
`Participant '${id}' is already in group '${existingGroup}' \u2014 participants can only belong to one group`
|
|
632
|
-
);
|
|
633
|
-
} else {
|
|
634
|
-
activeGroup.participantIds.push(key);
|
|
635
|
-
participantGroupMap.set(key, activeGroup.name);
|
|
636
|
-
}
|
|
637
|
-
}
|
|
680
|
+
joinActiveGroup(key, id, lineNumber);
|
|
638
681
|
continue;
|
|
639
682
|
}
|
|
640
683
|
const { core: colorCore, meta: colorMeta } = splitPipe(trimmed, lineNumber);
|
|
@@ -650,18 +693,7 @@ function parseSequenceDgmo(content, palette) {
|
|
|
650
693
|
const key = addParticipant(id, lineNumber, {
|
|
651
694
|
...colorMeta !== void 0 && { metadata: colorMeta }
|
|
652
695
|
});
|
|
653
|
-
|
|
654
|
-
const existingGroup = participantGroupMap.get(key);
|
|
655
|
-
if (existingGroup) {
|
|
656
|
-
pushError(
|
|
657
|
-
lineNumber,
|
|
658
|
-
`Participant '${id}' is already in group '${existingGroup}' \u2014 participants can only belong to one group`
|
|
659
|
-
);
|
|
660
|
-
} else {
|
|
661
|
-
activeGroup.participantIds.push(key);
|
|
662
|
-
participantGroupMap.set(key, activeGroup.name);
|
|
663
|
-
}
|
|
664
|
-
}
|
|
696
|
+
joinActiveGroup(key, id, lineNumber);
|
|
665
697
|
continue;
|
|
666
698
|
}
|
|
667
699
|
{
|
|
@@ -670,7 +702,7 @@ function parseSequenceDgmo(content, palette) {
|
|
|
670
702
|
meta: bareMeta,
|
|
671
703
|
alias: bareAlias
|
|
672
704
|
} = splitPipe(trimmed, lineNumber);
|
|
673
|
-
const inGroup = activeGroup && measureIndent(raw) > 0;
|
|
705
|
+
const inGroup = activeGroup() !== null && measureIndent(raw) > 0;
|
|
674
706
|
if (/^\S+$/.test(bareCore) && !ARROW_PATTERN.test(bareCore) && (inGroup || !bodyStarted || bareMeta)) {
|
|
675
707
|
contentStarted = true;
|
|
676
708
|
const id = bareCore;
|
|
@@ -682,18 +714,7 @@ function parseSequenceDgmo(content, palette) {
|
|
|
682
714
|
...position !== void 0 && { position },
|
|
683
715
|
...bareMeta !== void 0 && { metadata: bareMeta }
|
|
684
716
|
});
|
|
685
|
-
|
|
686
|
-
const existingGroup = participantGroupMap.get(key);
|
|
687
|
-
if (existingGroup) {
|
|
688
|
-
pushError(
|
|
689
|
-
lineNumber,
|
|
690
|
-
`Participant '${id}' is already in group '${existingGroup}' \u2014 participants can only belong to one group`
|
|
691
|
-
);
|
|
692
|
-
} else {
|
|
693
|
-
activeGroup.participantIds.push(key);
|
|
694
|
-
participantGroupMap.set(key, activeGroup.name);
|
|
695
|
-
}
|
|
696
|
-
}
|
|
717
|
+
joinActiveGroup(key, id, lineNumber);
|
|
697
718
|
continue;
|
|
698
719
|
}
|
|
699
720
|
}
|
|
@@ -1066,6 +1087,7 @@ function looksLikeSequence(content) {
|
|
|
1066
1087
|
}
|
|
1067
1088
|
|
|
1068
1089
|
export {
|
|
1090
|
+
SEQUENCE_DIAGNOSTICS,
|
|
1069
1091
|
isSequenceBlock,
|
|
1070
1092
|
isSequenceSection,
|
|
1071
1093
|
isSequenceNote,
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
isExtendedChartType,
|
|
7
7
|
knownChartTypeIds,
|
|
8
8
|
parseDgmo
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-T327J6CE.js";
|
|
10
10
|
import "./chunk-EOYPX6SF.js";
|
|
11
11
|
import "./chunk-WP2RLGDI.js";
|
|
12
12
|
import "./chunk-A2RUBBVT.js";
|
|
@@ -46,14 +46,14 @@ import {
|
|
|
46
46
|
looksLikeC4,
|
|
47
47
|
looksLikeGantt,
|
|
48
48
|
parseDgmoChartType
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-JVRDKR5R.js";
|
|
50
50
|
import "./chunk-3RYBTEF5.js";
|
|
51
51
|
import "./chunk-UNNJCSSQ.js";
|
|
52
52
|
import "./chunk-3TYUXC7D.js";
|
|
53
53
|
import "./chunk-HMWZQ53A.js";
|
|
54
54
|
import "./chunk-EQW6HOP4.js";
|
|
55
55
|
import "./chunk-DAOFNU6J.js";
|
|
56
|
-
import "./chunk-
|
|
56
|
+
import "./chunk-VPASQOR3.js";
|
|
57
57
|
import "./chunk-C3Z4DX3V.js";
|
|
58
58
|
import "./chunk-JRUEIRJB.js";
|
|
59
59
|
import "./chunk-7TF3QOOD.js";
|
package/dist/index.js
CHANGED
|
@@ -11,15 +11,15 @@ import {
|
|
|
11
11
|
} from "./chunk-SQAG3UXH.js";
|
|
12
12
|
import {
|
|
13
13
|
render
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-ADAGWVWJ.js";
|
|
15
15
|
import {
|
|
16
16
|
renderErrorCard
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-OZTDXMRQ.js";
|
|
18
18
|
import {
|
|
19
19
|
getDiagnosticSpec,
|
|
20
20
|
listDiagnosticCodes,
|
|
21
21
|
parseDgmo
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-T327J6CE.js";
|
|
23
23
|
import "./chunk-EOYPX6SF.js";
|
|
24
24
|
import "./chunk-WP2RLGDI.js";
|
|
25
25
|
import "./chunk-A2RUBBVT.js";
|
|
@@ -82,14 +82,14 @@ import {
|
|
|
82
82
|
decodeDiagramUrl,
|
|
83
83
|
encodeDiagramUrl
|
|
84
84
|
} from "./chunk-RE27AX7O.js";
|
|
85
|
-
import "./chunk-
|
|
85
|
+
import "./chunk-JVRDKR5R.js";
|
|
86
86
|
import "./chunk-3RYBTEF5.js";
|
|
87
87
|
import "./chunk-UNNJCSSQ.js";
|
|
88
88
|
import "./chunk-3TYUXC7D.js";
|
|
89
89
|
import "./chunk-HMWZQ53A.js";
|
|
90
90
|
import "./chunk-EQW6HOP4.js";
|
|
91
91
|
import "./chunk-DAOFNU6J.js";
|
|
92
|
-
import "./chunk-
|
|
92
|
+
import "./chunk-VPASQOR3.js";
|
|
93
93
|
import "./chunk-C3Z4DX3V.js";
|
|
94
94
|
import "./chunk-JRUEIRJB.js";
|
|
95
95
|
import "./chunk-7TF3QOOD.js";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
renderLiveLinkCard
|
|
3
3
|
} from "./chunk-A6YINTY6.js";
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
import "./chunk-OZTDXMRQ.js";
|
|
5
|
+
import "./chunk-T327J6CE.js";
|
|
6
6
|
import "./chunk-EOYPX6SF.js";
|
|
7
7
|
import "./chunk-WP2RLGDI.js";
|
|
8
8
|
import "./chunk-A2RUBBVT.js";
|
|
@@ -41,14 +41,14 @@ import "./chunk-GUTZCRBT.js";
|
|
|
41
41
|
import "./chunk-BAZT6CIF.js";
|
|
42
42
|
import "./chunk-KAO7JL4I.js";
|
|
43
43
|
import "./chunk-RE27AX7O.js";
|
|
44
|
-
import "./chunk-
|
|
44
|
+
import "./chunk-JVRDKR5R.js";
|
|
45
45
|
import "./chunk-3RYBTEF5.js";
|
|
46
46
|
import "./chunk-UNNJCSSQ.js";
|
|
47
47
|
import "./chunk-3TYUXC7D.js";
|
|
48
48
|
import "./chunk-HMWZQ53A.js";
|
|
49
49
|
import "./chunk-EQW6HOP4.js";
|
|
50
50
|
import "./chunk-DAOFNU6J.js";
|
|
51
|
-
import "./chunk-
|
|
51
|
+
import "./chunk-VPASQOR3.js";
|
|
52
52
|
import "./chunk-C3Z4DX3V.js";
|
|
53
53
|
import "./chunk-JRUEIRJB.js";
|
|
54
54
|
import "./chunk-7TF3QOOD.js";
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
groupMessagesBySection,
|
|
8
8
|
renderSequenceDiagram,
|
|
9
9
|
summarizeSectionParticipation
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-NJS62BAG.js";
|
|
11
11
|
import "./chunk-WMIKC5XO.js";
|
|
12
12
|
import {
|
|
13
13
|
parseInlineMarkdown,
|
|
@@ -22,7 +22,7 @@ import "./chunk-FM3WAVB6.js";
|
|
|
22
22
|
import "./chunk-ICLB27PZ.js";
|
|
23
23
|
import "./chunk-RH2PROYG.js";
|
|
24
24
|
import "./chunk-KAO7JL4I.js";
|
|
25
|
-
import "./chunk-
|
|
25
|
+
import "./chunk-VPASQOR3.js";
|
|
26
26
|
import "./chunk-C3Z4DX3V.js";
|
|
27
27
|
import "./chunk-N7VMGZCU.js";
|
|
28
28
|
import "./chunk-NOTA6TEI.js";
|
|
@@ -629,6 +629,18 @@ Names that previously inferred to a removed type — `AuthService`, `WebApp`, `C
|
|
|
629
629
|
```
|
|
630
630
|
|
|
631
631
|
- Metadata goes outside brackets: `[Backend] t: Eng`
|
|
632
|
+
- **Groups nest one level deep.** Indent a `[Group]` under another and its members one level deeper again; dedenting rejoins the outer group, so `FanScreen` below belongs to `Monolith`, not to `Linux`. A third level is refused with `E_SEQ_GROUP_DEPTH` and its participants join the group above.
|
|
633
|
+
|
|
634
|
+
```
|
|
635
|
+
[Monolith]
|
|
636
|
+
Camera
|
|
637
|
+
[Linux]
|
|
638
|
+
FacialCapture
|
|
639
|
+
GAEEdgeSW
|
|
640
|
+
FanScreen
|
|
641
|
+
StaffScreen
|
|
642
|
+
```
|
|
643
|
+
|
|
632
644
|
- **Color participants by category with a tag group** (§1.3). Declare the group with named palette colors, then assign each participant `<alias>: <Value>` — the tag is on the participant, not the group line or a message:
|
|
633
645
|
|
|
634
646
|
```
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
sequence Night Signal Chain
|
|
2
|
+
|
|
3
|
+
tag Owner as o
|
|
4
|
+
Crown red
|
|
5
|
+
Guild blue
|
|
6
|
+
|
|
7
|
+
[Flagship] o: Crown
|
|
8
|
+
Lookout
|
|
9
|
+
[Gun Deck] o: Guild
|
|
10
|
+
PowderRoom
|
|
11
|
+
RangeMaster
|
|
12
|
+
Helm
|
|
13
|
+
QuarterMaster
|
|
14
|
+
|
|
15
|
+
[Harbour Watch] o: Crown
|
|
16
|
+
[Watchtower] o: Guild
|
|
17
|
+
BeaconKeeper
|
|
18
|
+
TideGauge
|
|
19
|
+
|
|
20
|
+
[Signal Chain]
|
|
21
|
+
Runner o: Crown
|
|
22
|
+
[Cipher Room] collapsed
|
|
23
|
+
CipherClerk
|
|
24
|
+
CodeBook
|
|
25
|
+
|
|
26
|
+
== Sighting ==
|
|
27
|
+
Lookout -sail on the horizon-> Helm
|
|
28
|
+
Helm -range the target-> RangeMaster
|
|
29
|
+
|
|
30
|
+
note right of RangeMaster
|
|
31
|
+
Bearing and elevation are
|
|
32
|
+
read off the same glass, so
|
|
33
|
+
one clerk owns both numbers
|
|
34
|
+
|
|
35
|
+
RangeMaster -draw two charges-> PowderRoom
|
|
36
|
+
PowderRoom -charges ready-> RangeMaster
|
|
37
|
+
RangeMaster -laid and ready-> QuarterMaster
|
|
38
|
+
|
|
39
|
+
== Raising the Alarm ==
|
|
40
|
+
QuarterMaster -light the beacon-> BeaconKeeper
|
|
41
|
+
BeaconKeeper -read the tide-> TideGauge
|
|
42
|
+
TideGauge -water is making-> BeaconKeeper
|
|
43
|
+
BeaconKeeper -beacon lit-> Runner
|
|
44
|
+
|
|
45
|
+
== Passing the Word ==
|
|
46
|
+
Runner -carry the dispatch-> CipherClerk
|
|
47
|
+
CipherClerk -look up the night code-> CodeBook
|
|
48
|
+
CodeBook -tonight's cipher-> CipherClerk
|
|
49
|
+
CipherClerk -sealed dispatch-> Runner
|
|
50
|
+
Runner -word is away-> QuarterMaster
|