@milehimikey/em 1.5.0 → 1.6.1
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/event-modeling/SKILL.md +62 -17
- package/.claude/skills/event-modeling/reference/conform.md +33 -6
- package/.claude/skills/event-modeling/reference/em-dsl.md +144 -43
- package/.claude/skills/event-modeling/reference/extract.md +12 -2
- package/.claude/skills/event-modeling/reference/methodology.md +34 -14
- package/.claude/skills/event-modeling/templates/conformance-report.md +9 -7
- package/.claude/skills/event-modeling/templates/slice.md +6 -1
- package/.claude/skills/event-modeling/templates/state.md +8 -0
- package/README.md +1 -0
- package/dist/catalog/build.d.ts +33 -0
- package/dist/catalog/build.js +117 -0
- package/dist/catalog/build.js.map +1 -0
- package/dist/catalog/classify.d.ts +14 -0
- package/dist/catalog/classify.js +44 -0
- package/dist/catalog/classify.js.map +1 -0
- package/dist/catalog/pages.d.ts +45 -0
- package/dist/catalog/pages.js +174 -0
- package/dist/catalog/pages.js.map +1 -0
- package/dist/catalog/sliceDoc.d.ts +10 -0
- package/dist/catalog/sliceDoc.js +20 -0
- package/dist/catalog/sliceDoc.js.map +1 -0
- package/dist/cli/catalog-inputs.d.ts +16 -0
- package/dist/cli/catalog-inputs.js +18 -0
- package/dist/cli/catalog-inputs.js.map +1 -0
- package/dist/cli/glossary-inputs.d.ts +15 -0
- package/dist/cli/glossary-inputs.js +17 -0
- package/dist/cli/glossary-inputs.js.map +1 -0
- package/dist/cli/render-inputs.d.ts +27 -0
- package/dist/cli/render-inputs.js +41 -0
- package/dist/cli/render-inputs.js.map +1 -0
- package/dist/cli.js +188 -10
- package/dist/cli.js.map +1 -1
- package/dist/emit/diffJson.d.ts +1 -1
- package/dist/emit/diffJson.js +8 -1
- package/dist/emit/diffJson.js.map +1 -1
- package/dist/emit/dot.d.ts +7 -0
- package/dist/emit/dot.js +10 -4
- package/dist/emit/dot.js.map +1 -1
- package/dist/emit/glossaryJson.d.ts +13 -0
- package/dist/emit/glossaryJson.js +36 -0
- package/dist/emit/glossaryJson.js.map +1 -0
- package/dist/emit/json.d.ts +16 -2
- package/dist/emit/json.js +57 -6
- package/dist/emit/json.js.map +1 -1
- package/dist/emit/theme.d.ts +3 -0
- package/dist/emit/theme.js +19 -0
- package/dist/emit/theme.js.map +1 -1
- package/dist/model/diff.d.ts +36 -1
- package/dist/model/diff.js +198 -35
- package/dist/model/diff.js.map +1 -1
- package/dist/model/edges.d.ts +12 -1
- package/dist/model/edges.js +19 -8
- package/dist/model/edges.js.map +1 -1
- package/dist/model/glossary.d.ts +68 -0
- package/dist/model/glossary.js +138 -0
- package/dist/model/glossary.js.map +1 -0
- package/dist/model/model.d.ts +35 -0
- package/dist/model/model.js +41 -0
- package/dist/model/model.js.map +1 -1
- package/dist/model/validate.js +114 -3
- package/dist/model/validate.js.map +1 -1
- package/dist/parser/ast.d.ts +20 -0
- package/dist/parser/parser.js +170 -31
- package/dist/parser/parser.js.map +1 -1
- package/dist/render/drawNotes.d.ts +7 -3
- package/dist/render/drawNotes.js +75 -28
- package/dist/render/drawNotes.js.map +1 -1
- package/dist/render/render.d.ts +20 -1
- package/dist/render/render.js +52 -14
- package/dist/render/render.js.map +1 -1
- package/dist/render/serve.js +155 -0
- package/dist/render/serve.js.map +1 -1
- package/dist/render/sliceDiagram.d.ts +11 -0
- package/dist/render/sliceDiagram.js +198 -0
- package/dist/render/sliceDiagram.js.map +1 -0
- package/dist/render/sliceOverlay.d.ts +21 -0
- package/dist/render/sliceOverlay.js +111 -0
- package/dist/render/sliceOverlay.js.map +1 -0
- package/dist/render/sliceStatus.d.ts +5 -0
- package/dist/render/sliceStatus.js +26 -0
- package/dist/render/sliceStatus.js.map +1 -0
- package/dist/render/statusOverlay.d.ts +16 -0
- package/dist/render/statusOverlay.js +110 -0
- package/dist/render/statusOverlay.js.map +1 -0
- package/dist/render/svgGeometry.d.ts +30 -0
- package/dist/render/svgGeometry.js +33 -14
- package/dist/render/svgGeometry.js.map +1 -1
- package/dist/render/watch.d.ts +1 -1
- package/dist/render/watch.js +5 -2
- package/dist/render/watch.js.map +1 -1
- package/package.json +3 -2
package/dist/parser/ast.d.ts
CHANGED
|
@@ -20,14 +20,23 @@ export interface ElementNode {
|
|
|
20
20
|
note?: string;
|
|
21
21
|
/** `issue "text"` — an open question, flagged red on the diagram until resolved. */
|
|
22
22
|
issue?: string;
|
|
23
|
+
/** `divergence "text"` — a reasoned, ratified deviation between this element and its
|
|
24
|
+
* implementation. Distinct from `issue`: this is the *resolved* state (lint-suppression-
|
|
25
|
+
* with-rationale for conformance), not an open question. */
|
|
26
|
+
divergence?: string;
|
|
23
27
|
/** Data attributes declared in a `{ … }` block on the element. */
|
|
24
28
|
fields?: Field[];
|
|
25
29
|
/** view-only: a later timeline instance of an already-declared read model. */
|
|
26
30
|
again?: boolean;
|
|
31
|
+
/** `public` — event-only: marks this event as part of the published integration
|
|
32
|
+
* surface, as opposed to an internal-only fact. */
|
|
33
|
+
public?: boolean;
|
|
27
34
|
line: number;
|
|
28
35
|
}
|
|
29
36
|
export interface SliceNode {
|
|
30
37
|
name: string;
|
|
38
|
+
/** `source "url"` — link to the ticket/conversation this slice traces back to. */
|
|
39
|
+
source?: string;
|
|
31
40
|
elements: ElementNode[];
|
|
32
41
|
line: number;
|
|
33
42
|
}
|
|
@@ -36,6 +45,15 @@ export interface ArrowNode {
|
|
|
36
45
|
to: string;
|
|
37
46
|
line: number;
|
|
38
47
|
}
|
|
48
|
+
/** A named, reusable structured type, e.g. `type Money { amount: int, currency: String }`.
|
|
49
|
+
* Declared at top level; referenced from any field's type string elsewhere in the model
|
|
50
|
+
* (bare = nested object, `Name[]` = array of it). Supports no clauses in v1 — just a name
|
|
51
|
+
* and a `{ fields }` block. */
|
|
52
|
+
export interface TypeDeclNode {
|
|
53
|
+
name: string;
|
|
54
|
+
fields: Field[];
|
|
55
|
+
line: number;
|
|
56
|
+
}
|
|
39
57
|
export interface ModelNode {
|
|
40
58
|
name: string;
|
|
41
59
|
/** Declared persona lanes, in order. */
|
|
@@ -45,4 +63,6 @@ export interface ModelNode {
|
|
|
45
63
|
slices: SliceNode[];
|
|
46
64
|
/** Explicit top-level arrows (e.g. read-model feedback to a UI). */
|
|
47
65
|
arrows: ArrowNode[];
|
|
66
|
+
/** Named structured type declarations, in document order. */
|
|
67
|
+
types: TypeDeclNode[];
|
|
48
68
|
}
|
package/dist/parser/parser.js
CHANGED
|
@@ -6,14 +6,16 @@
|
|
|
6
6
|
// model "Name"
|
|
7
7
|
// persona Name
|
|
8
8
|
// context Name
|
|
9
|
-
// slice "Name" {
|
|
9
|
+
// slice "Name" [source "url"] {
|
|
10
10
|
// ui <free text> [@Persona]
|
|
11
11
|
// command <free text>
|
|
12
12
|
// view <free text> [from "Event"[, "Event2" ...]]
|
|
13
|
-
// event <free text> [@Context]
|
|
13
|
+
// event <free text> [@Context] [public]
|
|
14
14
|
// automation|processor|saga|translation <free text>
|
|
15
15
|
// }
|
|
16
16
|
// arrow <From Element> -> <To Element>
|
|
17
|
+
// type "Name" { field: Type, ... }
|
|
18
|
+
import { AUTOMATION_KINDS, } from "./ast.js";
|
|
17
19
|
import { splitQuotedList, stripComment, unquote } from "./lexer.js";
|
|
18
20
|
export class ParseError extends Error {
|
|
19
21
|
line;
|
|
@@ -40,21 +42,46 @@ export function parse(source) {
|
|
|
40
42
|
contexts: [],
|
|
41
43
|
slices: [],
|
|
42
44
|
arrows: [],
|
|
45
|
+
types: [],
|
|
43
46
|
};
|
|
44
47
|
const rawLines = source.split(/\r?\n/);
|
|
45
48
|
let currentSlice = null;
|
|
46
49
|
let currentElement = null; // open `{ … }` field block
|
|
50
|
+
let currentTypeDecl = null; // open `type Name { … }` block
|
|
47
51
|
for (let i = 0; i < rawLines.length; i++) {
|
|
48
52
|
const lineNo = i + 1;
|
|
49
53
|
const line = stripComment(rawLines[i]).trim();
|
|
50
54
|
if (line.length === 0)
|
|
51
55
|
continue;
|
|
52
|
-
// End of a block: an element's field block closes before its slice
|
|
53
|
-
|
|
56
|
+
// End of a block: an element's field block closes before its slice, and a
|
|
57
|
+
// top-level `type` block closes on its own (it has no enclosing container).
|
|
58
|
+
// A multi-line field block's closing line may itself carry trailing
|
|
59
|
+
// clauses, e.g. `} note "slices/x.md"` — extract those before dropping
|
|
60
|
+
// the open element. A `type` block supports no clauses at all, so any
|
|
61
|
+
// trailing text after its `}` is a hard parse error.
|
|
62
|
+
if (line === "}" ||
|
|
63
|
+
(currentElement && line.startsWith("}")) ||
|
|
64
|
+
(currentTypeDecl && line.startsWith("}"))) {
|
|
54
65
|
if (currentElement) {
|
|
66
|
+
const trailing = line.slice(1).trim();
|
|
67
|
+
if (trailing) {
|
|
68
|
+
const leftover = extractClauses(currentElement, trailing, lineNo);
|
|
69
|
+
if (leftover) {
|
|
70
|
+
throw new ParseError(`unrecognized trailing text after '}': '${leftover}'`, lineNo);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
55
73
|
currentElement = null;
|
|
56
74
|
continue;
|
|
57
75
|
}
|
|
76
|
+
if (currentTypeDecl) {
|
|
77
|
+
const trailing = line.slice(1).trim();
|
|
78
|
+
if (trailing) {
|
|
79
|
+
throw new ParseError(`unrecognized trailing text after '}': '${trailing}' (type declarations support no clauses)`, lineNo);
|
|
80
|
+
}
|
|
81
|
+
model.types.push(currentTypeDecl);
|
|
82
|
+
currentTypeDecl = null;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
58
85
|
if (currentSlice) {
|
|
59
86
|
model.slices.push(currentSlice);
|
|
60
87
|
currentSlice = null;
|
|
@@ -64,11 +91,13 @@ export function parse(source) {
|
|
|
64
91
|
}
|
|
65
92
|
// Inside an open field block: each line is a field declaration.
|
|
66
93
|
if (currentElement) {
|
|
67
|
-
for (const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
94
|
+
for (const f of parseInlineFields(line))
|
|
95
|
+
(currentElement.fields ??= []).push(f);
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
// Inside an open `type` block: each line is a field declaration too.
|
|
99
|
+
if (currentTypeDecl) {
|
|
100
|
+
currentTypeDecl.fields.push(...parseInlineFields(line));
|
|
72
101
|
continue;
|
|
73
102
|
}
|
|
74
103
|
const [keyword, ...rest] = splitFirstWord(line);
|
|
@@ -87,13 +116,23 @@ export function parse(source) {
|
|
|
87
116
|
const after = remainder.slice(braceAt + 1);
|
|
88
117
|
const closeAt = after.indexOf("}");
|
|
89
118
|
const inner = closeAt >= 0 ? after.slice(0, closeAt) : after;
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if (f)
|
|
93
|
-
el.fields.push(f);
|
|
94
|
-
}
|
|
95
|
-
if (closeAt < 0)
|
|
119
|
+
el.fields.push(...parseInlineFields(inner));
|
|
120
|
+
if (closeAt < 0) {
|
|
96
121
|
currentElement = el; // block stays open across lines
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
// Clauses may trail the closing brace on the same line, e.g.
|
|
125
|
+
// `event X { a: UUID } issue "..."` — without this, `note`,
|
|
126
|
+
// `issue`, `from`, `@Tag`, and `again` written after an inline
|
|
127
|
+
// fields block were silently discarded (MIL-65, MIL-74).
|
|
128
|
+
const trailing = after.slice(closeAt + 1).trim();
|
|
129
|
+
if (trailing) {
|
|
130
|
+
const leftover = extractClauses(el, trailing, lineNo);
|
|
131
|
+
if (leftover) {
|
|
132
|
+
throw new ParseError(`unrecognized trailing text after '{ … }' block: '${leftover}'`, lineNo);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
97
136
|
continue;
|
|
98
137
|
}
|
|
99
138
|
currentSlice.elements.push(parseElement(keyword, remainder, lineNo));
|
|
@@ -114,15 +153,50 @@ export function parse(source) {
|
|
|
114
153
|
const open = remainder.lastIndexOf("{");
|
|
115
154
|
if (open < 0)
|
|
116
155
|
throw new ParseError("slice must open a block with '{'", lineNo);
|
|
117
|
-
|
|
118
|
-
|
|
156
|
+
let header = remainder.slice(0, open).trim();
|
|
157
|
+
const node = { name: "", elements: [], line: lineNo };
|
|
158
|
+
// `source "url"` clause (valid on any slice, order-independent relative
|
|
159
|
+
// to the name): a link to the ticket/conversation this slice traces
|
|
160
|
+
// back to, so the intake-loop audit chain is machine-traversable
|
|
161
|
+
// through `em export` instead of living only in prose (MIL-69).
|
|
162
|
+
const sourceMatch = header.match(/(?:^|\s)source\s+"([^"]*)"/i);
|
|
163
|
+
if (sourceMatch && sourceMatch.index !== undefined) {
|
|
164
|
+
node.source = sourceMatch[1];
|
|
165
|
+
header = (header.slice(0, sourceMatch.index) + header.slice(sourceMatch.index + sourceMatch[0].length)).trim();
|
|
166
|
+
}
|
|
167
|
+
node.name = unquote(header);
|
|
168
|
+
if (!node.name)
|
|
119
169
|
throw new ParseError("slice requires a name", lineNo);
|
|
120
|
-
currentSlice =
|
|
170
|
+
currentSlice = node;
|
|
121
171
|
break;
|
|
122
172
|
}
|
|
123
173
|
case "arrow":
|
|
124
174
|
model.arrows.push(parseArrow(remainder, lineNo));
|
|
125
175
|
break;
|
|
176
|
+
case "type": {
|
|
177
|
+
const braceAt = remainder.indexOf("{");
|
|
178
|
+
if (braceAt < 0)
|
|
179
|
+
throw new ParseError("type must open a block with '{'", lineNo);
|
|
180
|
+
const name = unquote(remainder.slice(0, braceAt).trim());
|
|
181
|
+
if (!name)
|
|
182
|
+
throw new ParseError("type requires a name", lineNo);
|
|
183
|
+
const decl = { name, fields: [], line: lineNo };
|
|
184
|
+
const after = remainder.slice(braceAt + 1);
|
|
185
|
+
const closeAt = after.indexOf("}");
|
|
186
|
+
const inner = closeAt >= 0 ? after.slice(0, closeAt) : after;
|
|
187
|
+
decl.fields.push(...parseInlineFields(inner));
|
|
188
|
+
if (closeAt < 0) {
|
|
189
|
+
currentTypeDecl = decl; // block stays open across lines
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
const trailing = after.slice(closeAt + 1).trim();
|
|
193
|
+
if (trailing) {
|
|
194
|
+
throw new ParseError(`unrecognized trailing text after '{ … }' block: '${trailing}' (type declarations support no clauses)`, lineNo);
|
|
195
|
+
}
|
|
196
|
+
model.types.push(decl);
|
|
197
|
+
}
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
126
200
|
default:
|
|
127
201
|
throw new ParseError(`unknown keyword '${keyword}'`, lineNo);
|
|
128
202
|
}
|
|
@@ -130,6 +204,9 @@ export function parse(source) {
|
|
|
130
204
|
if (currentElement) {
|
|
131
205
|
throw new ParseError(`field block for "${currentElement.name}" is missing a closing '}'`, currentElement.line);
|
|
132
206
|
}
|
|
207
|
+
if (currentTypeDecl) {
|
|
208
|
+
throw new ParseError(`type "${currentTypeDecl.name}" is missing a closing '}'`, currentTypeDecl.line);
|
|
209
|
+
}
|
|
133
210
|
if (currentSlice) {
|
|
134
211
|
throw new ParseError(`slice "${currentSlice.name}" is missing a closing '}'`, currentSlice.line);
|
|
135
212
|
}
|
|
@@ -138,11 +215,31 @@ export function parse(source) {
|
|
|
138
215
|
return model;
|
|
139
216
|
}
|
|
140
217
|
function parseElement(kind, raw, line) {
|
|
141
|
-
let rest = raw;
|
|
142
218
|
const node = { kind, name: "", line };
|
|
219
|
+
const rest = extractClauses(node, raw, line);
|
|
220
|
+
node.name = unquote(rest);
|
|
221
|
+
if (!node.name)
|
|
222
|
+
throw new ParseError(`${kind} requires a name`, line);
|
|
223
|
+
return node;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Pulls `note`/`issue`/`divergence`/`from`/`public`/`@Tag`/`again` clauses out
|
|
227
|
+
* of `raw`, applying each to `node` and returning whatever text is left (the
|
|
228
|
+
* element's name, when called on the text before a `{ … }` block —
|
|
229
|
+
* otherwise anything unrecognized).
|
|
230
|
+
*
|
|
231
|
+
* Shared by `parseElement` (clauses before an inline field block, or on an
|
|
232
|
+
* element with no field block at all) and the field-block handling in
|
|
233
|
+
* `parse()` (clauses trailing a `{ … }` block's closing `}`, inline or
|
|
234
|
+
* multi-line) — trailing clauses are matched the same way as leading ones so
|
|
235
|
+
* `note`/`issue`/`divergence`/etc. are never silently dropped just because
|
|
236
|
+
* they come after the fields.
|
|
237
|
+
*/
|
|
238
|
+
function extractClauses(node, raw, line) {
|
|
239
|
+
let rest = raw;
|
|
143
240
|
// `note "path.md"` clause (valid on any element). Pulled off first because
|
|
144
241
|
// the `from` clause below greedily consumes to end-of-line.
|
|
145
|
-
const noteMatch = rest.match(
|
|
242
|
+
const noteMatch = rest.match(/(?:^|\s)note\s+"([^"]*)"/i);
|
|
146
243
|
if (noteMatch && noteMatch.index !== undefined) {
|
|
147
244
|
node.note = noteMatch[1];
|
|
148
245
|
rest = (rest.slice(0, noteMatch.index) + rest.slice(noteMatch.index + noteMatch[0].length)).trim();
|
|
@@ -150,24 +247,56 @@ function parseElement(kind, raw, line) {
|
|
|
150
247
|
// `issue "text"` clause (valid on any element): an open question flagged red on
|
|
151
248
|
// the diagram, distinct from `note`'s file link. Extracted the same way, before
|
|
152
249
|
// `from`, for the same reason.
|
|
153
|
-
const issueMatch = rest.match(
|
|
250
|
+
const issueMatch = rest.match(/(?:^|\s)issue\s+"([^"]*)"/i);
|
|
154
251
|
if (issueMatch && issueMatch.index !== undefined) {
|
|
155
252
|
node.issue = issueMatch[1];
|
|
156
253
|
rest = (rest.slice(0, issueMatch.index) + rest.slice(issueMatch.index + issueMatch[0].length)).trim();
|
|
157
254
|
}
|
|
158
|
-
// `
|
|
159
|
-
|
|
255
|
+
// `divergence "text"` clause (valid on any element): a reasoned, ratified
|
|
256
|
+
// deviation between this element and its implementation — the *resolved*
|
|
257
|
+
// sibling of `issue`'s open question. Extracted the same way, before
|
|
258
|
+
// `from`, for the same reason.
|
|
259
|
+
const divergenceMatch = rest.match(/(?:^|\s)divergence\s+"([^"]*)"/i);
|
|
260
|
+
if (divergenceMatch && divergenceMatch.index !== undefined) {
|
|
261
|
+
node.divergence = divergenceMatch[1];
|
|
262
|
+
rest = (rest.slice(0, divergenceMatch.index) + rest.slice(divergenceMatch.index + divergenceMatch[0].length)).trim();
|
|
263
|
+
}
|
|
264
|
+
// `from "A", "B"` clause (views and reactions). The keyword is case-sensitive
|
|
265
|
+
// and its operand must open with a quote, so a capitalized `From` — or a bare
|
|
266
|
+
// lowercase `from` — inside an element name (`event Widget Removed From
|
|
267
|
+
// Cabinet`, `view Requests from partners from "Request Submitted"`) folds
|
|
268
|
+
// into the free-text name instead of being mistaken for the clause.
|
|
269
|
+
const fromMatch = rest.match(/(?:^|\s)from\s+(?=")(.+)$/);
|
|
160
270
|
if (fromMatch && fromMatch.index !== undefined) {
|
|
271
|
+
if (node.kind !== "view" && !AUTOMATION_KINDS.has(node.kind))
|
|
272
|
+
throw new ParseError("`from` is only valid on view or a reaction (automation/processor/saga/translation)", line);
|
|
161
273
|
node.from = splitQuotedList(fromMatch[1]);
|
|
162
274
|
rest = rest.slice(0, fromMatch.index).trim();
|
|
163
275
|
}
|
|
276
|
+
// `public` clause (event only): marks this event as part of the published
|
|
277
|
+
// integration surface (e.g. an AsyncAPI contract), as opposed to an internal-only
|
|
278
|
+
// fact. Checked here, before `@Tag`, so `public` may be written either as the true
|
|
279
|
+
// last token (`event X @Context public`) or immediately before a trailing `@Tag`
|
|
280
|
+
// (`event X public @Context`) — either way `@Context` ends up the trailing-most
|
|
281
|
+
// token once `public` is excised, which is what the `@Tag` block below requires.
|
|
282
|
+
// Anywhere else in the line, a bare `public` is left alone and folds into the free-
|
|
283
|
+
// text name, same as any other unrecognized word (matching `again`'s discipline).
|
|
284
|
+
// Case-sensitive, like the top-level keyword table, so a title-cased `Public`
|
|
285
|
+
// in a name (`event Account Made Public`) is never taken as the marker.
|
|
286
|
+
const publicMatch = rest.match(/(?:^|\s)public(?=\s+@\S+\s*$|\s*$)/);
|
|
287
|
+
if (publicMatch && publicMatch.index !== undefined) {
|
|
288
|
+
if (node.kind !== "event")
|
|
289
|
+
throw new ParseError("`public` is only valid on event — only recorded facts are promoted to the integration surface", line);
|
|
290
|
+
node.public = true;
|
|
291
|
+
rest = (rest.slice(0, publicMatch.index) + rest.slice(publicMatch.index + publicMatch[0].length)).trim();
|
|
292
|
+
}
|
|
164
293
|
// Trailing `@Tag` (persona for ui, context for event).
|
|
165
294
|
const tagMatch = rest.match(/(?:^|\s)@(\S+)\s*$/);
|
|
166
295
|
if (tagMatch && tagMatch.index !== undefined) {
|
|
167
296
|
const tag = tagMatch[1];
|
|
168
|
-
if (kind === "ui")
|
|
297
|
+
if (node.kind === "ui")
|
|
169
298
|
node.persona = tag;
|
|
170
|
-
else if (kind === "event")
|
|
299
|
+
else if (node.kind === "event")
|
|
171
300
|
node.context = tag;
|
|
172
301
|
else
|
|
173
302
|
throw new ParseError(`'@${tag}' tag is only valid on ui (persona) or event (context)`, line);
|
|
@@ -175,17 +304,15 @@ function parseElement(kind, raw, line) {
|
|
|
175
304
|
}
|
|
176
305
|
// Trailing `again` (view only): a later timeline instance of an existing read model —
|
|
177
306
|
// the Event Modeling device for keeping arrows forward as a view evolves.
|
|
178
|
-
|
|
307
|
+
// Case-sensitive for the same reason as `public`: `view Backlog Again` is a name.
|
|
308
|
+
const againMatch = rest.match(/(?:^|\s)again$/);
|
|
179
309
|
if (againMatch && againMatch.index !== undefined) {
|
|
180
|
-
if (kind !== "view")
|
|
310
|
+
if (node.kind !== "view")
|
|
181
311
|
throw new ParseError("`again` is only valid on view — read models are the only elements that reappear along the timeline", line);
|
|
182
312
|
node.again = true;
|
|
183
313
|
rest = rest.slice(0, againMatch.index).trim();
|
|
184
314
|
}
|
|
185
|
-
|
|
186
|
-
if (!node.name)
|
|
187
|
-
throw new ParseError(`${kind} requires a name`, line);
|
|
188
|
-
return node;
|
|
315
|
+
return rest;
|
|
189
316
|
}
|
|
190
317
|
/** Parse one field spec: `name` or `name: Type`. Returns null for blanks. */
|
|
191
318
|
function parseFieldSpec(raw) {
|
|
@@ -201,6 +328,18 @@ function parseFieldSpec(raw) {
|
|
|
201
328
|
const name = unquote(s);
|
|
202
329
|
return name ? { name } : null;
|
|
203
330
|
}
|
|
331
|
+
/** Parse comma-separated field specs from the inner text of a `{ … }` block (or a single
|
|
332
|
+
* line inside an already-open one). Shared by element field blocks and `type` blocks —
|
|
333
|
+
* every field-bearing `{ … }` block in the grammar splits and parses fields the same way. */
|
|
334
|
+
function parseInlineFields(inner) {
|
|
335
|
+
const fields = [];
|
|
336
|
+
for (const spec of inner.split(",")) {
|
|
337
|
+
const f = parseFieldSpec(spec);
|
|
338
|
+
if (f)
|
|
339
|
+
fields.push(f);
|
|
340
|
+
}
|
|
341
|
+
return fields;
|
|
342
|
+
}
|
|
204
343
|
function parseArrow(raw, line) {
|
|
205
344
|
const parts = raw.split("->");
|
|
206
345
|
if (parts.length !== 2)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/parser/parser.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/parser/parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,16 +4,20 @@ import { Rect } from "./svgGeometry.js";
|
|
|
4
4
|
export declare function notedElements(model: NormalizedModel): Element[];
|
|
5
5
|
/** Elements carrying an open issue, in document order. Index + 1 is the footnote number. */
|
|
6
6
|
export declare function issuedElements(model: NormalizedModel): Element[];
|
|
7
|
+
/** Elements carrying an accepted divergence, in document order. Index + 1 is the footnote number. */
|
|
8
|
+
export declare function divergedElements(model: NormalizedModel): Element[];
|
|
7
9
|
/** How to turn an element's note into the link href (default: the raw note path). */
|
|
8
10
|
export type HrefOf = (el: Element) => string;
|
|
9
11
|
/** SVG group with a numbered corner marker per noted element (inside the graph group). */
|
|
10
12
|
export declare function buildNoteMarkers(model: NormalizedModel, rects: Map<string, Rect>, hrefOf?: HrefOf): string;
|
|
11
13
|
/** SVG group with a numbered corner marker per element with an open issue. */
|
|
12
14
|
export declare function buildIssueMarkers(model: NormalizedModel, rects: Map<string, Rect>): string;
|
|
15
|
+
/** SVG group with a numbered corner marker per element with an accepted divergence. */
|
|
16
|
+
export declare function buildDivergenceMarkers(model: NormalizedModel, rects: Map<string, Rect>): string;
|
|
13
17
|
/**
|
|
14
18
|
* Grow the canvas and append a legend below the diagram: a "Notes" section (if any
|
|
15
|
-
* element has a note)
|
|
16
|
-
*
|
|
17
|
-
* parsed.
|
|
19
|
+
* element has a note), an "Issues" section (if any element has an open issue), and an
|
|
20
|
+
* "Accepted Divergences" section (if any element has one). Returns the SVG unchanged
|
|
21
|
+
* if there's nothing to show or the dimensions can't be parsed.
|
|
18
22
|
*/
|
|
19
23
|
export declare function appendNoteLegend(svg: string, model: NormalizedModel, hrefOf?: HrefOf): string;
|
package/dist/render/drawNotes.js
CHANGED
|
@@ -1,21 +1,28 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// Draws "has notes" and "has
|
|
2
|
+
// Draws "has notes", "has issues", and "has an accepted divergence" affordances on top of
|
|
3
|
+
// a Graphviz-rendered SVG:
|
|
3
4
|
// - a small folded-corner (dog-ear) marker per noted box, top-right, amber, carrying
|
|
4
5
|
// a footnote number, linked to the note file;
|
|
5
6
|
// - a small folded-corner marker per element with an open `issue`, top-left, red,
|
|
6
7
|
// carrying its own footnote number — no link (there's nothing to open), just a
|
|
7
8
|
// `<title>` tooltip, since the full text lives in the legend;
|
|
9
|
+
// - a small folded-corner marker per element with a `divergence`, bottom-right, teal,
|
|
10
|
+
// same tooltip-only treatment as `issue` (inline text, no file to link to) — the
|
|
11
|
+
// *resolved* counterpart to issue's red: right side reads "documented" (note,
|
|
12
|
+
// divergence), left reads "open" (issue);
|
|
8
13
|
// - a legend appended below the diagram: a "Notes" section mapping each amber number
|
|
9
|
-
// to its element and note file,
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
14
|
+
// to its element and note file, an "Issues" section mapping each red number to its
|
|
15
|
+
// element and issue text, and an "Accepted Divergences" section mapping each teal
|
|
16
|
+
// number to its element and divergence text — each present only when non-empty.
|
|
17
|
+
// An element may carry a note, an issue, and a divergence all at once: note/issue sit on
|
|
18
|
+
// the top corners, divergence sits at bottom-right, so none of them overlap, and each
|
|
19
|
+
// keeps its own independent numbering (a "1" note, a "1" issue, and a "1" divergence on
|
|
20
|
+
// the same box are unambiguous — distinct color, distinct corner, distinct legend
|
|
21
|
+
// section).
|
|
22
|
+
// In SVG the note markers/rows are anchors (click to open the markdown); issue and
|
|
23
|
+
// divergence markers/rows never are, since inline text has no file to link to. Raster
|
|
24
|
+
// output (PNG/PDF) can't carry links or tooltips either way, so the legend is what tells
|
|
25
|
+
// you which note, issue, or divergence belongs to which element there.
|
|
19
26
|
//
|
|
20
27
|
// Marker coordinates come from parseNodeRects (the box coordinate space, inside
|
|
21
28
|
// Graphviz's transform group). The legend is laid out in the SVG's root/viewBox
|
|
@@ -26,6 +33,8 @@ const FILL = "#F4C430"; // sticky-note amber (notes)
|
|
|
26
33
|
const STROKE = "#7A5200"; // dark amber — reads on light and orange fills alike
|
|
27
34
|
const ISSUE_FILL = "#E53935"; // red sticky (open issues)
|
|
28
35
|
const ISSUE_STROKE = "#8B0000"; // dark red
|
|
36
|
+
const DIVERGENCE_FILL = "#26A69A"; // muted teal (accepted divergences — settled, not open)
|
|
37
|
+
const DIVERGENCE_STROKE = "#00695C"; // dark teal
|
|
29
38
|
/** Elements carrying a note, in document order. Index + 1 is the footnote number. */
|
|
30
39
|
export function notedElements(model) {
|
|
31
40
|
return model.elements.filter((el) => el.note);
|
|
@@ -34,6 +43,10 @@ export function notedElements(model) {
|
|
|
34
43
|
export function issuedElements(model) {
|
|
35
44
|
return model.elements.filter((el) => el.issue);
|
|
36
45
|
}
|
|
46
|
+
/** Elements carrying an accepted divergence, in document order. Index + 1 is the footnote number. */
|
|
47
|
+
export function divergedElements(model) {
|
|
48
|
+
return model.elements.filter((el) => el.divergence);
|
|
49
|
+
}
|
|
37
50
|
const rawNote = (el) => el.note ?? "";
|
|
38
51
|
/** SVG group with a numbered corner marker per noted element (inside the graph group). */
|
|
39
52
|
export function buildNoteMarkers(model, rects, hrefOf = rawNote) {
|
|
@@ -57,15 +70,29 @@ export function buildIssueMarkers(model, rects) {
|
|
|
57
70
|
});
|
|
58
71
|
return `<g class="em-issues">${markers.join("")}</g>`;
|
|
59
72
|
}
|
|
60
|
-
/**
|
|
61
|
-
function
|
|
62
|
-
const
|
|
73
|
+
/** SVG group with a numbered corner marker per element with an accepted divergence. */
|
|
74
|
+
export function buildDivergenceMarkers(model, rects) {
|
|
75
|
+
const markers = [];
|
|
76
|
+
divergedElements(model).forEach((el, i) => {
|
|
77
|
+
const r = rects.get(el.id);
|
|
78
|
+
if (!r)
|
|
79
|
+
return;
|
|
80
|
+
markers.push(divergenceMarker(r, el.divergence ?? "", i + 1));
|
|
81
|
+
});
|
|
82
|
+
return `<g class="em-divergences">${markers.join("")}</g>`;
|
|
83
|
+
}
|
|
84
|
+
/** The dog-ear glyph + footnote number, anchored at one corner of the box. */
|
|
85
|
+
function cornerGlyph(r, num, corner, vAlign, fill, stroke) {
|
|
63
86
|
const x = corner === "right" ? r.right - INSET : r.left + INSET;
|
|
64
87
|
const foldX = corner === "right" ? x - FOLD : x + FOLD;
|
|
65
|
-
|
|
66
|
-
|
|
88
|
+
// y grows downward: a top marker nudges down from the top edge and folds further down;
|
|
89
|
+
// a bottom marker nudges up from the bottom edge and folds further up.
|
|
90
|
+
const y = vAlign === "top" ? r.top + INSET : r.bottom - INSET;
|
|
91
|
+
const foldY = vAlign === "top" ? y + FOLD : y - FOLD;
|
|
92
|
+
const tri = `M${n(foldX)},${n(y)} L${n(x)},${n(y)} L${n(x)},${n(foldY)} Z`;
|
|
93
|
+
const crease = `M${n(foldX)},${n(y)} L${n(x)},${n(foldY)}`;
|
|
67
94
|
const numX = corner === "right" ? foldX - 2 : foldX + 2;
|
|
68
|
-
const numY = y + 9;
|
|
95
|
+
const numY = vAlign === "top" ? y + 9 : y - 5;
|
|
69
96
|
const anchor = corner === "right" ? "end" : "start";
|
|
70
97
|
return (`<path d="${tri}" fill="${fill}" stroke="${stroke}" stroke-width="1" stroke-linejoin="round"/>` +
|
|
71
98
|
`<path d="${crease}" fill="none" stroke="${stroke}" stroke-width="0.7"/>` +
|
|
@@ -77,7 +104,7 @@ function noteMarker(r, note, num) {
|
|
|
77
104
|
const href = esc(note);
|
|
78
105
|
return (`<a xlink:href="${href}" href="${href}" target="_blank">` +
|
|
79
106
|
`<title>${num}. ${href}</title>` +
|
|
80
|
-
cornerGlyph(r, num, "right", FILL, STROKE) +
|
|
107
|
+
cornerGlyph(r, num, "right", "top", FILL, STROKE) +
|
|
81
108
|
`</a>`);
|
|
82
109
|
}
|
|
83
110
|
/**
|
|
@@ -87,7 +114,16 @@ function noteMarker(r, note, num) {
|
|
|
87
114
|
* read the full issue text (tooltips don't survive rasterization either).
|
|
88
115
|
*/
|
|
89
116
|
function issueMarker(r, issue, num) {
|
|
90
|
-
return `<g><title>${num}. ${esc(issue)}</title>${cornerGlyph(r, num, "left", ISSUE_FILL, ISSUE_STROKE)}</g>`;
|
|
117
|
+
return `<g><title>${num}. ${esc(issue)}</title>${cornerGlyph(r, num, "left", "top", ISSUE_FILL, ISSUE_STROKE)}</g>`;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* A folded-corner glyph + footnote number at the box's bottom-right, marking an
|
|
121
|
+
* accepted divergence — the resolved counterpart to `issueMarker`'s open question.
|
|
122
|
+
* Same tooltip-only treatment (no link target); the legend is the reliable read.
|
|
123
|
+
*/
|
|
124
|
+
function divergenceMarker(r, divergence, num) {
|
|
125
|
+
return (`<g><title>${num}. ${esc(divergence)}</title>` +
|
|
126
|
+
`${cornerGlyph(r, num, "right", "bottom", DIVERGENCE_FILL, DIVERGENCE_STROKE)}</g>`);
|
|
91
127
|
}
|
|
92
128
|
// ---- legend ----
|
|
93
129
|
const PAD_X = 16;
|
|
@@ -97,14 +133,15 @@ const LINE_H = 18;
|
|
|
97
133
|
const PAD_BOTTOM = 14;
|
|
98
134
|
/**
|
|
99
135
|
* Grow the canvas and append a legend below the diagram: a "Notes" section (if any
|
|
100
|
-
* element has a note)
|
|
101
|
-
*
|
|
102
|
-
* parsed.
|
|
136
|
+
* element has a note), an "Issues" section (if any element has an open issue), and an
|
|
137
|
+
* "Accepted Divergences" section (if any element has one). Returns the SVG unchanged
|
|
138
|
+
* if there's nothing to show or the dimensions can't be parsed.
|
|
103
139
|
*/
|
|
104
140
|
export function appendNoteLegend(svg, model, hrefOf = rawNote) {
|
|
105
141
|
const noted = notedElements(model);
|
|
106
142
|
const issued = issuedElements(model);
|
|
107
|
-
|
|
143
|
+
const diverged = divergedElements(model);
|
|
144
|
+
if (noted.length === 0 && issued.length === 0 && diverged.length === 0)
|
|
108
145
|
return svg;
|
|
109
146
|
const vb = /viewBox="([\d.eE+-]+)\s+([\d.eE+-]+)\s+([\d.eE+-]+)\s+([\d.eE+-]+)"/.exec(svg);
|
|
110
147
|
const hpt = /height="([\d.eE+-]+)pt"/.exec(svg);
|
|
@@ -116,7 +153,8 @@ export function appendNoteLegend(svg, model, hrefOf = rawNote) {
|
|
|
116
153
|
const vh = +vb[4];
|
|
117
154
|
const notesH = noted.length > 0 ? HEAD_H + noted.length * LINE_H : 0;
|
|
118
155
|
const issuesH = issued.length > 0 ? HEAD_H + issued.length * LINE_H : 0;
|
|
119
|
-
const
|
|
156
|
+
const divergencesH = diverged.length > 0 ? HEAD_H + diverged.length * LINE_H : 0;
|
|
157
|
+
const legendH = PAD_TOP + notesH + issuesH + divergencesH + PAD_BOTTOM;
|
|
120
158
|
const newVh = vh + legendH;
|
|
121
159
|
const newHpt = (+hpt[1]) * (newVh / vh); // keep the pt:viewBox ratio (handles scaling)
|
|
122
160
|
const top = minY + vh; // legend sits just below the diagram, in root coords
|
|
@@ -143,6 +181,15 @@ export function appendNoteLegend(svg, model, hrefOf = rawNote) {
|
|
|
143
181
|
.join("");
|
|
144
182
|
sectionY += issuesH;
|
|
145
183
|
}
|
|
184
|
+
if (diverged.length > 0) {
|
|
185
|
+
sections +=
|
|
186
|
+
`<text x="${n(minX + PAD_X)}" y="${n(sectionY + 14)}" font-family="Helvetica" ` +
|
|
187
|
+
`font-weight="bold" font-size="12" fill="${DIVERGENCE_STROKE}">Accepted Divergences</text>`;
|
|
188
|
+
sections += diverged
|
|
189
|
+
.map((el, i) => row(el, el.divergence ?? "", i + 1, minX + PAD_X, sectionY + HEAD_H + i * LINE_H + 13, "divergence"))
|
|
190
|
+
.join("");
|
|
191
|
+
sectionY += divergencesH;
|
|
192
|
+
}
|
|
146
193
|
const legend = `<g class="em-note-legend">` +
|
|
147
194
|
`<rect x="${n(minX)}" y="${n(top)}" width="${n(vw)}" height="${n(legendH)}" fill="#FFFFFF"/>` +
|
|
148
195
|
`<line x1="${n(minX)}" y1="${n(top)}" x2="${n(minX + vw)}" y2="${n(top)}" stroke="#D0D0D0" stroke-width="1"/>` +
|
|
@@ -152,18 +199,18 @@ export function appendNoteLegend(svg, model, hrefOf = rawNote) {
|
|
|
152
199
|
}
|
|
153
200
|
/**
|
|
154
201
|
* One legend row: "N. Element name — text". Notes rows link to the note file;
|
|
155
|
-
* issue rows carry
|
|
202
|
+
* issue and divergence rows carry their full text and have no link target.
|
|
156
203
|
*/
|
|
157
204
|
function row(el, hrefOrText, num, x, y, kind = "note") {
|
|
158
|
-
const color = kind === "issue" ? ISSUE_STROKE : STROKE;
|
|
159
|
-
const label = esc(kind === "issue" ? el.issue ?? "" : el.note ?? ""); // readable text
|
|
205
|
+
const color = kind === "issue" ? ISSUE_STROKE : kind === "divergence" ? DIVERGENCE_STROKE : STROKE;
|
|
206
|
+
const label = esc(kind === "issue" ? el.issue ?? "" : kind === "divergence" ? el.divergence ?? "" : el.note ?? ""); // readable text
|
|
160
207
|
const name = esc(el.name);
|
|
161
208
|
const text = `<text x="${n(x)}" y="${n(y)}" font-family="Helvetica" font-size="11" fill="#202124">` +
|
|
162
209
|
`<tspan font-weight="bold" fill="${color}">${num}.</tspan>` +
|
|
163
210
|
`<tspan dx="6">${name}</tspan>` +
|
|
164
211
|
`<tspan dx="6" fill="#5F6368">— ${label}</tspan>` +
|
|
165
212
|
`</text>`;
|
|
166
|
-
if (kind === "issue")
|
|
213
|
+
if (kind === "issue" || kind === "divergence")
|
|
167
214
|
return text; // nothing to link to
|
|
168
215
|
const href = esc(hrefOrText); // resolved link target
|
|
169
216
|
return `<a xlink:href="${href}" href="${href}" target="_blank">${text}</a>`;
|