@markdy/cli 0.7.28 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -3
- package/dist/index.js +143 -209
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DiagramAST } from '@markdy/core';
|
|
2
2
|
import { Server } from 'node:http';
|
|
3
3
|
|
|
4
4
|
interface CliIo {
|
|
@@ -15,8 +15,7 @@ interface RunResult {
|
|
|
15
15
|
type LoadedScene = {
|
|
16
16
|
filePath: string;
|
|
17
17
|
source: string;
|
|
18
|
-
ast:
|
|
19
|
-
imports: Record<string, SceneAST>;
|
|
18
|
+
ast: DiagramAST;
|
|
20
19
|
};
|
|
21
20
|
declare function runCli(argv: string[], io?: CliIo, runtime?: CliRuntime): Promise<RunResult>;
|
|
22
21
|
declare function buildStandaloneHtml(scene: LoadedScene): Promise<string>;
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import {
|
|
5
|
-
import { systemsPack } from "@markdy/stdlib-systems";
|
|
4
|
+
import { parse } from "@markdy/core";
|
|
6
5
|
import { createRequire } from "module";
|
|
7
6
|
import { basename, dirname, extname, join, resolve, sep } from "path";
|
|
8
7
|
import { fileURLToPath, pathToFileURL } from "url";
|
|
@@ -11,152 +10,126 @@ import { readdir, readFile, stat, writeFile } from "fs/promises";
|
|
|
11
10
|
import { spawn } from "child_process";
|
|
12
11
|
|
|
13
12
|
// src/format.ts
|
|
14
|
-
var BARE_TOKEN_RE = /^[\p{L}\p{N}_.$#/+:-]+$/u;
|
|
15
|
-
var MODIFIER_KEYS = ["scale", "rotate", "opacity", "size", "z"];
|
|
16
13
|
function formatScene(ast) {
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
if (ast.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
return `${sections.filter(Boolean).join("\n\n")}
|
|
49
|
-
`;
|
|
50
|
-
}
|
|
51
|
-
function formatSceneHeader(ast) {
|
|
52
|
-
const parts = [
|
|
53
|
-
`scene width=${formatNumber(ast.meta.width)}`,
|
|
54
|
-
`height=${formatNumber(ast.meta.height)}`,
|
|
55
|
-
`fps=${formatNumber(ast.meta.fps)}`,
|
|
56
|
-
`bg=${ast.meta.bg}`
|
|
57
|
-
];
|
|
58
|
-
if (ast.meta.duration !== void 0) {
|
|
59
|
-
parts.push(`duration=${formatNumber(ast.meta.duration)}`);
|
|
60
|
-
}
|
|
61
|
-
return parts.join(" ");
|
|
62
|
-
}
|
|
63
|
-
function formatImportDecl(decl) {
|
|
64
|
-
return `import ${JSON.stringify(decl.path)} as ${decl.namespace}`;
|
|
65
|
-
}
|
|
66
|
-
function formatActorDecl(name, actor) {
|
|
67
|
-
const ctor = `${actor.type}(${actor.args.map(formatToken).join(", ")})`;
|
|
68
|
-
const position = actor.anchor ? `at ${actor.anchor}` : `at (${formatNumber(actor.x)}, ${formatNumber(actor.y)})`;
|
|
69
|
-
const modifiers = MODIFIER_KEYS.flatMap((key) => {
|
|
70
|
-
const value = actor[key];
|
|
71
|
-
return value === void 0 ? [] : [`${key}=${formatNumber(value)}`];
|
|
72
|
-
}).join(", ");
|
|
73
|
-
return modifiers.length > 0 ? `actor ${name} = ${ctor} ${position} with ${modifiers}` : `actor ${name} = ${ctor} ${position}`;
|
|
74
|
-
}
|
|
75
|
-
function formatTemplateDef(name, def) {
|
|
76
|
-
const args = def.bodyArgs.map(formatTemplateArg).join(", ");
|
|
77
|
-
return `def ${name}(${def.params.join(", ")}) {
|
|
78
|
-
${def.actorType}(${args})
|
|
79
|
-
}`;
|
|
80
|
-
}
|
|
81
|
-
function formatTemplateArg(arg) {
|
|
82
|
-
return arg.startsWith("${") && arg.endsWith("}") ? arg : formatToken(arg);
|
|
83
|
-
}
|
|
84
|
-
function formatSequenceDef(name, seq) {
|
|
85
|
-
const lines = seq.events.map((event) => {
|
|
86
|
-
const params = event.paramsRaw.trim();
|
|
87
|
-
const suffix = params ? `(${params})` : "()";
|
|
88
|
-
return ` @+${formatNumber(event.offset)}: $.${event.action}${suffix}`;
|
|
89
|
-
});
|
|
90
|
-
return `seq ${name}(${seq.params.join(", ")}) {
|
|
91
|
-
${lines.join("\n")}
|
|
92
|
-
}`;
|
|
93
|
-
}
|
|
94
|
-
function formatTimeline(ast) {
|
|
95
|
-
if (ast.events.length === 0 && ast.chapters.length === 0) {
|
|
96
|
-
return "";
|
|
97
|
-
}
|
|
98
|
-
const blocks = [];
|
|
99
|
-
const topLevelEvents = ast.events.filter((event) => event.chapter === void 0);
|
|
100
|
-
for (const event of topLevelEvents) {
|
|
101
|
-
blocks.push({ line: event.line, text: formatEvent(event) });
|
|
102
|
-
}
|
|
103
|
-
const chaptersByLine = [...ast.chapters].sort((a, b) => a.startLine - b.startLine);
|
|
104
|
-
for (let index = 0; index < chaptersByLine.length; index++) {
|
|
105
|
-
const chapter = chaptersByLine[index];
|
|
106
|
-
const nextStartLine = chaptersByLine[index + 1]?.startLine ?? Number.POSITIVE_INFINITY;
|
|
107
|
-
const events = ast.events.filter(
|
|
108
|
-
(event) => event.chapter === chapter.name && event.line > chapter.startLine && event.line < nextStartLine
|
|
109
|
-
).sort((a, b) => a.line - b.line);
|
|
110
|
-
blocks.push({ line: chapter.startLine, text: formatChapter(chapter, events) });
|
|
111
|
-
}
|
|
112
|
-
return blocks.sort((a, b) => a.line - b.line).map((block) => block.text).join("\n\n");
|
|
113
|
-
}
|
|
114
|
-
function formatChapter(chapter, events) {
|
|
115
|
-
const body = events.length > 0 ? `
|
|
116
|
-
${events.map((event) => ` ${formatEvent(event)}`).join("\n")}
|
|
117
|
-
` : "\n";
|
|
118
|
-
return `scene ${JSON.stringify(chapter.name)} {${body}}`;
|
|
119
|
-
}
|
|
120
|
-
function formatEvent(event) {
|
|
121
|
-
const params = Object.entries(event.params).map(([key, value]) => `${key}=${formatParamValue(value)}`).join(", ");
|
|
122
|
-
return `@${formatNumber(event.time)}: ${event.actor}.${event.action}(${params})`;
|
|
123
|
-
}
|
|
124
|
-
function formatParamValue(value) {
|
|
125
|
-
if (Array.isArray(value)) {
|
|
126
|
-
return `(${value.map(formatTupleValue).join(", ")})`;
|
|
127
|
-
}
|
|
128
|
-
if (typeof value === "number") {
|
|
129
|
-
return formatNumber(value);
|
|
130
|
-
}
|
|
131
|
-
if (typeof value === "string") {
|
|
132
|
-
return formatToken(value);
|
|
14
|
+
const lines = [];
|
|
15
|
+
const sceneParts = [`scene`];
|
|
16
|
+
if (ast.meta.title) sceneParts.push(JSON.stringify(ast.meta.title));
|
|
17
|
+
sceneParts.push(`theme=${ast.meta.theme}`);
|
|
18
|
+
if (ast.meta.width !== 1280) sceneParts.push(`width=${ast.meta.width}`);
|
|
19
|
+
if (ast.meta.height !== 720) sceneParts.push(`height=${ast.meta.height}`);
|
|
20
|
+
if (ast.meta.fps !== 60) sceneParts.push(`fps=${ast.meta.fps}`);
|
|
21
|
+
if (ast.meta.duration !== void 0) sceneParts.push(`duration=${ast.meta.duration}`);
|
|
22
|
+
lines.push(sceneParts.join(" "));
|
|
23
|
+
if (ast.meta.direction !== "LR") {
|
|
24
|
+
lines.push(`layout ${ast.meta.direction}`);
|
|
25
|
+
}
|
|
26
|
+
for (const style of Object.values(ast.styles)) {
|
|
27
|
+
lines.push(formatStyle(style));
|
|
28
|
+
}
|
|
29
|
+
for (const node of Object.values(ast.nodes)) {
|
|
30
|
+
lines.push(formatNode(node));
|
|
31
|
+
}
|
|
32
|
+
for (const edge of ast.edges) {
|
|
33
|
+
lines.push(formatEdge(edge));
|
|
34
|
+
}
|
|
35
|
+
for (const group of Object.values(ast.groups)) {
|
|
36
|
+
lines.push(formatGroup(group));
|
|
37
|
+
}
|
|
38
|
+
for (const pattern of Object.values(ast.patterns)) {
|
|
39
|
+
lines.push(`pattern ${pattern.name}(${pattern.params.join(", ")}):`);
|
|
40
|
+
for (const cue of pattern.body) {
|
|
41
|
+
lines.push(` ${formatCue(cue)}`);
|
|
42
|
+
}
|
|
43
|
+
lines.push("");
|
|
133
44
|
}
|
|
134
|
-
|
|
135
|
-
|
|
45
|
+
for (const beat of ast.beats) {
|
|
46
|
+
lines.push(formatBeat(beat));
|
|
47
|
+
lines.push("");
|
|
136
48
|
}
|
|
137
|
-
return
|
|
49
|
+
return `${lines.join("\n").trim()}
|
|
50
|
+
`;
|
|
138
51
|
}
|
|
139
|
-
function
|
|
140
|
-
|
|
141
|
-
|
|
52
|
+
function formatStyle(style) {
|
|
53
|
+
const props = Object.entries(style.props).map(([k, v]) => `${k}=${formatValue(v)}`).join(" ");
|
|
54
|
+
return `style ${style.name} = ${props}`;
|
|
55
|
+
}
|
|
56
|
+
function formatNode(node) {
|
|
57
|
+
let line = `${node.kind} ${node.id}`;
|
|
58
|
+
if (node.label !== node.id && node.label) line += ` ${JSON.stringify(node.label)}`;
|
|
59
|
+
if (node.style) line += ` style=${node.style}`;
|
|
60
|
+
return line;
|
|
61
|
+
}
|
|
62
|
+
function formatEdge(edge) {
|
|
63
|
+
const op = edge.kind === "request" ? "->" : edge.kind === "response" ? "<-" : edge.kind === "event" ? "~>" : "--";
|
|
64
|
+
const [left, right] = edge.kind === "response" ? [edge.to, edge.from] : [edge.from, edge.to];
|
|
65
|
+
let chain = `${left} ${op} ${right}`;
|
|
66
|
+
if (edge.label) chain += ` ${JSON.stringify(edge.label)}`;
|
|
67
|
+
return `edge ${edge.id}: ${chain}`;
|
|
68
|
+
}
|
|
69
|
+
function formatGroup(group) {
|
|
70
|
+
const label = group.label ? ` ${JSON.stringify(group.label)}` : "";
|
|
71
|
+
return `group ${group.id}${label}: ${group.members.join(" ")}`;
|
|
72
|
+
}
|
|
73
|
+
function formatBeat(beat) {
|
|
74
|
+
const label = beat.label ? ` ${JSON.stringify(beat.label)}` : "";
|
|
75
|
+
const lines = [`beat ${beat.name}${label}:`];
|
|
76
|
+
for (const cue of beat.cues) {
|
|
77
|
+
lines.push(` ${formatCue(cue)}`);
|
|
78
|
+
}
|
|
79
|
+
return lines.join("\n");
|
|
80
|
+
}
|
|
81
|
+
function formatCue(cue) {
|
|
82
|
+
if (cue.kind === "parallel") {
|
|
83
|
+
return cue.cues.map(formatCue).join(" & ");
|
|
84
|
+
}
|
|
85
|
+
if (cue.kind === "flow") {
|
|
86
|
+
let chain = "";
|
|
87
|
+
for (let i = 0; i < cue.segments.length; i++) {
|
|
88
|
+
const seg = cue.segments[i];
|
|
89
|
+
const op = seg.op === "request" ? "->" : seg.op === "response" ? "<-" : seg.op === "event" ? "~>" : "--";
|
|
90
|
+
const [left, right] = seg.op === "response" ? [seg.to, seg.from] : [seg.from, seg.to];
|
|
91
|
+
if (i === 0) chain += left;
|
|
92
|
+
chain += ` ${op} ${right}`;
|
|
93
|
+
if (seg.label) chain += ` ${JSON.stringify(seg.label)}`;
|
|
94
|
+
}
|
|
95
|
+
if (cue.dur !== void 0) chain += ` dur=${cue.dur}s`;
|
|
96
|
+
return chain;
|
|
97
|
+
}
|
|
98
|
+
if (cue.kind === "show" || cue.kind === "hide") {
|
|
99
|
+
let line = `${cue.kind} ${cue.targets.join(" ")}`;
|
|
100
|
+
if (cue.kind === "show" && cue.stagger !== void 0) line += ` stagger=${cue.stagger}s`;
|
|
101
|
+
if (cue.dur !== void 0) line += ` dur=${cue.dur}s`;
|
|
102
|
+
return line;
|
|
103
|
+
}
|
|
104
|
+
if (cue.kind === "glow") {
|
|
105
|
+
let line = `glow ${cue.targets.join(" ")}`;
|
|
106
|
+
if (cue.color) line += ` color=${cue.color}`;
|
|
107
|
+
if (cue.strength !== void 0) line += ` strength=${cue.strength}`;
|
|
108
|
+
if (cue.dur !== void 0) line += ` dur=${cue.dur}s`;
|
|
109
|
+
return line;
|
|
110
|
+
}
|
|
111
|
+
if (cue.kind === "focus") {
|
|
112
|
+
let line = `focus ${cue.targets.join(" ")}`;
|
|
113
|
+
if (cue.zoom !== void 0) line += ` zoom=${cue.zoom}`;
|
|
114
|
+
if (cue.dur !== void 0) line += ` dur=${cue.dur}s`;
|
|
115
|
+
return line;
|
|
116
|
+
}
|
|
117
|
+
if (cue.kind === "use") {
|
|
118
|
+
const args = Object.entries(cue.args).map(([k, v]) => k.startsWith("__pos_") ? v : `${k}=${v}`).join(", ");
|
|
119
|
+
return `use ${cue.pattern}(${args})`;
|
|
120
|
+
}
|
|
121
|
+
return "";
|
|
122
|
+
}
|
|
123
|
+
function formatValue(value) {
|
|
124
|
+
if (typeof value === "number") return String(value);
|
|
125
|
+
if (typeof value === "string") return value;
|
|
142
126
|
return JSON.stringify(value);
|
|
143
127
|
}
|
|
144
|
-
function formatToken(value) {
|
|
145
|
-
return BARE_TOKEN_RE.test(value) ? value : JSON.stringify(value);
|
|
146
|
-
}
|
|
147
|
-
function formatNumber(value) {
|
|
148
|
-
return Number.isInteger(value) ? String(value) : String(round3(value));
|
|
149
|
-
}
|
|
150
|
-
function round3(value) {
|
|
151
|
-
return Math.round(value * 1e3) / 1e3;
|
|
152
|
-
}
|
|
153
128
|
|
|
154
129
|
// src/index.ts
|
|
155
130
|
var DEFAULT_PORT = 4242;
|
|
156
|
-
var IMPORT_RE = /^import\s+"([^"]+)"\s+as\s+(\w+)\s*$/;
|
|
157
131
|
var MARKDY_EXT = ".markdy";
|
|
158
132
|
var PACKAGE_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
159
|
-
registerActorPack(systemsPack);
|
|
160
133
|
async function runCli(argv, io = defaultIo(), runtime = defaultRuntime()) {
|
|
161
134
|
const parsed = parseArgv(argv);
|
|
162
135
|
if (hasFlag(parsed, "help")) {
|
|
@@ -205,7 +178,7 @@ async function lintCommand(parsed, io) {
|
|
|
205
178
|
try {
|
|
206
179
|
const scene = await loadSceneFromFile(file, cache);
|
|
207
180
|
io.stdout(`OK ${file}`);
|
|
208
|
-
warningCount += printWarnings(scene.ast.
|
|
181
|
+
warningCount += printWarnings(scene.ast.diagnostics, file, io);
|
|
209
182
|
} catch (error) {
|
|
210
183
|
errorCount++;
|
|
211
184
|
io.stderr(`FAIL ${file}`);
|
|
@@ -302,37 +275,23 @@ async function explainCommand(parsed, io) {
|
|
|
302
275
|
const summary = [
|
|
303
276
|
`File: ${scene.filePath}`,
|
|
304
277
|
`Viewport: ${scene.ast.meta.width}\xD7${scene.ast.meta.height} @ ${scene.ast.meta.fps}fps`,
|
|
305
|
-
`
|
|
306
|
-
`Duration: ${scene.ast.meta.duration ??
|
|
307
|
-
`
|
|
308
|
-
`
|
|
309
|
-
`
|
|
310
|
-
`Imports: ${scene.ast.imports.length > 0 ? scene.ast.imports.map((item) => `${item.namespace} -> ${item.path}`).join(", ") : "(none)"}`,
|
|
311
|
-
`Warnings: ${scene.ast.warnings.length}`
|
|
278
|
+
`Theme: ${scene.ast.meta.theme}`,
|
|
279
|
+
`Duration: ${scene.ast.meta.duration ?? "(auto)"}`,
|
|
280
|
+
`Nodes: ${Object.keys(scene.ast.nodes).length}`,
|
|
281
|
+
`Beats: ${scene.ast.beats.map((b) => b.name).join(", ") || "(none)"}`,
|
|
282
|
+
`Diagnostics: ${scene.ast.diagnostics.length}`
|
|
312
283
|
];
|
|
313
284
|
io.stdout(summary.join("\n"));
|
|
314
|
-
if (scene.ast.
|
|
315
|
-
printWarnings(scene.ast.
|
|
285
|
+
if (scene.ast.diagnostics.length > 0) {
|
|
286
|
+
printWarnings(scene.ast.diagnostics, scene.filePath, io);
|
|
316
287
|
}
|
|
317
288
|
return { exitCode: 0 };
|
|
318
289
|
}
|
|
319
290
|
async function newCommand(parsed, io) {
|
|
320
|
-
const
|
|
321
|
-
const second = parsed.positionals[1];
|
|
291
|
+
const target = parsed.positionals[0] ?? "scene.markdy";
|
|
322
292
|
const force = hasFlag(parsed, "force");
|
|
323
|
-
let presetName = "basic";
|
|
324
|
-
let target = "scene.markdy";
|
|
325
|
-
if (presetOrTarget) {
|
|
326
|
-
if (PRESET_NAMES.includes(presetOrTarget)) {
|
|
327
|
-
presetName = presetOrTarget;
|
|
328
|
-
target = second ?? target;
|
|
329
|
-
} else {
|
|
330
|
-
target = presetOrTarget;
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
293
|
const resolvedTarget = resolve(target);
|
|
334
|
-
const content =
|
|
335
|
-
`;
|
|
294
|
+
const content = defaultSceneTemplate();
|
|
336
295
|
if (!force && await exists(resolvedTarget)) {
|
|
337
296
|
io.stderr(`markdy new: target already exists: ${resolvedTarget} (pass --force to overwrite)`);
|
|
338
297
|
return { exitCode: 1 };
|
|
@@ -395,10 +354,9 @@ async function checkAllCommand(parsed, io) {
|
|
|
395
354
|
async function launchPlayground(parsed, io, runtime, scene) {
|
|
396
355
|
const portFlag = getStringFlag(parsed, "port");
|
|
397
356
|
const preferredPort = portFlag ? Number(portFlag) : DEFAULT_PORT;
|
|
398
|
-
const code = scene?.source ??
|
|
399
|
-
const imports = scene?.imports ?? {};
|
|
357
|
+
const code = scene?.source ?? defaultSceneTemplate();
|
|
400
358
|
const sourcePath = scene?.filePath;
|
|
401
|
-
const server = await startPreviewServer(code,
|
|
359
|
+
const server = await startPreviewServer(code, sourcePath, preferredPort);
|
|
402
360
|
const address = server.address();
|
|
403
361
|
const port = typeof address === "object" && address ? address.port : preferredPort;
|
|
404
362
|
const url = `http://127.0.0.1:${port}`;
|
|
@@ -408,10 +366,10 @@ async function launchPlayground(parsed, io, runtime, scene) {
|
|
|
408
366
|
}
|
|
409
367
|
return { exitCode: 0, server };
|
|
410
368
|
}
|
|
411
|
-
async function startPreviewServer(code,
|
|
369
|
+
async function startPreviewServer(code, sourcePath, preferredPort) {
|
|
412
370
|
const coreDist = resolvePackageDist("@markdy/core");
|
|
413
371
|
const rendererDist = resolvePackageDist("@markdy/renderer-dom");
|
|
414
|
-
const html = buildPlaygroundHtml(code,
|
|
372
|
+
const html = buildPlaygroundHtml(code, sourcePath);
|
|
415
373
|
const server = createServer(async (request, response) => {
|
|
416
374
|
try {
|
|
417
375
|
const requestUrl = new URL(request.url ?? "/", "http://127.0.0.1");
|
|
@@ -470,32 +428,11 @@ async function loadSceneFromFile(filePath, cache = /* @__PURE__ */ new Map(), st
|
|
|
470
428
|
const source = await readFile(resolvedPath, "utf8").catch((error) => {
|
|
471
429
|
throw new Error(`Unable to read ${resolvedPath}: ${describeError(error)}`);
|
|
472
430
|
});
|
|
473
|
-
const
|
|
474
|
-
const
|
|
475
|
-
const loaded = { filePath: resolvedPath, source, ast, imports };
|
|
431
|
+
const ast = parse(source);
|
|
432
|
+
const loaded = { filePath: resolvedPath, source, ast };
|
|
476
433
|
cache.set(resolvedPath, loaded);
|
|
477
434
|
return loaded;
|
|
478
435
|
}
|
|
479
|
-
async function resolveSceneImports(source, filePath, cache, stack) {
|
|
480
|
-
const imports = {};
|
|
481
|
-
for (const declaration of scanImports(source)) {
|
|
482
|
-
const childPath = resolve(dirname(filePath), declaration.path);
|
|
483
|
-
const child = await loadSceneFromFile(childPath, cache, stack);
|
|
484
|
-
imports[declaration.namespace] = child.ast;
|
|
485
|
-
}
|
|
486
|
-
return imports;
|
|
487
|
-
}
|
|
488
|
-
function scanImports(source) {
|
|
489
|
-
const imports = [];
|
|
490
|
-
for (const line of source.split(/\r?\n/)) {
|
|
491
|
-
const trimmed = line.trim();
|
|
492
|
-
if (!trimmed.startsWith("import ")) continue;
|
|
493
|
-
const match = IMPORT_RE.exec(trimmed);
|
|
494
|
-
if (!match) continue;
|
|
495
|
-
imports.push({ path: match[1], namespace: match[2] });
|
|
496
|
-
}
|
|
497
|
-
return imports;
|
|
498
|
-
}
|
|
499
436
|
async function collectSceneFiles(inputs) {
|
|
500
437
|
const candidates = inputs.length > 0 ? inputs : [process.cwd()];
|
|
501
438
|
const out = /* @__PURE__ */ new Set();
|
|
@@ -533,7 +470,7 @@ async function walkMarkdyFiles(root) {
|
|
|
533
470
|
}
|
|
534
471
|
return files;
|
|
535
472
|
}
|
|
536
|
-
function buildPlaygroundHtml(code,
|
|
473
|
+
function buildPlaygroundHtml(code, sourcePath) {
|
|
537
474
|
return `<!doctype html>
|
|
538
475
|
<html lang="en">
|
|
539
476
|
<head>
|
|
@@ -629,7 +566,7 @@ function buildPlaygroundHtml(code, imports, sourcePath) {
|
|
|
629
566
|
<strong>Markdy Playground</strong>
|
|
630
567
|
<div><code>${escapeHtml(sourcePath ?? "scratch scene")}</code></div>
|
|
631
568
|
</div>
|
|
632
|
-
<div>
|
|
569
|
+
<div>MarkdyScript 0.8 diagram playground</div>
|
|
633
570
|
</header>
|
|
634
571
|
<main>
|
|
635
572
|
<section class="editor">
|
|
@@ -648,7 +585,6 @@ function buildPlaygroundHtml(code, imports, sourcePath) {
|
|
|
648
585
|
<script type="module">
|
|
649
586
|
import { createPlayer } from "@markdy/renderer-dom";
|
|
650
587
|
|
|
651
|
-
const imports = ${JSON.stringify(imports)};
|
|
652
588
|
const textarea = document.getElementById("code");
|
|
653
589
|
const viewport = document.getElementById("viewport");
|
|
654
590
|
const warnings = document.getElementById("warnings");
|
|
@@ -665,10 +601,9 @@ function buildPlaygroundHtml(code, imports, sourcePath) {
|
|
|
665
601
|
player = createPlayer({
|
|
666
602
|
container: viewport,
|
|
667
603
|
code: textarea.value,
|
|
668
|
-
imports,
|
|
669
604
|
onWarning(warning) {
|
|
670
605
|
const item = document.createElement("li");
|
|
671
|
-
item.textContent = \`line \${warning.line}: \${warning.message}
|
|
606
|
+
item.textContent = \`line \${warning.line}: \${warning.message}\`;
|
|
672
607
|
warnings.appendChild(item);
|
|
673
608
|
}
|
|
674
609
|
});
|
|
@@ -731,9 +666,8 @@ async function buildStandaloneHtml(scene) {
|
|
|
731
666
|
createPlayer({
|
|
732
667
|
container: document.getElementById("app"),
|
|
733
668
|
code: ${JSON.stringify(scene.source)},
|
|
734
|
-
imports: ${JSON.stringify(scene.imports)},
|
|
735
669
|
onWarning(warning) {
|
|
736
|
-
console.warn(\`[markdy] line \${warning.line}: \${warning.message}
|
|
670
|
+
console.warn(\`[markdy] line \${warning.line}: \${warning.message}\`);
|
|
737
671
|
}
|
|
738
672
|
});
|
|
739
673
|
</script>
|
|
@@ -750,12 +684,10 @@ function helpText() {
|
|
|
750
684
|
" markdy fmt <file-or-dir> [--write | --check]",
|
|
751
685
|
" markdy render <file.markdy> [--out file.html] [--port 4242] [--no-open]",
|
|
752
686
|
" markdy explain <file.markdy> [--json]",
|
|
753
|
-
" markdy new [
|
|
687
|
+
" markdy new [target.markdy] [--force]",
|
|
754
688
|
" markdy docs [--open]",
|
|
755
689
|
" markdy ai [--open]",
|
|
756
|
-
" markdy check-all [dir] [--strict]"
|
|
757
|
-
"",
|
|
758
|
-
`Built-in presets: ${PRESET_NAMES.join(", ")}`
|
|
690
|
+
" markdy check-all [dir] [--strict]"
|
|
759
691
|
].join("\n");
|
|
760
692
|
}
|
|
761
693
|
function parseArgv(argv) {
|
|
@@ -824,10 +756,10 @@ function getStringFlag(parsed, name) {
|
|
|
824
756
|
return typeof value === "string" ? value : void 0;
|
|
825
757
|
}
|
|
826
758
|
function printWarnings(warnings, file, io) {
|
|
827
|
-
for (const warning of warnings) {
|
|
828
|
-
io.stderr(`WARN ${file}:${warning.line} ${warning.
|
|
759
|
+
for (const warning of warnings.filter((w) => w.severity === "warning")) {
|
|
760
|
+
io.stderr(`WARN ${file}:${warning.line} ${warning.message}`);
|
|
829
761
|
}
|
|
830
|
-
return warnings.length;
|
|
762
|
+
return warnings.filter((w) => w.severity === "warning").length;
|
|
831
763
|
}
|
|
832
764
|
function stableStringify(value) {
|
|
833
765
|
const seen = /* @__PURE__ */ new WeakSet();
|
|
@@ -888,14 +820,16 @@ function describeError(error) {
|
|
|
888
820
|
}
|
|
889
821
|
function defaultSceneTemplate() {
|
|
890
822
|
return [
|
|
891
|
-
|
|
823
|
+
'scene "My Architecture" theme=midnight',
|
|
824
|
+
"layout LR",
|
|
892
825
|
"",
|
|
893
|
-
|
|
894
|
-
"
|
|
826
|
+
"browser Client",
|
|
827
|
+
"service API",
|
|
828
|
+
"database DB",
|
|
895
829
|
"",
|
|
896
|
-
"
|
|
897
|
-
"
|
|
898
|
-
'
|
|
830
|
+
"beat intro:",
|
|
831
|
+
" show $nodes",
|
|
832
|
+
' Client -> API "GET /health" -> DB "lookup"',
|
|
899
833
|
""
|
|
900
834
|
].join("\n");
|
|
901
835
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markdy/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "First-party CLI for MarkdyScript: lint, format, explain, render, and local playground tooling.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
"access": "public"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@markdy/core": "0.
|
|
45
|
-
"@markdy/
|
|
46
|
-
"@markdy/
|
|
44
|
+
"@markdy/core": "0.8.0",
|
|
45
|
+
"@markdy/stdlib-systems": "0.8.0",
|
|
46
|
+
"@markdy/renderer-dom": "0.8.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@types/node": "^25.9.5",
|