@modularcloud/cspec 0.1.0 → 0.3.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/bin/cspec.d.ts +3 -0
- package/dist/bin/cspec.d.ts.map +1 -0
- package/dist/bin/cspec.js +6 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +383 -0
- package/dist/editor/assets/index-BV-lxU2y.css +1 -0
- package/dist/editor/assets/index-DL-RbHCV.js +80 -0
- package/dist/editor/index.html +14 -0
- package/dist/runtime.d.ts +12 -0
- package/{src → dist}/runtime.js +3 -6
- package/package.json +28 -11
- package/bin/cspec.js +0 -7
- package/src/cli.js +0 -62
- package/src/config.js +0 -47
- package/src/errors.js +0 -15
- package/src/generate.js +0 -53
- package/src/glob.js +0 -42
- package/src/ids.js +0 -45
- package/src/parser.js +0 -221
- package/src/render.js +0 -89
- package/src/workspace.js +0 -37
package/src/render.js
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import { CspecError } from "./errors.js";
|
|
2
|
-
import { lineAt, resolveImportPath } from "./parser.js";
|
|
3
|
-
|
|
4
|
-
export function compileWorkspace(documents) {
|
|
5
|
-
const byFile = new Map(documents.map((doc) => [doc.file, doc]));
|
|
6
|
-
const context = { byFile, stack: [] };
|
|
7
|
-
for (const doc of documents) {
|
|
8
|
-
compileBlock(doc, doc.root, context);
|
|
9
|
-
for (const block of doc.blocks.values()) compileBlock(doc, block, context);
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function compileBlock(doc, block, context) {
|
|
14
|
-
const key = `${doc.file}#${block.id || "$"}`;
|
|
15
|
-
if (block.compiled !== null) return block.compiled;
|
|
16
|
-
const cycleAt = context.stack.indexOf(key);
|
|
17
|
-
if (cycleAt !== -1) {
|
|
18
|
-
const cycle = context.stack.slice(cycleAt).concat(key).map((item) => item.split("#")[1]).join(" -> ");
|
|
19
|
-
throw new CspecError(`Embedding cycle detected:\n${cycle}`, { file: doc.file, line: block.line });
|
|
20
|
-
}
|
|
21
|
-
context.stack.push(key);
|
|
22
|
-
const start = block.id ? block.contentStart : 0;
|
|
23
|
-
const end = block.id ? block.contentEnd : doc.source.length;
|
|
24
|
-
block.compiled = renderRange(doc, start, end, context);
|
|
25
|
-
context.stack.pop();
|
|
26
|
-
return block.compiled;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function renderRange(doc, start, end, context) {
|
|
30
|
-
const removals = doc.rangesToRemove
|
|
31
|
-
.filter(([a, b]) => b > start && a < end)
|
|
32
|
-
.map(([a, b]) => [Math.max(a, start), Math.min(b, end), ""]);
|
|
33
|
-
const replacements = doc.references
|
|
34
|
-
.filter((ref) => ref.start >= start && ref.end <= end)
|
|
35
|
-
.map((ref) => [ref.start, ref.end, resolveReference(doc, ref, context)]);
|
|
36
|
-
const edits = removals.concat(replacements).sort((a, b) => a[0] - b[0] || b[1] - a[1]);
|
|
37
|
-
|
|
38
|
-
let out = "";
|
|
39
|
-
let cursor = start;
|
|
40
|
-
for (const [a, b, value] of edits) {
|
|
41
|
-
if (a < cursor) continue;
|
|
42
|
-
out += doc.source.slice(cursor, a);
|
|
43
|
-
out += value;
|
|
44
|
-
cursor = b;
|
|
45
|
-
}
|
|
46
|
-
out += doc.source.slice(cursor, end);
|
|
47
|
-
return trimOuterBlankLines(out);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function resolveReference(doc, ref, context) {
|
|
51
|
-
if (ref.kind === "local") {
|
|
52
|
-
if (!ref.validStatic) {
|
|
53
|
-
throw new CspecError("ref(...) requires a static string literal.", {
|
|
54
|
-
file: doc.file,
|
|
55
|
-
line: lineAt(doc.source, ref.start)
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
const target = doc.blocks.get(ref.id);
|
|
59
|
-
if (!target) {
|
|
60
|
-
throw new CspecError(`Unknown local block reference "${ref.id}".`, {
|
|
61
|
-
file: doc.file,
|
|
62
|
-
line: lineAt(doc.source, ref.start)
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
return compileBlock(doc, target, context);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const imported = doc.imports.find((item) => item.kind === "module" && item.local === ref.local);
|
|
69
|
-
const targetFile = resolveImportPath(doc.file, imported.specifier);
|
|
70
|
-
const targetDoc = context.byFile.get(targetFile);
|
|
71
|
-
if (!targetDoc) {
|
|
72
|
-
throw new CspecError(`Unresolved import ${imported.specifier}.`, {
|
|
73
|
-
file: doc.file,
|
|
74
|
-
line: lineAt(doc.source, ref.start)
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
const target = ref.path ? targetDoc.blocks.get(ref.path) : targetDoc.root;
|
|
78
|
-
if (!target) {
|
|
79
|
-
throw new CspecError(`Unknown block reference ${ref.expression}.`, {
|
|
80
|
-
file: doc.file,
|
|
81
|
-
line: lineAt(doc.source, ref.start)
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
return compileBlock(targetDoc, target, context);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function trimOuterBlankLines(value) {
|
|
88
|
-
return value.replace(/^\s*\n/, "").replace(/\n\s*$/, "");
|
|
89
|
-
}
|
package/src/workspace.js
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { loadConfig } from "./config.js";
|
|
4
|
-
import { discoverFiles } from "./glob.js";
|
|
5
|
-
import { parseSource } from "./parser.js";
|
|
6
|
-
import { compileWorkspace } from "./render.js";
|
|
7
|
-
import { generatedFilesFor } from "./generate.js";
|
|
8
|
-
import { CspecError } from "./errors.js";
|
|
9
|
-
|
|
10
|
-
export async function loadWorkspace(cwd) {
|
|
11
|
-
const config = await loadConfig(cwd);
|
|
12
|
-
const files = discoverFiles(cwd, config.specs);
|
|
13
|
-
const documents = files.map((file) => parseSource(file, fs.readFileSync(file, "utf8")));
|
|
14
|
-
compileWorkspace(documents);
|
|
15
|
-
return { cwd, config, documents };
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function expectedOutputs(workspace) {
|
|
19
|
-
return workspace.documents.flatMap((doc) =>
|
|
20
|
-
generatedFilesFor(doc, { markdownEmit: workspace.config.markdown.emit })
|
|
21
|
-
);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function writeOutputs(workspace) {
|
|
25
|
-
for (const output of expectedOutputs(workspace)) {
|
|
26
|
-
fs.writeFileSync(output.file, output.content);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function assertFresh(workspace) {
|
|
31
|
-
for (const output of expectedOutputs(workspace)) {
|
|
32
|
-
const rel = path.relative(workspace.cwd, output.file);
|
|
33
|
-
if (!fs.existsSync(output.file) || fs.readFileSync(output.file, "utf8") !== output.content) {
|
|
34
|
-
throw new CspecError(`Generated file ${rel} is stale.\nRun cspec build.`, { file: output.file });
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|