@milehimikey/em 1.7.2 → 1.8.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 +92 -65
- package/.claude/skills/event-modeling/reference/conform.md +45 -20
- package/.claude/skills/event-modeling/reference/em-dsl.md +132 -55
- package/.claude/skills/event-modeling/reference/extract.md +5 -4
- package/.claude/skills/event-modeling/reference/implement.md +34 -22
- package/.claude/skills/event-modeling/templates/model-readme.md +8 -5
- package/.claude/skills/event-modeling/templates/slice.md +19 -5
- package/README.md +6 -4
- package/dist/catalog/docJoin.d.ts +28 -3
- package/dist/catalog/docJoin.js +82 -13
- package/dist/catalog/docJoin.js.map +1 -1
- package/dist/catalog/docModelConsistencyValidate.d.ts +8 -0
- package/dist/catalog/docModelConsistencyValidate.js +335 -0
- package/dist/catalog/docModelConsistencyValidate.js.map +1 -0
- package/dist/catalog/noteBindingValidate.d.ts +8 -0
- package/dist/catalog/noteBindingValidate.js +133 -0
- package/dist/catalog/noteBindingValidate.js.map +1 -0
- package/dist/catalog/pages.js +3 -3
- package/dist/catalog/pages.js.map +1 -1
- package/dist/catalog/sliceDoc.d.ts +14 -0
- package/dist/catalog/sliceDoc.js +22 -0
- package/dist/catalog/sliceDoc.js.map +1 -1
- package/dist/catalog/sliceReadyValidate.d.ts +18 -0
- package/dist/catalog/sliceReadyValidate.js +25 -1
- package/dist/catalog/sliceReadyValidate.js.map +1 -1
- package/dist/cli/agentsMd.d.ts +15 -0
- package/dist/cli/agentsMd.js +72 -0
- package/dist/cli/agentsMd.js.map +1 -0
- package/dist/cli/conformScope.d.ts +86 -0
- package/dist/cli/conformScope.js +156 -0
- package/dist/cli/conformScope.js.map +1 -0
- package/dist/cli/contract.d.ts +7 -0
- package/dist/cli/contract.js +27 -0
- package/dist/cli/contract.js.map +1 -0
- package/dist/cli/coverage.d.ts +71 -0
- package/dist/cli/coverage.js +177 -0
- package/dist/cli/coverage.js.map +1 -0
- package/dist/cli/markImplemented.d.ts +34 -0
- package/dist/cli/markImplemented.js +180 -0
- package/dist/cli/markImplemented.js.map +1 -0
- package/dist/cli/migrateReactionShape.d.ts +62 -0
- package/dist/cli/migrateReactionShape.js +283 -0
- package/dist/cli/migrateReactionShape.js.map +1 -0
- package/dist/cli/sliceIndex.d.ts +49 -0
- package/dist/cli/sliceIndex.js +115 -0
- package/dist/cli/sliceIndex.js.map +1 -0
- package/dist/cli/sliceNew.d.ts +18 -0
- package/dist/cli/sliceNew.js +53 -0
- package/dist/cli/sliceNew.js.map +1 -0
- package/dist/cli/stateFile.d.ts +74 -0
- package/dist/cli/stateFile.js +191 -0
- package/dist/cli/stateFile.js.map +1 -0
- package/dist/cli.js +535 -43
- package/dist/cli.js.map +1 -1
- package/dist/emit/coverageJson.d.ts +8 -0
- package/dist/emit/coverageJson.js +30 -0
- package/dist/emit/coverageJson.js.map +1 -0
- package/dist/emit/diffJson.d.ts +9 -1
- package/dist/emit/diffJson.js +44 -1
- package/dist/emit/diffJson.js.map +1 -1
- package/dist/emit/dot.js +41 -10
- package/dist/emit/dot.js.map +1 -1
- package/dist/emit/json.d.ts +77 -4
- package/dist/emit/json.js +78 -4
- package/dist/emit/json.js.map +1 -1
- package/dist/emit/validateJson.d.ts +52 -0
- package/dist/emit/validateJson.js +120 -0
- package/dist/emit/validateJson.js.map +1 -0
- package/dist/mcp/main.d.ts +2 -0
- package/dist/mcp/main.js +20 -0
- package/dist/mcp/main.js.map +1 -0
- package/dist/mcp/server.d.ts +11 -0
- package/dist/mcp/server.js +260 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/model/model.d.ts +30 -1
- package/dist/model/model.js +26 -0
- package/dist/model/model.js.map +1 -1
- package/dist/model/rules.d.ts +114 -0
- package/dist/model/rules.js +116 -4
- package/dist/model/rules.js.map +1 -1
- package/dist/model/validate.js +92 -8
- package/dist/model/validate.js.map +1 -1
- package/dist/parser/ast.d.ts +47 -0
- package/dist/parser/lexer.d.ts +16 -0
- package/dist/parser/lexer.js +44 -2
- package/dist/parser/lexer.js.map +1 -1
- package/dist/parser/parser.js +354 -20
- package/dist/parser/parser.js.map +1 -1
- package/dist/render/drawNotes.d.ts +11 -1
- package/dist/render/drawNotes.js +28 -3
- package/dist/render/drawNotes.js.map +1 -1
- package/dist/render/render.js +116 -23
- package/dist/render/render.js.map +1 -1
- package/dist/render/serve.d.ts +4 -0
- package/dist/render/serve.js +27 -239
- package/dist/render/serve.js.map +1 -1
- package/dist/render/sliceOverlay.d.ts +7 -2
- package/dist/render/sliceOverlay.js +19 -7
- package/dist/render/sliceOverlay.js.map +1 -1
- package/dist/render/sliceStatus.d.ts +7 -3
- package/dist/render/sliceStatus.js +48 -12
- package/dist/render/sliceStatus.js.map +1 -1
- package/dist/render/viewerHtml.d.ts +1 -0
- package/dist/render/viewerHtml.js +5 -0
- package/dist/render/viewerHtml.js.map +1 -0
- package/dist/render/watch.d.ts +10 -0
- package/dist/render/watch.js +29 -0
- package/dist/render/watch.js.map +1 -1
- package/dist/templates.d.ts +20 -1
- package/dist/templates.js +172 -3
- package/dist/templates.js.map +1 -1
- package/dist/util/markers.d.ts +13 -0
- package/dist/util/markers.js +30 -0
- package/dist/util/markers.js.map +1 -0
- package/dist/util/walkDir.d.ts +10 -1
- package/dist/util/walkDir.js +11 -7
- package/dist/util/walkDir.js.map +1 -1
- package/package.json +12 -3
- package/.claude/skills/event-modeling/templates/live.html +0 -117
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drawNotes.js","sourceRoot":"","sources":["../../src/render/drawNotes.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,0FAA0F;AAC1F,2BAA2B;AAC3B,uFAAuF;AACvF,kDAAkD;AAClD,oFAAoF;AACpF,mFAAmF;AACnF,kEAAkE;AAClE,wFAAwF;AACxF,qFAAqF;AACrF,kFAAkF;AAClF,8CAA8C;AAC9C,uFAAuF;AACvF,uFAAuF;AACvF,sFAAsF;AACtF,oFAAoF;AACpF,yFAAyF;AACzF,sFAAsF;AACtF,wFAAwF;AACxF,kFAAkF;AAClF,YAAY;AACZ,mFAAmF;AACnF,sFAAsF;AACtF,yFAAyF;AACzF,uEAAuE;AACvE,EAAE;AACF,gFAAgF;AAChF,gFAAgF;AAChF,6EAA6E;
|
|
1
|
+
{"version":3,"file":"drawNotes.js","sourceRoot":"","sources":["../../src/render/drawNotes.ts"],"names":[],"mappings":"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"}
|
package/dist/render/render.js
CHANGED
|
@@ -5,18 +5,23 @@
|
|
|
5
5
|
// to SVG; it does NOT route the arrows. We read each box's rectangle back out of
|
|
6
6
|
// that SVG, draw the edges ourselves (straight within a slice, curved across
|
|
7
7
|
// slices) plus the note markers, and inject them. SVG is written directly; PNG
|
|
8
|
-
// is rasterized in-process with resvg
|
|
9
|
-
//
|
|
8
|
+
// is rasterized in-process with resvg; PDF is composed in-process with pdfkit +
|
|
9
|
+
// svg-to-pdfkit (MIL-26 — both pure JS, no native deps, same "self-contained
|
|
10
|
+
// rendering" posture as resvg's PNG path). Any other format (ps, eps, ...) falls
|
|
11
|
+
// back to an optional system `rsvg-convert` if one is installed — genuinely rare
|
|
12
|
+
// formats aren't worth a bespoke in-process path. No system Graphviz is required.
|
|
10
13
|
import { spawn } from "node:child_process";
|
|
11
|
-
import { writeFile } from "node:fs/promises";
|
|
12
|
-
import { dirname, extname, isAbsolute, relative, resolve, sep } from "node:path";
|
|
14
|
+
import { rename, unlink, writeFile } from "node:fs/promises";
|
|
15
|
+
import { dirname, extname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
13
16
|
import { Graphviz } from "@hpcc-js/wasm-graphviz";
|
|
14
17
|
import { Resvg } from "@resvg/resvg-js";
|
|
18
|
+
import PDFDocument from "pdfkit";
|
|
19
|
+
import SVGtoPDF from "svg-to-pdfkit";
|
|
15
20
|
import { fitCanvas, parseNodeRects } from "./svgGeometry.js";
|
|
16
21
|
import { buildEdgeOverlay } from "./drawEdges.js";
|
|
17
22
|
import { buildNoteMarkers, buildIssueMarkers, buildDivergenceMarkers, appendNoteLegend } from "./drawNotes.js";
|
|
18
23
|
import { sliceOverlayIds, tagSliceAttrs, buildSliceOverlay } from "./sliceOverlay.js";
|
|
19
|
-
import {
|
|
24
|
+
import { readSliceDocs } from "./sliceStatus.js";
|
|
20
25
|
import { applyStatusColors, appendStatusLegend } from "./statusOverlay.js";
|
|
21
26
|
const RSVG_BIN = process.env.EM_RSVG || "rsvg-convert";
|
|
22
27
|
// The WASM Graphviz module is loaded once and reused across renders.
|
|
@@ -47,28 +52,95 @@ export async function layoutDot(dot) {
|
|
|
47
52
|
*/
|
|
48
53
|
export function composeSvg(rawSvg, model, grid, baseDir, outDir) {
|
|
49
54
|
const hrefOf = (el) => noteHref(el.note ?? "", baseDir, outDir);
|
|
50
|
-
|
|
51
|
-
|
|
55
|
+
// MIL-153: a doc's own relative asset/link references (e.g. ``, read
|
|
56
|
+
// relative to slices/, the doc's own directory) need the same baseDir->outDir rewrite
|
|
57
|
+
// noteHref gives a `note` path — otherwise an embedded <img src="./foo.svg"> resolves
|
|
58
|
+
// against the live viewer's own page URL instead of slices/, and 404s.
|
|
59
|
+
const docs = readSliceDocs(model, baseDir).map((doc) => doc ? { ...doc, html: rewriteDocLinks(doc.html, baseDir, outDir) } : null);
|
|
60
|
+
return withOverlays(rawSvg, model, grid, hrefOf, docs);
|
|
52
61
|
}
|
|
53
62
|
/** Serialize a composed SVG string to `outPath` in the requested format — split out
|
|
54
63
|
* so a caller can transform the composed string in between composing and writing it. */
|
|
55
64
|
export async function writeRendered(svg, outPath, format = formatFromPath(outPath)) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
65
|
+
// Write to a tmp sibling, then rename over outPath: rename within one directory
|
|
66
|
+
// (same filesystem) is atomic, so a concurrent reader — the live viewer fetching
|
|
67
|
+
// mid-render, an open editor preview — never sees a truncated file. On any
|
|
68
|
+
// failure the tmp is unlinked best-effort so a crashed render leaves no litter.
|
|
69
|
+
// The pid in the tmp name keeps concurrent em processes targeting the same
|
|
70
|
+
// output (an `em watch --serve` plus a one-off `em render`) from promoting
|
|
71
|
+
// each other's half-written bytes; within one process, watch already
|
|
72
|
+
// serializes builds.
|
|
73
|
+
const tmp = `${outPath}.${process.pid}.tmp`;
|
|
74
|
+
try {
|
|
75
|
+
if (format === "svg") {
|
|
76
|
+
await writeFile(tmp, svg, "utf8");
|
|
77
|
+
}
|
|
78
|
+
else if (format === "png") {
|
|
79
|
+
await writeFile(tmp, new Resvg(svg).render().asPng());
|
|
80
|
+
}
|
|
81
|
+
else if (format === "pdf") {
|
|
82
|
+
await writeFile(tmp, await svgToPdfBuffer(svg));
|
|
83
|
+
}
|
|
84
|
+
else if (await hasBin(RSVG_BIN)) {
|
|
85
|
+
// Anything else (ps, eps, …) isn't built in; a system rsvg-convert writes the
|
|
86
|
+
// tmp itself (--format is explicit, so the .tmp extension doesn't mislead it)
|
|
87
|
+
// and the rename below only happens after a clean exit.
|
|
88
|
+
await rsvgConvert(svg, tmp, format);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
throw new Error(`format '${format}' is not built in (svg, png, and pdf are). Install librsvg ` +
|
|
92
|
+
`(provides '${RSVG_BIN}') to render '${format}', or use -o file.svg / -o file.png / -o file.pdf.`);
|
|
93
|
+
}
|
|
94
|
+
await rename(tmp, outPath);
|
|
59
95
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
return;
|
|
96
|
+
catch (e) {
|
|
97
|
+
await unlink(tmp).catch(() => { });
|
|
98
|
+
throw e;
|
|
64
99
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Render a composed SVG string to a PDF buffer, in-process — pdfkit + svg-to-pdfkit,
|
|
103
|
+
* both pure JS, no native deps or system binary (MIL-26). Page size matches the SVG's
|
|
104
|
+
* own viewBox/width/height exactly (Graphviz's "pt" units already map 1:1 to PDF points),
|
|
105
|
+
* so the PDF isn't cropped or rescaled relative to the PNG/SVG siblings of the same render.
|
|
106
|
+
*/
|
|
107
|
+
function svgToPdfBuffer(svg) {
|
|
108
|
+
const { width, height } = svgDimensions(svg);
|
|
109
|
+
const doc = new PDFDocument({ size: [width, height], margin: 0, autoFirstPage: true });
|
|
110
|
+
const chunks = [];
|
|
111
|
+
const done = new Promise((resolve, reject) => {
|
|
112
|
+
doc.on("data", (chunk) => chunks.push(chunk));
|
|
113
|
+
doc.on("end", () => resolve(Buffer.concat(chunks)));
|
|
114
|
+
doc.on("error", reject);
|
|
115
|
+
});
|
|
116
|
+
SVGtoPDF(doc, svg, 0, 0, {
|
|
117
|
+
// Graphviz's own SVG output is in points already — treat px-less numeric
|
|
118
|
+
// coordinates as pt directly instead of applying the library's default
|
|
119
|
+
// 96dpi assumption, or the whole diagram would render at the wrong scale.
|
|
120
|
+
assumePt: true,
|
|
121
|
+
// svg-to-pdfkit's default warningCallback is `console.warn` — anything it can't
|
|
122
|
+
// render (an unsupported feature, a malformed value) would otherwise print
|
|
123
|
+
// straight to the terminal on every `em render -o file.pdf`. Swallow instead:
|
|
124
|
+
// the composed SVG is em's own output, not untrusted input, so a best-effort
|
|
125
|
+
// PDF sibling to the SVG/PNG outputs is the right default, not a build failure
|
|
126
|
+
// or unsolicited console noise over one draw call it couldn't translate.
|
|
127
|
+
warningCallback: () => { },
|
|
128
|
+
});
|
|
129
|
+
doc.end();
|
|
130
|
+
return done;
|
|
131
|
+
}
|
|
132
|
+
/** Pixel/point dimensions of a composed SVG, from its viewBox (falls back to the
|
|
133
|
+
* width/height attributes if viewBox is somehow absent) — same regexes svgGeometry.ts
|
|
134
|
+
* uses for the same attributes, kept local since this is the only pdf-path consumer. */
|
|
135
|
+
function svgDimensions(svg) {
|
|
136
|
+
const vb = /viewBox="[\d.eE+-]+\s+[\d.eE+-]+\s+([\d.eE+-]+)\s+([\d.eE+-]+)"/.exec(svg);
|
|
137
|
+
if (vb)
|
|
138
|
+
return { width: +vb[1], height: +vb[2] };
|
|
139
|
+
const w = /width="([\d.eE+-]+)pt"/.exec(svg);
|
|
140
|
+
const h = /height="([\d.eE+-]+)pt"/.exec(svg);
|
|
141
|
+
if (w && h)
|
|
142
|
+
return { width: +w[1], height: +h[1] };
|
|
143
|
+
throw new Error("svgToPdfBuffer: composed SVG has neither a viewBox nor width/height in pt");
|
|
72
144
|
}
|
|
73
145
|
export async function renderDot(dot, model, grid, outPath, format = formatFromPath(outPath), baseDir = process.cwd()) {
|
|
74
146
|
const outDir = dirname(outPath);
|
|
@@ -89,13 +161,34 @@ export function noteHref(note, baseDir, outDir) {
|
|
|
89
161
|
const rel = relative(outDir, resolve(baseDir, note)) || note;
|
|
90
162
|
return rel.split(sep).join("/"); // posix separators for URLs
|
|
91
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* Rewrite a slice doc's own relative link/asset references (`<img src>`, `<a href>` — e.g.
|
|
166
|
+
* the `` every slice-doc template carries) from being relative to the
|
|
167
|
+
* doc's own directory (`baseDir/slices/`) to being relative to `outDir` — the same job
|
|
168
|
+
* noteHref does for a `note` path, just applied to a whole rendered-HTML doc body instead of
|
|
169
|
+
* one bare string. Without this, an `<img src="./foo.svg">` embedded verbatim in the live
|
|
170
|
+
* viewer resolves against the page's own URL, not `slices/`, and 404s.
|
|
171
|
+
* Fragment-only (`#...`), scheme'd (`http:`, `data:`, `mailto:`, ...), and absolute values
|
|
172
|
+
* pass through untouched, same as noteHref does for those cases.
|
|
173
|
+
*/
|
|
174
|
+
function rewriteDocLinks(html, baseDir, outDir) {
|
|
175
|
+
const docsDir = join(baseDir, "slices");
|
|
176
|
+
return html.replace(/\b(src|href)="([^"]*)"/g, (_m, attr, value) => {
|
|
177
|
+
if (!value || value.startsWith("#") || /^[a-z][a-z0-9+.-]*:/i.test(value) || isAbsolute(value)) {
|
|
178
|
+
return `${attr}="${value}"`;
|
|
179
|
+
}
|
|
180
|
+
const rel = relative(outDir, resolve(docsDir, value)) || value;
|
|
181
|
+
return `${attr}="${rel.split(sep).join("/")}"`;
|
|
182
|
+
});
|
|
183
|
+
}
|
|
92
184
|
/** Draw the semantic edges and note markers into a Graphviz-rendered SVG. */
|
|
93
|
-
function withOverlays(svg, model, grid, hrefOf,
|
|
185
|
+
function withOverlays(svg, model, grid, hrefOf, docs) {
|
|
94
186
|
const rects = parseNodeRects(svg, new Set([...model.byId.keys(), ...sliceOverlayIds(grid)]));
|
|
95
187
|
const { defs, group, bbox } = buildEdgeOverlay(model, rects);
|
|
96
188
|
const notes = buildNoteMarkers(model, rects, hrefOf);
|
|
97
189
|
const issues = buildIssueMarkers(model, rects);
|
|
98
190
|
const divergences = buildDivergenceMarkers(model, rects);
|
|
191
|
+
const statuses = docs.map((doc) => doc?.status ?? null);
|
|
99
192
|
// an edge detour can run outside the box grid Graphviz sized the canvas for, so make
|
|
100
193
|
// room before anything else measures or appends to the viewBox
|
|
101
194
|
let out = fitCanvas(svg, bbox);
|
|
@@ -107,7 +200,7 @@ function withOverlays(svg, model, grid, hrefOf, statuses) {
|
|
|
107
200
|
// viewer (`em watch --serve`) can highlight/zoom to one slice at a time
|
|
108
201
|
// client-side, purely from what's already in the SVG.
|
|
109
202
|
out = tagSliceAttrs(out, model);
|
|
110
|
-
const sliceOverlay = buildSliceOverlay(out, grid, rects);
|
|
203
|
+
const sliceOverlay = buildSliceOverlay(out, grid, rects, docs);
|
|
111
204
|
// arrowhead markers + slice metadata/style go just inside <svg …>
|
|
112
205
|
out = out.replace(/(<svg\b[^>]*>)/, `$1${defs}${sliceOverlay}`);
|
|
113
206
|
// edges go under the boxes: just before the first node group
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/render/render.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,+BAA+B;AAC/B,EAAE;AACF,+EAA+E;AAC/E,iFAAiF;AACjF,6EAA6E;AAC7E,+EAA+E;AAC/E,gFAAgF;AAChF,
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/render/render.ts"],"names":[],"mappings":"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"}
|
package/dist/render/serve.d.ts
CHANGED
|
@@ -5,6 +5,10 @@ export interface LiveServer {
|
|
|
5
5
|
port: number;
|
|
6
6
|
/** Push a reload to every connected browser (call after a successful render). */
|
|
7
7
|
notify: () => void;
|
|
8
|
+
/** Tell every connected browser a save failed to render (parse/render error):
|
|
9
|
+
* the viewer keeps the last good diagram and shows the message in its banner,
|
|
10
|
+
* so a shared screen never silently goes stale. */
|
|
11
|
+
notifyError: (message: string) => void;
|
|
8
12
|
/** Stop the server and drop all SSE connections. */
|
|
9
13
|
close: () => Promise<void>;
|
|
10
14
|
}
|
package/dist/render/serve.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
2
|
// Optional localhost dev server for `em watch --serve`.
|
|
3
3
|
//
|
|
4
|
-
// Serves the model directory over HTTP
|
|
5
|
-
// browser via Server-Sent Events (SSE) after each
|
|
6
|
-
//
|
|
7
|
-
//
|
|
4
|
+
// Serves the model directory over HTTP, the viewer page at `/`, and pushes an
|
|
5
|
+
// instant reload to the browser via Server-Sent Events (SSE) after each
|
|
6
|
+
// successful re-render: no polling, instant updates, and zero idle work
|
|
7
|
+
// between edits.
|
|
8
8
|
//
|
|
9
9
|
// Uses only Node's built-in `http` — no extra dependencies. Binds to
|
|
10
10
|
// 127.0.0.1 (loopback) so the model is never exposed off the machine.
|
|
@@ -12,6 +12,9 @@ import { createServer } from "node:http";
|
|
|
12
12
|
import { createReadStream } from "node:fs";
|
|
13
13
|
import { stat } from "node:fs/promises";
|
|
14
14
|
import { extname, join, relative, resolve, sep } from "node:path";
|
|
15
|
+
// The viewer page ships as a generated constant (source of truth:
|
|
16
|
+
// src/render/viewer.html — see scripts/generate-viewer-html.ts).
|
|
17
|
+
import { VIEWER_HTML } from "./viewerHtml.js";
|
|
15
18
|
const HOST = "127.0.0.1";
|
|
16
19
|
const DEFAULT_PORT = 5173;
|
|
17
20
|
// Number of sequential ports to try if the preferred one is taken.
|
|
@@ -26,6 +29,10 @@ const CONTENT_TYPES = {
|
|
|
26
29
|
".js": "text/javascript; charset=utf-8",
|
|
27
30
|
".json": "application/json; charset=utf-8",
|
|
28
31
|
".pdf": "application/pdf",
|
|
32
|
+
// MIL-153: without this, a note marker's link to a `.md` file falls through to
|
|
33
|
+
// the default application/octet-stream below and the browser downloads it
|
|
34
|
+
// instead of opening it — text/markdown displays it inline like any other text.
|
|
35
|
+
".md": "text/markdown; charset=utf-8",
|
|
29
36
|
};
|
|
30
37
|
/**
|
|
31
38
|
* Start the live server for `dir`. Resolves once it is listening.
|
|
@@ -48,6 +55,12 @@ export async function startLiveServer(opts) {
|
|
|
48
55
|
for (const res of clients)
|
|
49
56
|
res.write("data: reload\n\n");
|
|
50
57
|
},
|
|
58
|
+
notifyError(message) {
|
|
59
|
+
// SSE data must be one line; keep it short — it lands in the viewer banner.
|
|
60
|
+
const line = message.replace(/\s*\r?\n\s*/g, " · ").slice(0, 300);
|
|
61
|
+
for (const res of clients)
|
|
62
|
+
res.write("event: renderError\ndata: " + line + "\n\n");
|
|
63
|
+
},
|
|
51
64
|
async close() {
|
|
52
65
|
clearInterval(keepalive);
|
|
53
66
|
for (const res of clients)
|
|
@@ -83,7 +96,16 @@ function listen(server, port) {
|
|
|
83
96
|
}
|
|
84
97
|
function handle(req, res, root, clients) {
|
|
85
98
|
const url = new URL(req.url ?? "/", "http://localhost");
|
|
86
|
-
|
|
99
|
+
let pathname;
|
|
100
|
+
try {
|
|
101
|
+
pathname = decodeURIComponent(url.pathname);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// A malformed percent-escape must 400, not throw — an uncaught URIError
|
|
105
|
+
// here would take down the watcher and the live view with it.
|
|
106
|
+
res.writeHead(400).end("bad request");
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
87
109
|
if (pathname === "/__events") {
|
|
88
110
|
openEventStream(res, clients);
|
|
89
111
|
return;
|
|
@@ -132,238 +154,4 @@ async function serveStatic(pathname, root, res) {
|
|
|
132
154
|
res.writeHead(404).end("not found");
|
|
133
155
|
}
|
|
134
156
|
}
|
|
135
|
-
// Served viewer page. Same double-buffered, no-flicker swap as the static
|
|
136
|
-
// live.html fallback, but driven by SSE push instead of a poll loop — the
|
|
137
|
-
// browser reloads only when the server says the SVG actually changed.
|
|
138
|
-
//
|
|
139
|
-
// Also carries stakeholder review mode: a Prev/Next storyboard that highlights
|
|
140
|
-
// and pans/zooms to one slice at a time, reading the `data-slice`
|
|
141
|
-
// attributes/`<metadata id="em-slices">` that src/render/sliceOverlay.ts
|
|
142
|
-
// embeds in every rendered SVG. Review-mode state (`reviewMode`/`activeSlice`)
|
|
143
|
-
// deliberately lives outside reload()'s closure and is re-applied after every
|
|
144
|
-
// SSE-triggered swap — a facilitator hand-editing an `issue "..."` clause live
|
|
145
|
-
// during a session should see it appear without losing their place.
|
|
146
|
-
const VIEWER_HTML = `<!doctype html>
|
|
147
|
-
<html lang="en">
|
|
148
|
-
<head>
|
|
149
|
-
<meta charset="utf-8" />
|
|
150
|
-
<title>Event Model — Live</title>
|
|
151
|
-
<style>
|
|
152
|
-
:root { color-scheme: light dark; }
|
|
153
|
-
body { margin: 0; font-family: system-ui, sans-serif; background: #fafafa; }
|
|
154
|
-
header {
|
|
155
|
-
display: flex; align-items: center; gap: .75rem;
|
|
156
|
-
padding: .5rem .9rem; background: #1f2933; color: #fff; font-size: 14px;
|
|
157
|
-
}
|
|
158
|
-
header .dot { width: 9px; height: 9px; border-radius: 50%; background: #34c759; transition: background .3s; }
|
|
159
|
-
header .dot.stale { background: #f0a020; }
|
|
160
|
-
header .stamp { margin-left: auto; opacity: .7; font-variant-numeric: tabular-nums; }
|
|
161
|
-
.btn {
|
|
162
|
-
background: #3b4754; color: #fff; border: 0; border-radius: 4px;
|
|
163
|
-
padding: .3rem .7rem; font-size: 13px; cursor: pointer; font-family: inherit;
|
|
164
|
-
}
|
|
165
|
-
.btn:hover { background: #4b5763; }
|
|
166
|
-
.btn:disabled { opacity: .4; cursor: default; }
|
|
167
|
-
.btn.active { background: #2f6fed; }
|
|
168
|
-
#storyboard {
|
|
169
|
-
display: flex; align-items: center; gap: .5rem; padding: .4rem .9rem;
|
|
170
|
-
background: #e8eaed; border-bottom: 1px solid #d0d3d7;
|
|
171
|
-
}
|
|
172
|
-
#storyboard[hidden] { display: none; }
|
|
173
|
-
#storyboard .nav { background: none; border: 0; font-size: 18px; line-height: 1; cursor: pointer; color: #3b4754; padding: 0 .3rem; }
|
|
174
|
-
#storyboard .nav:disabled { opacity: .3; cursor: default; }
|
|
175
|
-
#filmstrip { display: flex; gap: .35rem; overflow-x: auto; }
|
|
176
|
-
#filmstrip .slice {
|
|
177
|
-
padding: .25rem .6rem; border-radius: 12px; background: #fff; border: 1px solid #d0d3d7;
|
|
178
|
-
font-size: 12px; white-space: nowrap; cursor: pointer; color: #3b4754; font-family: inherit;
|
|
179
|
-
}
|
|
180
|
-
#filmstrip .slice.active { background: #2f6fed; border-color: #2f6fed; color: #fff; font-weight: 600; }
|
|
181
|
-
#stage { padding: 1rem; }
|
|
182
|
-
object { width: 100%; height: calc(100vh - 60px); border: 0; }
|
|
183
|
-
</style>
|
|
184
|
-
</head>
|
|
185
|
-
<body>
|
|
186
|
-
<header>
|
|
187
|
-
<span class="dot" id="dot"></span>
|
|
188
|
-
<span>Event Model — live (push)</span>
|
|
189
|
-
<button class="btn" id="reviewToggle" title="Step through one slice at a time">Review mode</button>
|
|
190
|
-
<span class="stamp" id="stamp">connecting…</span>
|
|
191
|
-
</header>
|
|
192
|
-
<nav id="storyboard" hidden>
|
|
193
|
-
<button class="nav" id="prevSlice" aria-label="Previous slice">‹</button>
|
|
194
|
-
<div id="filmstrip"></div>
|
|
195
|
-
<button class="nav" id="nextSlice" aria-label="Next slice">›</button>
|
|
196
|
-
</nav>
|
|
197
|
-
<div id="stage">
|
|
198
|
-
<object id="svg" type="image/svg+xml"></object>
|
|
199
|
-
</div>
|
|
200
|
-
<script>
|
|
201
|
-
// The SVG filename comes from ?svg=<name>.svg (defaults to model.svg), so one
|
|
202
|
-
// server serves any model without editing this page.
|
|
203
|
-
const SVG_FILE = new URLSearchParams(location.search).get("svg") || "model.svg";
|
|
204
|
-
const stage = document.getElementById("stage");
|
|
205
|
-
const stamp = document.getElementById("stamp");
|
|
206
|
-
const dot = document.getElementById("dot");
|
|
207
|
-
const reviewToggle = document.getElementById("reviewToggle");
|
|
208
|
-
const storyboard = document.getElementById("storyboard");
|
|
209
|
-
const filmstrip = document.getElementById("filmstrip");
|
|
210
|
-
const prevBtn = document.getElementById("prevSlice");
|
|
211
|
-
const nextBtn = document.getElementById("nextSlice");
|
|
212
|
-
let current = document.getElementById("svg");
|
|
213
|
-
|
|
214
|
-
// --- storyboard state: outside reload()'s closure on purpose, see the
|
|
215
|
-
// file-level comment above — an SSE reload must not reset these. ---
|
|
216
|
-
let reviewMode = false;
|
|
217
|
-
let activeSlice = null; // slice index, or null for "show all"
|
|
218
|
-
let slices = []; // [{index, name, x0, x1}], from this load's <metadata>
|
|
219
|
-
let rowLabels = null; // {x0, x1} | null, the swimlane label column's range
|
|
220
|
-
let naturalViewBox = null; // this load's pre-zoom viewBox, cached once per load
|
|
221
|
-
|
|
222
|
-
// Double-buffer: load into a hidden <object>, swap on load, so the shared
|
|
223
|
-
// screen never flashes white during a reload. Keep <object> (not <img>) so
|
|
224
|
-
// note "..." links inside the SVG stay clickable. The buffer must be
|
|
225
|
-
// attached to the document BEFORE data is set — a detached <object> never
|
|
226
|
-
// starts fetching its resource, so its load event would never fire.
|
|
227
|
-
let pending = null; // the in-flight buffer <object>, if a reload is loading
|
|
228
|
-
function reload() {
|
|
229
|
-
dot.classList.add("stale");
|
|
230
|
-
if (pending) pending.remove(); // superseded by this newer reload
|
|
231
|
-
const next = document.createElement("object");
|
|
232
|
-
next.type = "image/svg+xml";
|
|
233
|
-
next.style.cssText = current.style.cssText;
|
|
234
|
-
next.style.position = "absolute"; // out of flow + invisible while loading
|
|
235
|
-
next.style.visibility = "hidden";
|
|
236
|
-
next.addEventListener("load", () => {
|
|
237
|
-
if (pending !== next) return; // a newer reload already replaced this one
|
|
238
|
-
pending = null;
|
|
239
|
-
next.style.position = "";
|
|
240
|
-
next.style.visibility = "";
|
|
241
|
-
stage.removeChild(current);
|
|
242
|
-
current = next;
|
|
243
|
-
stamp.textContent = new Date().toLocaleTimeString();
|
|
244
|
-
dot.classList.remove("stale");
|
|
245
|
-
onSvgLoaded();
|
|
246
|
-
}, { once: true });
|
|
247
|
-
stage.appendChild(next);
|
|
248
|
-
pending = next;
|
|
249
|
-
next.setAttribute("data", SVG_FILE + "?t=" + Date.now());
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
function readSliceMeta(doc) {
|
|
253
|
-
const el = doc.getElementById("em-slices");
|
|
254
|
-
if (!el) return null;
|
|
255
|
-
try { return JSON.parse(el.textContent); } catch { return null; }
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// The currently-loaded SVG's own document + root element, or null before
|
|
259
|
-
// the first load / if the served file isn't a well-formed SVG.
|
|
260
|
-
function currentSvgDoc() {
|
|
261
|
-
const doc = current.contentDocument;
|
|
262
|
-
const svgRoot = doc && doc.querySelector("svg");
|
|
263
|
-
return doc && svgRoot ? { doc, svgRoot } : null;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// Re-read this load's slice metadata + natural viewBox, then reapply
|
|
267
|
-
// whatever storyboard state was already in effect (a fresh SSE push mid-
|
|
268
|
-
// review shouldn't reset the facilitator's position).
|
|
269
|
-
function onSvgLoaded() {
|
|
270
|
-
const loaded = currentSvgDoc();
|
|
271
|
-
if (!loaded) return;
|
|
272
|
-
|
|
273
|
-
naturalViewBox = loaded.svgRoot.getAttribute("viewBox");
|
|
274
|
-
const meta = readSliceMeta(loaded.doc);
|
|
275
|
-
slices = (meta && meta.slices) || [];
|
|
276
|
-
rowLabels = (meta && meta.rowLabels) || null;
|
|
277
|
-
// The model may have changed shape (slice added/removed) between loads.
|
|
278
|
-
if (activeSlice !== null && !slices.some((s) => s.index === activeSlice)) {
|
|
279
|
-
activeSlice = slices.length ? slices[0].index : null;
|
|
280
|
-
}
|
|
281
|
-
render();
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// Apply reviewMode/activeSlice to the currently-loaded SVG + the control bar.
|
|
285
|
-
// Safe to call directly from UI handlers (Prev/Next/toggle/arrow keys) — it
|
|
286
|
-
// never re-reads metadata, just re-applies the cached state.
|
|
287
|
-
function render() {
|
|
288
|
-
storyboard.hidden = slices.length === 0;
|
|
289
|
-
reviewToggle.classList.toggle("active", reviewMode);
|
|
290
|
-
reviewToggle.disabled = slices.length === 0;
|
|
291
|
-
renderFilmstrip();
|
|
292
|
-
|
|
293
|
-
const loaded = currentSvgDoc();
|
|
294
|
-
if (!loaded) return;
|
|
295
|
-
const { doc, svgRoot } = loaded;
|
|
296
|
-
|
|
297
|
-
doc.querySelectorAll("[data-slice]").forEach((node) => {
|
|
298
|
-
const dim = reviewMode && activeSlice !== null &&
|
|
299
|
-
Number(node.getAttribute("data-slice")) !== activeSlice;
|
|
300
|
-
node.classList.toggle("em-slice-dim", dim);
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
if (!naturalViewBox) return;
|
|
304
|
-
if (!reviewMode || activeSlice === null) {
|
|
305
|
-
svgRoot.setAttribute("viewBox", naturalViewBox);
|
|
306
|
-
return;
|
|
307
|
-
}
|
|
308
|
-
const slice = slices.find((s) => s.index === activeSlice);
|
|
309
|
-
if (!slice) return;
|
|
310
|
-
const [nx, ny, nw, nh] = naturalViewBox.split(/\\s+/).map(Number);
|
|
311
|
-
const PAD = 24; // breathing room around the framed slice
|
|
312
|
-
let x0 = rowLabels ? Math.min(rowLabels.x0, slice.x0) : slice.x0;
|
|
313
|
-
let x1 = slice.x1;
|
|
314
|
-
x0 = Math.max(nx, x0 - PAD);
|
|
315
|
-
x1 = Math.min(nx + nw, x1 + PAD);
|
|
316
|
-
svgRoot.setAttribute("viewBox", x0 + " " + ny + " " + Math.max(1, x1 - x0) + " " + nh);
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
function renderFilmstrip() {
|
|
320
|
-
filmstrip.innerHTML = "";
|
|
321
|
-
for (const s of slices) {
|
|
322
|
-
const b = document.createElement("button");
|
|
323
|
-
b.className = "slice" + (s.index === activeSlice ? " active" : "");
|
|
324
|
-
b.textContent = s.name;
|
|
325
|
-
b.addEventListener("click", () => goTo(s.index));
|
|
326
|
-
filmstrip.appendChild(b);
|
|
327
|
-
}
|
|
328
|
-
const first = slices[0], last = slices[slices.length - 1];
|
|
329
|
-
prevBtn.disabled = activeSlice === null || !first || activeSlice <= first.index;
|
|
330
|
-
nextBtn.disabled = activeSlice === null || !last || activeSlice >= last.index;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
function goTo(index) {
|
|
334
|
-
activeSlice = index;
|
|
335
|
-
render();
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
function step(delta) {
|
|
339
|
-
if (!slices.length) return;
|
|
340
|
-
if (activeSlice === null) { goTo(slices[0].index); return; }
|
|
341
|
-
const i = slices.findIndex((s) => s.index === activeSlice);
|
|
342
|
-
const next = slices[Math.min(slices.length - 1, Math.max(0, i + delta))];
|
|
343
|
-
if (next) goTo(next.index);
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
reviewToggle.addEventListener("click", () => {
|
|
347
|
-
reviewMode = !reviewMode;
|
|
348
|
-
if (reviewMode && activeSlice === null && slices.length) activeSlice = slices[0].index;
|
|
349
|
-
render();
|
|
350
|
-
});
|
|
351
|
-
prevBtn.addEventListener("click", () => step(-1));
|
|
352
|
-
nextBtn.addEventListener("click", () => step(1));
|
|
353
|
-
document.addEventListener("keydown", (e) => {
|
|
354
|
-
if (!reviewMode) return;
|
|
355
|
-
if (e.key === "ArrowLeft") step(-1);
|
|
356
|
-
else if (e.key === "ArrowRight") step(1);
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
reload();
|
|
360
|
-
|
|
361
|
-
const es = new EventSource("/__events");
|
|
362
|
-
es.onopen = () => { stamp.textContent = new Date().toLocaleTimeString(); };
|
|
363
|
-
es.onmessage = reload;
|
|
364
|
-
es.onerror = () => { dot.classList.add("stale"); };
|
|
365
|
-
</script>
|
|
366
|
-
</body>
|
|
367
|
-
</html>
|
|
368
|
-
`;
|
|
369
157
|
//# sourceMappingURL=serve.js.map
|
package/dist/render/serve.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../../src/render/serve.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,wDAAwD;AACxD,EAAE;AACF,
|
|
1
|
+
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../../src/render/serve.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { NormalizedModel } from "../model/model.js";
|
|
2
2
|
import { Grid } from "../layout/grid.js";
|
|
3
|
+
import { SliceDoc } from "../catalog/sliceDoc.js";
|
|
3
4
|
import { Rect } from "./svgGeometry.js";
|
|
4
5
|
/** Every non-element node id the slice overlay needs a rect for (header cells),
|
|
5
6
|
* to fold into the same parseNodeRects() call as element ids. */
|
|
@@ -17,5 +18,9 @@ export declare function tagSliceAttrs(svg: string, model: NormalizedModel): stri
|
|
|
17
18
|
* `<g class="graph" transform="scale(...) translate(...)">` wrapper — not the root
|
|
18
19
|
* SVG/viewBox space the served viewer sets `viewBox` in. Every x0/x1 here goes
|
|
19
20
|
* through readGraphTransform()'s toRoot() before it's embedded, the same
|
|
20
|
-
* conversion fitCanvas() applies to the edge-detour bbox for the same reason.
|
|
21
|
-
|
|
21
|
+
* conversion fitCanvas() applies to the edge-detour bbox for the same reason.
|
|
22
|
+
*
|
|
23
|
+
* `docs` is each slice's resolved doc (or null), same order as `grid`'s columns —
|
|
24
|
+
* see render/sliceStatus.ts's `readSliceDocs`, the same resolution that colors the
|
|
25
|
+
* slice's header by status. */
|
|
26
|
+
export declare function buildSliceOverlay(svg: string, grid: Grid, rects: Map<string, Rect>, docs: (SliceDoc | null)[]): string;
|