@milehimikey/em 1.4.0 → 1.6.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/.claude/skills/event-modeling/SKILL.md +121 -30
- package/.claude/skills/event-modeling/reference/conform.md +36 -7
- package/.claude/skills/event-modeling/reference/em-dsl.md +210 -48
- package/.claude/skills/event-modeling/reference/extract.md +24 -7
- package/.claude/skills/event-modeling/reference/methodology.md +129 -32
- package/.claude/skills/event-modeling/templates/conformance-report.md +9 -7
- package/.claude/skills/event-modeling/templates/model-readme.md +9 -0
- package/.claude/skills/event-modeling/templates/slice.md +20 -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 +26 -24
- 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 +252 -1
- package/dist/model/validate.js.map +1 -1
- package/dist/parser/ast.d.ts +20 -0
- package/dist/parser/parser.js +158 -29
- package/dist/parser/parser.js.map +1 -1
- package/dist/render/drawEdges.d.ts +3 -1
- package/dist/render/drawEdges.js +119 -7
- package/dist/render/drawEdges.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 +57 -17
- 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 +43 -0
- package/dist/render/svgGeometry.js +69 -3
- 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
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// HTML-string builders for `em catalog`'s static site: an index page and one
|
|
3
|
+
// per-slice detail page. Hand-written template literals, no templating
|
|
4
|
+
// library — same convention as the live-viewer page in
|
|
5
|
+
// src/render/serve.ts's VIEWER_HTML, just as functions instead of one static
|
|
6
|
+
// template, since these pages vary per model/slice.
|
|
7
|
+
import { slicePatternLabel } from "./classify.js";
|
|
8
|
+
export function escapeHtml(s) {
|
|
9
|
+
return s
|
|
10
|
+
.replace(/&/g, "&")
|
|
11
|
+
.replace(/</g, "<")
|
|
12
|
+
.replace(/>/g, ">")
|
|
13
|
+
.replace(/"/g, """)
|
|
14
|
+
.replace(/'/g, "'");
|
|
15
|
+
}
|
|
16
|
+
/** Human-readable status cell: "no doc" (nothing found), "unknown" (doc found, no Status
|
|
17
|
+
* line), or the doc's own Status value verbatim. Shared by the index and slice pages so the
|
|
18
|
+
* two never drift out of sync on how a missing/freeform doc reads. */
|
|
19
|
+
function statusLabel(hasDoc, status) {
|
|
20
|
+
if (!hasDoc)
|
|
21
|
+
return "no doc";
|
|
22
|
+
if (!status)
|
|
23
|
+
return "unknown";
|
|
24
|
+
return status;
|
|
25
|
+
}
|
|
26
|
+
/** MIME type for the diagram `<object>` — must match the actual file `buildCatalog` wrote
|
|
27
|
+
* (`diagram.svg` or `diagram.png`), or the browser won't render it. */
|
|
28
|
+
function diagramMimeType(format) {
|
|
29
|
+
return format === "png" ? "image/png" : "image/svg+xml";
|
|
30
|
+
}
|
|
31
|
+
/** `homeHref` is relative to the page being built (`index.html` from the index page itself,
|
|
32
|
+
* `../../index.html` from a slice page two levels down) so the site works opened straight
|
|
33
|
+
* off disk via `file://`, with no server — an absolute `href="/"` would jump to the
|
|
34
|
+
* filesystem root instead. */
|
|
35
|
+
function layout(title, bodyHtml, homeHref) {
|
|
36
|
+
return `<!doctype html>
|
|
37
|
+
<html lang="en">
|
|
38
|
+
<head>
|
|
39
|
+
<meta charset="utf-8" />
|
|
40
|
+
<title>${escapeHtml(title)}</title>
|
|
41
|
+
<style>
|
|
42
|
+
:root { color-scheme: light dark; }
|
|
43
|
+
body {
|
|
44
|
+
margin: 0; font-family: system-ui, sans-serif; line-height: 1.5;
|
|
45
|
+
background: #fafafa; color: #1f2933;
|
|
46
|
+
}
|
|
47
|
+
header {
|
|
48
|
+
padding: .75rem 1.25rem; background: #1f2933; color: #fff;
|
|
49
|
+
}
|
|
50
|
+
header a { color: #fff; text-decoration: none; }
|
|
51
|
+
main { max-width: 960px; margin: 0 auto; padding: 1.5rem 1.25rem 3rem; }
|
|
52
|
+
table { border-collapse: collapse; width: 100%; margin: 1rem 0; }
|
|
53
|
+
th, td { text-align: left; padding: .4rem .6rem; border-bottom: 1px solid #ddd; font-size: 14px; }
|
|
54
|
+
th { font-weight: 600; background: #f0f2f5; }
|
|
55
|
+
.status { display: inline-block; padding: .1rem .5rem; border-radius: 999px; font-size: 12px; background: #e4e7eb; }
|
|
56
|
+
.pattern { font-size: 12px; color: #52606d; }
|
|
57
|
+
/* Fixed-height frame, not a width-driven one: a slice diagram is often
|
|
58
|
+
narrow and tall relative to the full model's wide/short diagram, so
|
|
59
|
+
sizing by width alone would blow a narrow one's height up hugely.
|
|
60
|
+
object-fit doesn't apply to <object> the way it does <img> (needed here,
|
|
61
|
+
not <img>, so the SVG's clickable note links keep working) — giving it a
|
|
62
|
+
DEFINITE width AND height together stretches it non-uniformly, distorting
|
|
63
|
+
the aspect ratio instead of preserving it. width:auto + height:100% +
|
|
64
|
+
max-width:100% instead sizes it from its own intrinsic aspect ratio
|
|
65
|
+
(capped, never overflowing the frame); the flex centers it horizontally. */
|
|
66
|
+
.diagram-frame {
|
|
67
|
+
height: 420px; border: 1px solid #ddd; margin: 1rem 0; overflow: hidden; background: #fff;
|
|
68
|
+
display: flex; align-items: flex-start; justify-content: center;
|
|
69
|
+
}
|
|
70
|
+
object.diagram { width: auto; height: 100%; max-width: 100%; }
|
|
71
|
+
.full-diagram-link { margin: 0 0 1rem; font-size: 13px; }
|
|
72
|
+
.doc { margin-top: 1.5rem; padding-top: 1rem; border-top: 1px solid #ddd; }
|
|
73
|
+
.doc h1 { font-size: 1.3rem; }
|
|
74
|
+
.doc h2 { font-size: 1.05rem; }
|
|
75
|
+
.no-doc { color: #7b8794; font-style: italic; }
|
|
76
|
+
code { background: #eee; padding: .05rem .3rem; border-radius: 3px; }
|
|
77
|
+
</style>
|
|
78
|
+
</head>
|
|
79
|
+
<body>
|
|
80
|
+
<header><a href="${escapeHtml(homeHref)}">Event Model Catalog</a></header>
|
|
81
|
+
<main>
|
|
82
|
+
${bodyHtml}
|
|
83
|
+
</main>
|
|
84
|
+
</body>
|
|
85
|
+
</html>
|
|
86
|
+
`;
|
|
87
|
+
}
|
|
88
|
+
export function renderIndexPage(models, title, format) {
|
|
89
|
+
const sections = models
|
|
90
|
+
.map((m) => {
|
|
91
|
+
const rows = m.slices
|
|
92
|
+
.map((s) => ` <tr>
|
|
93
|
+
<td><a href="${escapeHtml(m.key)}/slices/${escapeHtml(s.key)}.html">${escapeHtml(s.name)}</a></td>
|
|
94
|
+
<td class="pattern">${escapeHtml(slicePatternLabel(s.pattern))}</td>
|
|
95
|
+
<td><span class="status">${escapeHtml(statusLabel(s.hasDoc, s.status))}</span></td>
|
|
96
|
+
</tr>`)
|
|
97
|
+
.join("\n");
|
|
98
|
+
const diagramHref = `${escapeHtml(m.key)}/${escapeHtml(m.diagramFile)}`;
|
|
99
|
+
return ` <section>
|
|
100
|
+
<h2>${escapeHtml(m.name)}</h2>
|
|
101
|
+
<p>${m.slices.length} slice${m.slices.length === 1 ? "" : "s"} · <code>${escapeHtml(m.file)}</code> · <a href="${diagramHref}">open diagram full-size</a></p>
|
|
102
|
+
<div class="diagram-frame"><object class="diagram" type="${diagramMimeType(format)}" data="${diagramHref}"></object></div>
|
|
103
|
+
<table>
|
|
104
|
+
<thead><tr><th>Slice</th><th>Pattern</th><th>Status</th></tr></thead>
|
|
105
|
+
<tbody>
|
|
106
|
+
${rows}
|
|
107
|
+
</tbody>
|
|
108
|
+
</table>
|
|
109
|
+
</section>`;
|
|
110
|
+
})
|
|
111
|
+
.join("\n");
|
|
112
|
+
return layout(title, ` <h1>${escapeHtml(title)}</h1>
|
|
113
|
+
${sections}`, "index.html");
|
|
114
|
+
}
|
|
115
|
+
function formatFields(el) {
|
|
116
|
+
if (!el.fields || el.fields.length === 0)
|
|
117
|
+
return "";
|
|
118
|
+
return el.fields.map((f) => (f.type ? `${f.name}: ${f.type}` : f.name)).join(", ");
|
|
119
|
+
}
|
|
120
|
+
function elementDetail(el) {
|
|
121
|
+
const parts = [];
|
|
122
|
+
if (el.persona)
|
|
123
|
+
parts.push(`@${el.persona}`);
|
|
124
|
+
if (el.context)
|
|
125
|
+
parts.push(`@${el.context}`);
|
|
126
|
+
if (el.from && el.from.length > 0)
|
|
127
|
+
parts.push(`from ${el.from.join(", ")}`);
|
|
128
|
+
if (el.again)
|
|
129
|
+
parts.push("again");
|
|
130
|
+
if (el.public)
|
|
131
|
+
parts.push("public");
|
|
132
|
+
const fields = formatFields(el);
|
|
133
|
+
if (fields)
|
|
134
|
+
parts.push(`{ ${fields} }`);
|
|
135
|
+
return parts.map(escapeHtml).join(" · ");
|
|
136
|
+
}
|
|
137
|
+
function renderElementsTable(slice, elementRefs) {
|
|
138
|
+
const rows = slice.elements
|
|
139
|
+
.map((el) => {
|
|
140
|
+
const ref = elementRefs.get(el.id);
|
|
141
|
+
const anchor = ref ? ` id="${escapeHtml(ref)}"` : "";
|
|
142
|
+
const annotations = [];
|
|
143
|
+
if (el.issue)
|
|
144
|
+
annotations.push(`<div><span class="status">issue</span> ${escapeHtml(el.issue)}</div>`);
|
|
145
|
+
if (el.divergence)
|
|
146
|
+
annotations.push(`<div><span class="status">divergence</span> ${escapeHtml(el.divergence)}</div>`);
|
|
147
|
+
return ` <tr${anchor}>
|
|
148
|
+
<td>${escapeHtml(el.kind)}</td>
|
|
149
|
+
<td>${escapeHtml(el.name)}</td>
|
|
150
|
+
<td>${elementDetail(el)}${annotations.join("")}</td>
|
|
151
|
+
</tr>`;
|
|
152
|
+
})
|
|
153
|
+
.join("\n");
|
|
154
|
+
return ` <table>
|
|
155
|
+
<thead><tr><th>Kind</th><th>Name</th><th>Detail</th></tr></thead>
|
|
156
|
+
<tbody>
|
|
157
|
+
${rows}
|
|
158
|
+
</tbody>
|
|
159
|
+
</table>`;
|
|
160
|
+
}
|
|
161
|
+
export function renderSlicePage(args) {
|
|
162
|
+
const { modelName, diagramFile, sliceDiagramFile, slice, pattern, elementRefs, doc, docExpectedPath } = args;
|
|
163
|
+
const docSection = doc
|
|
164
|
+
? ` <div class="doc">${doc.html}</div>`
|
|
165
|
+
: ` <p class="no-doc">No slice doc found at <code>${escapeHtml(docExpectedPath)}</code>.</p>`;
|
|
166
|
+
return layout(`${slice.name} — ${modelName}`, ` <p><a href="../../index.html">← ${escapeHtml(modelName)}</a></p>
|
|
167
|
+
<h1>${escapeHtml(slice.name)}</h1>
|
|
168
|
+
<p class="pattern">${escapeHtml(slicePatternLabel(pattern))} · <span class="status">${escapeHtml(statusLabel(!!doc, doc?.status ?? null))}</span></p>
|
|
169
|
+
<div class="diagram-frame"><object class="diagram" type="image/svg+xml" data="${escapeHtml(sliceDiagramFile)}"></object></div>
|
|
170
|
+
<p class="full-diagram-link"><a href="${escapeHtml(diagramFile)}">View full model diagram →</a></p>
|
|
171
|
+
${renderElementsTable(slice, elementRefs)}
|
|
172
|
+
${docSection}`, "../../index.html");
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=pages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pages.js","sourceRoot":"","sources":["../../src/catalog/pages.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface SliceDoc {
|
|
2
|
+
/** The doc's raw markdown, as read from disk. */
|
|
3
|
+
raw: string;
|
|
4
|
+
/** Lowercased value of the doc's `- **Status:** ...` line, or null if no such line is found
|
|
5
|
+
* (a freeform doc that doesn't follow the slice.md template). */
|
|
6
|
+
status: string | null;
|
|
7
|
+
/** The whole doc rendered to HTML. */
|
|
8
|
+
html: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function parseSliceDoc(markdown: string): SliceDoc;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Parses a slice design doc (slices/<slice-name>.md, see
|
|
3
|
+
// .claude/skills/event-modeling/templates/slice.md) for `em catalog`. `em`
|
|
4
|
+
// has never parsed this markdown structurally before — it only checked the
|
|
5
|
+
// file exists (cli.ts's warnMissingNotes). This is deliberately shallow: pull
|
|
6
|
+
// the one bold-label line the index page needs (`- **Status:** ...`) with a
|
|
7
|
+
// regex rather than a full frontmatter parser, and render the whole doc body
|
|
8
|
+
// as HTML for the per-slice detail page. Pure — no fs access; the caller
|
|
9
|
+
// reads the file and hands us its text.
|
|
10
|
+
import { marked } from "marked";
|
|
11
|
+
const STATUS_LINE = /^-\s*\*\*Status:\*\*\s*(.+?)\s*$/im;
|
|
12
|
+
export function parseSliceDoc(markdown) {
|
|
13
|
+
const match = markdown.match(STATUS_LINE);
|
|
14
|
+
return {
|
|
15
|
+
raw: markdown,
|
|
16
|
+
status: match ? match[1].trim().toLowerCase() : null,
|
|
17
|
+
html: marked.parse(markdown, { async: false }),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=sliceDoc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sliceDoc.js","sourceRoot":"","sources":["../../src/catalog/sliceDoc.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,yDAAyD;AACzD,2EAA2E;AAC3E,2EAA2E;AAC3E,8EAA8E;AAC9E,4EAA4E;AAC5E,6EAA6E;AAC7E,yEAAyE;AACzE,wCAAwC;AAExC,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAYhC,MAAM,WAAW,GAAG,oCAAoC,CAAC;AAEzD,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAC1C,OAAO;QACL,GAAG,EAAE,QAAQ;QACb,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI;QACpD,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAW;KACzD,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Resolved `em catalog` flag validation, or a user-facing `error`. */
|
|
2
|
+
export type CatalogPlan = {
|
|
3
|
+
error: string;
|
|
4
|
+
} | {
|
|
5
|
+
ok: true;
|
|
6
|
+
format: "svg" | "png";
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Validate the `em catalog` `--format` flag. Pure — no I/O. Only svg/png are
|
|
10
|
+
* accepted: the per-slice page embeds the diagram in an `<object>`/`<img>`,
|
|
11
|
+
* which needs a format a browser can render directly — pdf (and any other
|
|
12
|
+
* rsvg-convert-only format) is out of scope for a static browsable site.
|
|
13
|
+
*/
|
|
14
|
+
export declare function planCatalogArgs(opts: {
|
|
15
|
+
format?: string;
|
|
16
|
+
}): CatalogPlan;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Testable input handling for `em catalog`: --format validation, factored
|
|
3
|
+
// out of cli.ts so it's unit-testable without spawning a subprocess (mirrors
|
|
4
|
+
// src/cli/glossary-inputs.ts's planGlossaryArgs shape).
|
|
5
|
+
/**
|
|
6
|
+
* Validate the `em catalog` `--format` flag. Pure — no I/O. Only svg/png are
|
|
7
|
+
* accepted: the per-slice page embeds the diagram in an `<object>`/`<img>`,
|
|
8
|
+
* which needs a format a browser can render directly — pdf (and any other
|
|
9
|
+
* rsvg-convert-only format) is out of scope for a static browsable site.
|
|
10
|
+
*/
|
|
11
|
+
export function planCatalogArgs(opts) {
|
|
12
|
+
const format = opts.format ?? "svg";
|
|
13
|
+
if (format !== "svg" && format !== "png") {
|
|
14
|
+
return { error: `em catalog: unsupported --format '${format}' (catalog diagrams support svg or png only)` };
|
|
15
|
+
}
|
|
16
|
+
return { ok: true, format };
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=catalog-inputs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog-inputs.js","sourceRoot":"","sources":["../../src/cli/catalog-inputs.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,0EAA0E;AAC1E,6EAA6E;AAC7E,wDAAwD;AAKxD;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,IAAyB;IACvD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC;IACpC,IAAI,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;QACzC,OAAO,EAAE,KAAK,EAAE,qCAAqC,MAAM,8CAA8C,EAAE,CAAC;IAC9G,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Resolved `em glossary` flag validation, or a user-facing `error`. */
|
|
2
|
+
export type GlossaryPlan = {
|
|
3
|
+
error: string;
|
|
4
|
+
} | {
|
|
5
|
+
ok: true;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Validate the `em glossary` flag combination. Pure — no I/O. `-o` only makes
|
|
9
|
+
* sense alongside `--json`: there's no JSON document to write from the text
|
|
10
|
+
* report, so the combination is a usage error rather than a silent no-op.
|
|
11
|
+
*/
|
|
12
|
+
export declare function planGlossaryArgs(opts: {
|
|
13
|
+
json?: boolean;
|
|
14
|
+
out?: string;
|
|
15
|
+
}): GlossaryPlan;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Testable input handling for `em glossary`: flag-combination validation,
|
|
3
|
+
// factored out of cli.ts so it's unit-testable without spawning a subprocess
|
|
4
|
+
// (cli.ts keeps the process.exit/console wiring; see test/glossary-inputs.test.ts).
|
|
5
|
+
// Mirrors src/cli/diff-inputs.ts's planDiffArgs shape for the same reason.
|
|
6
|
+
/**
|
|
7
|
+
* Validate the `em glossary` flag combination. Pure — no I/O. `-o` only makes
|
|
8
|
+
* sense alongside `--json`: there's no JSON document to write from the text
|
|
9
|
+
* report, so the combination is a usage error rather than a silent no-op.
|
|
10
|
+
*/
|
|
11
|
+
export function planGlossaryArgs(opts) {
|
|
12
|
+
if (opts.out && !opts.json) {
|
|
13
|
+
return { error: "em glossary: -o requires --json (there's no file to write from the text report)" };
|
|
14
|
+
}
|
|
15
|
+
return { ok: true };
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=glossary-inputs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glossary-inputs.js","sourceRoot":"","sources":["../../src/cli/glossary-inputs.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,0EAA0E;AAC1E,6EAA6E;AAC7E,oFAAoF;AACpF,2EAA2E;AAK3E;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAsC;IACrE,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAC3B,OAAO,EAAE,KAAK,EAAE,iFAAiF,EAAE,CAAC;IACtG,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACtB,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Slice } from "../model/model.js";
|
|
2
|
+
export type SliceLookup = {
|
|
3
|
+
index: number;
|
|
4
|
+
} | {
|
|
5
|
+
error: string;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Resolve `--slice <name>` against the compiled model's slices: an exact,
|
|
9
|
+
* case-sensitive match against `Slice.name` — not a fuzzy namespace. On no
|
|
10
|
+
* match, lists every valid slice name in declaration order so a typo is
|
|
11
|
+
* correctable without opening the .em file.
|
|
12
|
+
*
|
|
13
|
+
* Note this is a *different* identity than `em export`/`em catalog`'s
|
|
14
|
+
* deduped `sliceKey` (kebab-slug + `~2`/`~3` suffix for repeated names) —
|
|
15
|
+
* `findIndex` here always returns the *first* slice with a given name, so two
|
|
16
|
+
* identically-named slices can't be disambiguated via `--slice` at all today.
|
|
17
|
+
* Rare in practice (duplicate slice names are themselves a validation
|
|
18
|
+
* warning), and not worth a key-based `--slice` syntax until it's a real
|
|
19
|
+
* complaint — flagging here rather than silently.
|
|
20
|
+
*/
|
|
21
|
+
export declare function resolveSliceArg(name: string, slices: Slice[]): SliceLookup;
|
|
22
|
+
/**
|
|
23
|
+
* Default output path for a slice diagram: slices/<kebab-slug>.svg next to the
|
|
24
|
+
* .em file — the same slices/ + kebabSlug convention em catalog's sibling-file
|
|
25
|
+
* lookup and the event-modeling skill's slice-doc path already use.
|
|
26
|
+
*/
|
|
27
|
+
export declare function defaultSliceOut(file: string, sliceName: string): string;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Testable input handling for `em render --slice`: slice-name resolution and
|
|
3
|
+
// its default output path, factored out of cli.ts so they're unit-testable
|
|
4
|
+
// without spawning a subprocess (mirrors src/cli/catalog-inputs.ts's shape).
|
|
5
|
+
// Unlike planCatalogArgs's pre-file --format check, resolving a slice name
|
|
6
|
+
// needs the compiled model, so this isn't a pre-file plan*Args gate — it's
|
|
7
|
+
// called from the render action after compileFile().
|
|
8
|
+
import { dirname, join } from "node:path";
|
|
9
|
+
import { kebabSlug } from "../util/slug.js";
|
|
10
|
+
/**
|
|
11
|
+
* Resolve `--slice <name>` against the compiled model's slices: an exact,
|
|
12
|
+
* case-sensitive match against `Slice.name` — not a fuzzy namespace. On no
|
|
13
|
+
* match, lists every valid slice name in declaration order so a typo is
|
|
14
|
+
* correctable without opening the .em file.
|
|
15
|
+
*
|
|
16
|
+
* Note this is a *different* identity than `em export`/`em catalog`'s
|
|
17
|
+
* deduped `sliceKey` (kebab-slug + `~2`/`~3` suffix for repeated names) —
|
|
18
|
+
* `findIndex` here always returns the *first* slice with a given name, so two
|
|
19
|
+
* identically-named slices can't be disambiguated via `--slice` at all today.
|
|
20
|
+
* Rare in practice (duplicate slice names are themselves a validation
|
|
21
|
+
* warning), and not worth a key-based `--slice` syntax until it's a real
|
|
22
|
+
* complaint — flagging here rather than silently.
|
|
23
|
+
*/
|
|
24
|
+
export function resolveSliceArg(name, slices) {
|
|
25
|
+
const index = slices.findIndex((s) => s.name === name);
|
|
26
|
+
if (index >= 0)
|
|
27
|
+
return { index };
|
|
28
|
+
const names = slices.map((s) => `"${s.name}"`).join(", ");
|
|
29
|
+
return {
|
|
30
|
+
error: `em render: no slice named "${name}" — valid slices: ${names || "(model has no slices)"}`,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Default output path for a slice diagram: slices/<kebab-slug>.svg next to the
|
|
35
|
+
* .em file — the same slices/ + kebabSlug convention em catalog's sibling-file
|
|
36
|
+
* lookup and the event-modeling skill's slice-doc path already use.
|
|
37
|
+
*/
|
|
38
|
+
export function defaultSliceOut(file, sliceName) {
|
|
39
|
+
return join(dirname(file), "slices", `${kebabSlug(sliceName)}.svg`);
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=render-inputs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-inputs.js","sourceRoot":"","sources":["../../src/cli/render-inputs.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,6EAA6E;AAC7E,2EAA2E;AAC3E,6EAA6E;AAC7E,2EAA2E;AAC3E,2EAA2E;AAC3E,qDAAqD;AAErD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI5C;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,MAAe;IAC3D,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IACvD,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACjC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1D,OAAO;QACL,KAAK,EAAE,8BAA8B,IAAI,qBAAqB,KAAK,IAAI,uBAAuB,EAAE;KACjG,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,SAAiB;IAC7D,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;AACtE,CAAC"}
|