@aruzone/aze-forge 0.1.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.
Files changed (133) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +408 -0
  3. package/dist/acceptance.d.ts +48 -0
  4. package/dist/acceptance.js +180 -0
  5. package/dist/acceptance.js.map +1 -0
  6. package/dist/assets.d.ts +19 -0
  7. package/dist/assets.js +509 -0
  8. package/dist/assets.js.map +1 -0
  9. package/dist/atomic-write.d.ts +1 -0
  10. package/dist/atomic-write.js +23 -0
  11. package/dist/atomic-write.js.map +1 -0
  12. package/dist/callout.d.ts +27 -0
  13. package/dist/callout.js +78 -0
  14. package/dist/callout.js.map +1 -0
  15. package/dist/capabilities-json.d.ts +4 -0
  16. package/dist/capabilities-json.js +225 -0
  17. package/dist/capabilities-json.js.map +1 -0
  18. package/dist/capabilities.d.ts +110 -0
  19. package/dist/capabilities.js +270 -0
  20. package/dist/capabilities.js.map +1 -0
  21. package/dist/cli.d.ts +2 -0
  22. package/dist/cli.js +1096 -0
  23. package/dist/cli.js.map +1 -0
  24. package/dist/compiler.d.ts +3 -0
  25. package/dist/compiler.js +1034 -0
  26. package/dist/compiler.js.map +1 -0
  27. package/dist/configuration-error.d.ts +4 -0
  28. package/dist/configuration-error.js +9 -0
  29. package/dist/configuration-error.js.map +1 -0
  30. package/dist/diagnostics-json.d.ts +23 -0
  31. package/dist/diagnostics-json.js +143 -0
  32. package/dist/diagnostics-json.js.map +1 -0
  33. package/dist/diagnostics.d.ts +16 -0
  34. package/dist/diagnostics.js +154 -0
  35. package/dist/diagnostics.js.map +1 -0
  36. package/dist/equation.d.ts +74 -0
  37. package/dist/equation.js +485 -0
  38. package/dist/equation.js.map +1 -0
  39. package/dist/font.d.ts +19 -0
  40. package/dist/font.js +75 -0
  41. package/dist/font.js.map +1 -0
  42. package/dist/format.d.ts +2 -0
  43. package/dist/format.js +308 -0
  44. package/dist/format.js.map +1 -0
  45. package/dist/hash.d.ts +5 -0
  46. package/dist/hash.js +189 -0
  47. package/dist/hash.js.map +1 -0
  48. package/dist/help.d.ts +9 -0
  49. package/dist/help.js +102 -0
  50. package/dist/help.js.map +1 -0
  51. package/dist/html-fragment.d.ts +7 -0
  52. package/dist/html-fragment.js +70 -0
  53. package/dist/html-fragment.js.map +1 -0
  54. package/dist/index.d.ts +39 -0
  55. package/dist/index.js +32 -0
  56. package/dist/index.js.map +1 -0
  57. package/dist/markdown.d.ts +14 -0
  58. package/dist/markdown.js +425 -0
  59. package/dist/markdown.js.map +1 -0
  60. package/dist/mermaid-browser.d.ts +43 -0
  61. package/dist/mermaid-browser.js +358 -0
  62. package/dist/mermaid-browser.js.map +1 -0
  63. package/dist/mermaid.d.ts +84 -0
  64. package/dist/mermaid.js +740 -0
  65. package/dist/mermaid.js.map +1 -0
  66. package/dist/model.d.ts +406 -0
  67. package/dist/model.js +2 -0
  68. package/dist/model.js.map +1 -0
  69. package/dist/parse.d.ts +3 -0
  70. package/dist/parse.js +1374 -0
  71. package/dist/parse.js.map +1 -0
  72. package/dist/preview-server.d.ts +39 -0
  73. package/dist/preview-server.js +156 -0
  74. package/dist/preview-server.js.map +1 -0
  75. package/dist/preview-shell.d.ts +29 -0
  76. package/dist/preview-shell.js +102 -0
  77. package/dist/preview-shell.js.map +1 -0
  78. package/dist/reference-validation.d.ts +7 -0
  79. package/dist/reference-validation.js +42 -0
  80. package/dist/reference-validation.js.map +1 -0
  81. package/dist/registry.d.ts +29 -0
  82. package/dist/registry.js +384 -0
  83. package/dist/registry.js.map +1 -0
  84. package/dist/render-html.d.ts +24 -0
  85. package/dist/render-html.js +149 -0
  86. package/dist/render-html.js.map +1 -0
  87. package/dist/render-pdf.d.ts +64 -0
  88. package/dist/render-pdf.js +503 -0
  89. package/dist/render-pdf.js.map +1 -0
  90. package/dist/render-png.d.ts +32 -0
  91. package/dist/render-png.js +427 -0
  92. package/dist/render-png.js.map +1 -0
  93. package/dist/render-svg.d.ts +23 -0
  94. package/dist/render-svg.js +243 -0
  95. package/dist/render-svg.js.map +1 -0
  96. package/dist/runtime-support.d.ts +26 -0
  97. package/dist/runtime-support.js +62 -0
  98. package/dist/runtime-support.js.map +1 -0
  99. package/dist/source-map.d.ts +12 -0
  100. package/dist/source-map.js +75 -0
  101. package/dist/source-map.js.map +1 -0
  102. package/dist/table.d.ts +22 -0
  103. package/dist/table.js +90 -0
  104. package/dist/table.js.map +1 -0
  105. package/dist/theme.d.ts +6 -0
  106. package/dist/theme.js +89 -0
  107. package/dist/theme.js.map +1 -0
  108. package/dist/tool-version.d.ts +3 -0
  109. package/dist/tool-version.js +3 -0
  110. package/dist/tool-version.js.map +1 -0
  111. package/dist/type-guards.d.ts +1 -0
  112. package/dist/type-guards.js +4 -0
  113. package/dist/type-guards.js.map +1 -0
  114. package/dist/validate-document.d.ts +2 -0
  115. package/dist/validate-document.js +248 -0
  116. package/dist/validate-document.js.map +1 -0
  117. package/dist/version.d.ts +37 -0
  118. package/dist/version.js +111 -0
  119. package/dist/version.js.map +1 -0
  120. package/dist/watch-dependencies.d.ts +15 -0
  121. package/dist/watch-dependencies.js +93 -0
  122. package/dist/watch-dependencies.js.map +1 -0
  123. package/dist/watch-events.d.ts +51 -0
  124. package/dist/watch-events.js +27 -0
  125. package/dist/watch-events.js.map +1 -0
  126. package/dist/watch-loop.d.ts +39 -0
  127. package/dist/watch-loop.js +117 -0
  128. package/dist/watch-loop.js.map +1 -0
  129. package/package.json +70 -0
  130. package/schemas/acceptance.json +104 -0
  131. package/schemas/capabilities.json +491 -0
  132. package/schemas/diagnostics.json +219 -0
  133. package/schemas/version.json +167 -0
@@ -0,0 +1,93 @@
1
+ import { realpath } from "node:fs/promises";
2
+ import { extname, resolve } from "node:path";
3
+ import { isAbsoluteSource, isContained, isRemoteSource } from "./assets.js";
4
+ const SUPPORTED_IMAGE_EXTENSIONS = new Set([".png", ".jpg", ".jpeg", ".svg"]);
5
+ function collectInlineSources(nodes, out) {
6
+ for (const node of nodes) {
7
+ if (node.kind === "image") {
8
+ out.push(node.src);
9
+ }
10
+ else if (node.kind === "link") {
11
+ collectInlineSources(node.children, out);
12
+ }
13
+ else if (node.kind === "emphasis" || node.kind === "strong") {
14
+ collectInlineSources(node.children, out);
15
+ }
16
+ }
17
+ }
18
+ function collectBlockSources(blocks, out) {
19
+ for (const block of blocks) {
20
+ switch (block.kind) {
21
+ case "heading":
22
+ case "paragraph":
23
+ collectInlineSources(block.children, out);
24
+ break;
25
+ case "blockquote":
26
+ collectBlockSources(block.children, out);
27
+ break;
28
+ case "list":
29
+ for (const item of block.items)
30
+ collectBlockSources(item.blocks, out);
31
+ break;
32
+ case "callout":
33
+ collectBlockSources(block.children, out);
34
+ if (block.title !== undefined)
35
+ collectInlineSources(block.title, out);
36
+ break;
37
+ case "table":
38
+ for (const row of block.data.header)
39
+ collectInlineSources(row, out);
40
+ for (const row of block.data.rows) {
41
+ for (const cell of row)
42
+ collectInlineSources(cell, out);
43
+ }
44
+ if (block.caption !== undefined)
45
+ collectInlineSources(block.caption, out);
46
+ break;
47
+ default:
48
+ break;
49
+ }
50
+ }
51
+ }
52
+ /** Every image `src` referenced by a Document, in Source order. */
53
+ export function collectImageSources(document) {
54
+ const out = [];
55
+ collectBlockSources(document.blocks, out);
56
+ return out;
57
+ }
58
+ /**
59
+ * Partition image references into existing files and missing root-confined
60
+ * candidates. Remote, absolute, escaping, and unsupported-type references are
61
+ * compile errors, not watch targets, so they are skipped here.
62
+ */
63
+ export async function resolveWatchPaths(projectRoot, imageSources) {
64
+ const files = new Set();
65
+ const missing = new Set();
66
+ for (const src of imageSources) {
67
+ if (src.trim() === "" || src.includes("\0"))
68
+ continue;
69
+ if (isAbsoluteSource(src) || isRemoteSource(src))
70
+ continue;
71
+ if (!SUPPORTED_IMAGE_EXTENSIONS.has(extname(src).toLowerCase()))
72
+ continue;
73
+ const candidate = resolve(projectRoot, src);
74
+ if (!isContained(projectRoot, candidate))
75
+ continue;
76
+ let candidateReal;
77
+ try {
78
+ candidateReal = await realpath(candidate);
79
+ }
80
+ catch {
81
+ missing.add(candidate);
82
+ continue;
83
+ }
84
+ if (!isContained(projectRoot, candidateReal))
85
+ continue;
86
+ files.add(candidateReal);
87
+ }
88
+ return {
89
+ files: [...files].sort(),
90
+ missing: [...missing].sort(),
91
+ };
92
+ }
93
+ //# sourceMappingURL=watch-dependencies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch-dependencies.js","sourceRoot":"","sources":["../src/watch-dependencies.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ import type { ArtifactMetadata, ContentHash, Diagnostic } from "./model.js";
2
+ import { TOOL_VERSION } from "./tool-version.js";
3
+ export declare const WATCH_EVENT_SCHEMA_ID: "azeforge.event/v1";
4
+ export type WatchCommand = "watch" | "serve";
5
+ export type WatchEventKind = "started" | "result" | "stopped";
6
+ interface WatchEventBase {
7
+ readonly schema: typeof WATCH_EVENT_SCHEMA_ID;
8
+ readonly schemaVersion: 1;
9
+ readonly tool: Readonly<{
10
+ name: "azeforge";
11
+ version: typeof TOOL_VERSION;
12
+ }>;
13
+ readonly command: WatchCommand;
14
+ readonly seq: number;
15
+ readonly kind: WatchEventKind;
16
+ }
17
+ export interface WatchStartedEvent extends WatchEventBase {
18
+ readonly kind: "started";
19
+ readonly source: string;
20
+ /** Watch only: the file Artifact destination. */
21
+ readonly artifact?: string;
22
+ /** Watch only: the Artifact format. */
23
+ readonly format?: "html" | "svg" | "png" | "pdf";
24
+ /** Serve only: the loopback preview URL. */
25
+ readonly url?: string;
26
+ }
27
+ export interface WatchResultEvent extends WatchEventBase {
28
+ readonly kind: "result";
29
+ readonly success: boolean;
30
+ readonly diagnostics: readonly Diagnostic[];
31
+ readonly contentHash?: ContentHash;
32
+ readonly artifact?: ArtifactMetadata;
33
+ /** Serve only: the loopback preview URL. */
34
+ readonly url?: string;
35
+ /** Serve only: opaque asset URLs for the current manifest. */
36
+ readonly assets?: readonly Readonly<{
37
+ url: string;
38
+ mediaType: string;
39
+ byteLength: number;
40
+ }>[];
41
+ }
42
+ export interface WatchStoppedEvent extends WatchEventBase {
43
+ readonly kind: "stopped";
44
+ readonly reason: string;
45
+ }
46
+ export type WatchEvent = WatchStartedEvent | WatchResultEvent | WatchStoppedEvent;
47
+ export declare function createStartedEvent(command: WatchCommand, seq: number, details: Omit<WatchStartedEvent, "schema" | "schemaVersion" | "tool" | "command" | "seq" | "kind">): WatchStartedEvent;
48
+ export declare function createResultEvent(command: WatchCommand, seq: number, details: Omit<WatchResultEvent, "schema" | "schemaVersion" | "tool" | "command" | "seq" | "kind">): WatchResultEvent;
49
+ export declare function createStoppedEvent(command: WatchCommand, seq: number, reason: string): WatchStoppedEvent;
50
+ export declare function serializeEvent(event: WatchEvent): string;
51
+ export {};
@@ -0,0 +1,27 @@
1
+ import { TOOL_VERSION } from "./tool-version.js";
2
+ export const WATCH_EVENT_SCHEMA_ID = "azeforge.event/v1";
3
+ function toolIdentity() {
4
+ return { name: "azeforge", version: TOOL_VERSION };
5
+ }
6
+ function baseEvent(command, seq) {
7
+ return {
8
+ schema: WATCH_EVENT_SCHEMA_ID,
9
+ schemaVersion: 1,
10
+ tool: toolIdentity(),
11
+ command,
12
+ seq,
13
+ };
14
+ }
15
+ export function createStartedEvent(command, seq, details) {
16
+ return { ...baseEvent(command, seq), kind: "started", ...details };
17
+ }
18
+ export function createResultEvent(command, seq, details) {
19
+ return { ...baseEvent(command, seq), kind: "result", ...details };
20
+ }
21
+ export function createStoppedEvent(command, seq, reason) {
22
+ return { ...baseEvent(command, seq), kind: "stopped", reason };
23
+ }
24
+ export function serializeEvent(event) {
25
+ return JSON.stringify(event);
26
+ }
27
+ //# sourceMappingURL=watch-events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch-events.js","sourceRoot":"","sources":["../src/watch-events.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,MAAM,CAAC,MAAM,qBAAqB,GAAG,mBAA4B,CAAC;AAgDlE,SAAS,YAAY;IACnB,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC;AACrD,CAAC;AAED,SAAS,SAAS,CAAC,OAAqB,EAAE,GAAW;IACnD,OAAO;QACL,MAAM,EAAE,qBAAqB;QAC7B,aAAa,EAAE,CAAC;QAChB,IAAI,EAAE,YAAY,EAAE;QACpB,OAAO;QACP,GAAG;KACJ,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,OAAqB,EACrB,GAAW,EACX,OAAkG;IAElG,OAAO,EAAE,GAAG,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,OAAO,EAAE,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,OAAqB,EACrB,GAAW,EACX,OAAiG;IAEjG,OAAO,EAAE,GAAG,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,OAAO,EAAE,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,OAAqB,EACrB,GAAW,EACX,MAAc;IAEd,OAAO,EAAE,GAAG,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;AACjE,CAAC;AACD,MAAM,UAAU,cAAc,CAAC,KAAiB;IAC9C,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,39 @@
1
+ export interface CompileOutcome {
2
+ /** Image `src` values observed in the latest Document, if any compiled. */
3
+ readonly imageSources: readonly string[];
4
+ }
5
+ export interface WatchDriverOptions {
6
+ /** Canonical Source path. */
7
+ readonly sourcePath: string;
8
+ /** Canonical project root. */
9
+ readonly projectRoot: string;
10
+ /** Milliseconds to coalesce rapid change notifications. */
11
+ readonly debounceMs: number;
12
+ /** Resolve watch paths for the latest compile outcome. */
13
+ readonly watchPathsFor: (outcome: CompileOutcome | undefined) => Promise<{
14
+ readonly files: readonly string[];
15
+ readonly missing: readonly string[];
16
+ }>;
17
+ readonly onChange: () => void;
18
+ readonly onWatcherFailed: (error: unknown) => void;
19
+ }
20
+ /**
21
+ * Serialized, coalescing file watcher. Change notifications during an active
22
+ * compile collapse into one scheduled follow-up cycle; the caller serializes
23
+ * compiles and invokes `onChange` per settled trigger.
24
+ */
25
+ export declare class WatchDriver {
26
+ private readonly options;
27
+ private watchers;
28
+ private timer;
29
+ private closed;
30
+ private failed;
31
+ private constructor();
32
+ static start(options: WatchDriverOptions, initialOutcome: CompileOutcome | undefined): Promise<WatchDriver>;
33
+ /** Signal that the current compile settled; watch paths refresh. */
34
+ rearm(outcome: CompileOutcome | undefined): Promise<void>;
35
+ private observe;
36
+ private schedule;
37
+ private fail;
38
+ close(): Promise<void>;
39
+ }
@@ -0,0 +1,117 @@
1
+ import { watch } from "node:fs";
2
+ import { stat } from "node:fs/promises";
3
+ import { dirname, resolve } from "node:path";
4
+ async function nearestExistingAncestor(candidate) {
5
+ let current = candidate;
6
+ for (;;) {
7
+ try {
8
+ await stat(current);
9
+ return current;
10
+ }
11
+ catch {
12
+ const parent = dirname(current);
13
+ if (parent === current)
14
+ return current;
15
+ current = parent;
16
+ }
17
+ }
18
+ }
19
+ /**
20
+ * Serialized, coalescing file watcher. Change notifications during an active
21
+ * compile collapse into one scheduled follow-up cycle; the caller serializes
22
+ * compiles and invokes `onChange` per settled trigger.
23
+ */
24
+ export class WatchDriver {
25
+ options;
26
+ watchers = [];
27
+ timer;
28
+ closed = false;
29
+ failed = false;
30
+ constructor(options) {
31
+ this.options = options;
32
+ }
33
+ static async start(options, initialOutcome) {
34
+ const driver = new WatchDriver(options);
35
+ await driver.rearm(initialOutcome);
36
+ return driver;
37
+ }
38
+ /** Signal that the current compile settled; watch paths refresh. */
39
+ async rearm(outcome) {
40
+ if (this.closed || this.failed)
41
+ return;
42
+ for (const watcher of this.watchers)
43
+ watcher.close();
44
+ this.watchers = [];
45
+ let paths;
46
+ try {
47
+ paths = await this.options.watchPathsFor(outcome);
48
+ }
49
+ catch (error) {
50
+ this.fail(error);
51
+ return;
52
+ }
53
+ const targets = new Set(paths.files);
54
+ targets.add(this.options.sourcePath);
55
+ const ancestors = new Set();
56
+ for (const missing of paths.missing) {
57
+ const parent = dirname(resolve(missing));
58
+ ancestors.add(await nearestExistingAncestor(parent));
59
+ }
60
+ ancestors.add(await nearestExistingAncestor(dirname(this.options.sourcePath)));
61
+ for (const target of [...targets].sort())
62
+ this.observe(target);
63
+ for (const ancestor of [...ancestors].sort()) {
64
+ if (!targets.has(ancestor))
65
+ this.observe(ancestor);
66
+ }
67
+ }
68
+ observe(target) {
69
+ if (this.closed || this.failed)
70
+ return;
71
+ let watcher;
72
+ try {
73
+ watcher = watch(target, { persistent: true }, () => this.schedule());
74
+ }
75
+ catch (error) {
76
+ this.fail(error);
77
+ return;
78
+ }
79
+ watcher.on("error", (error) => this.fail(error));
80
+ this.watchers.push(watcher);
81
+ }
82
+ schedule() {
83
+ if (this.closed || this.failed)
84
+ return;
85
+ if (this.timer !== undefined)
86
+ clearTimeout(this.timer);
87
+ this.timer = setTimeout(() => {
88
+ this.timer = undefined;
89
+ this.options.onChange();
90
+ }, this.options.debounceMs);
91
+ this.timer.unref?.();
92
+ }
93
+ fail(error) {
94
+ if (this.closed || this.failed)
95
+ return;
96
+ this.failed = true;
97
+ if (this.timer !== undefined) {
98
+ clearTimeout(this.timer);
99
+ this.timer = undefined;
100
+ }
101
+ for (const watcher of this.watchers)
102
+ watcher.close();
103
+ this.watchers = [];
104
+ this.options.onWatcherFailed(error);
105
+ }
106
+ async close() {
107
+ this.closed = true;
108
+ if (this.timer !== undefined) {
109
+ clearTimeout(this.timer);
110
+ this.timer = undefined;
111
+ }
112
+ for (const watcher of this.watchers)
113
+ watcher.close();
114
+ this.watchers = [];
115
+ }
116
+ }
117
+ //# sourceMappingURL=watch-loop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch-loop.js","sourceRoot":"","sources":["../src/watch-loop.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "@aruzone/aze-forge",
3
+ "version": "0.1.0",
4
+ "description": "Deterministic AzeMark compiler: readable source in, self-contained HTML, SVG, PNG, and PDF artifacts out.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/aruzone/aze-forge.git"
9
+ },
10
+ "keywords": [
11
+ "azemark",
12
+ "markdown",
13
+ "publishing",
14
+ "pdf",
15
+ "svg"
16
+ ],
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "type": "module",
21
+ "bin": {
22
+ "azeforge": "./dist/cli.js"
23
+ },
24
+ "exports": {
25
+ ".": {
26
+ "types": "./dist/index.d.ts",
27
+ "import": "./dist/index.js"
28
+ }
29
+ },
30
+ "files": [
31
+ "dist",
32
+ "schemas"
33
+ ],
34
+ "engines": {
35
+ "node": ">=22 <23 || >=24 <25"
36
+ },
37
+ "scripts": {
38
+ "build": "tsc -p tsconfig.json",
39
+ "typecheck": "tsc -p tsconfig.json --noEmit",
40
+ "prepublishOnly": "npm run build --silent",
41
+ "test": "npm run build --silent && node --test test/*.test.mjs",
42
+ "test:matrix": "node --test --test-reporter=tap test/capabilities.test.mjs test/cli.test.mjs test/compatibility.test.mjs test/compiler.test.mjs test/equation.test.mjs test/fail-closed.test.mjs test/format.test.mjs test/installed-cli.test.mjs test/schemas.test.mjs test/theme-assets.test.mjs test/watch-serve.test.mjs",
43
+ "test:browser-smoke": "node --test --test-reporter=tap test/browser-smoke.test.mjs",
44
+ "test:canonical": "node scripts/acceptance.mjs --json",
45
+ "test:canonical-suite": "node --test --test-reporter=tap test/acceptance.test.mjs test/mermaid.test.mjs test/pdf.test.mjs test/png.test.mjs test/svg.test.mjs",
46
+ "test:compiler": "npm run build --silent && node --test test/compiler.test.mjs",
47
+ "test:cli": "npm run build --silent && node --test test/cli.test.mjs",
48
+ "test:acceptance": "npm run build --silent && node --test test/acceptance.test.mjs",
49
+ "acceptance": "node scripts/acceptance.mjs",
50
+ "acceptance:refresh": "node scripts/acceptance.mjs --refresh"
51
+ },
52
+ "dependencies": {
53
+ "@fontsource/inter": "5.3.0",
54
+ "@fontsource/jetbrains-mono": "5.2.8",
55
+ "@puppeteer/browsers": "3.2.2",
56
+ "katex": "0.18.5",
57
+ "mermaid": "11.17.2",
58
+ "puppeteer": "25.10.0",
59
+ "puppeteer-core": "25.10.0",
60
+ "saxes": "6.0.0",
61
+ "yaml": "2.9.0"
62
+ },
63
+ "devDependencies": {
64
+ "@types/node": "24.3.0",
65
+ "typescript": "5.9.2"
66
+ },
67
+ "allowScripts": {
68
+ "puppeteer@25.10.0": true
69
+ }
70
+ }
@@ -0,0 +1,104 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "azeforge.acceptance/v1",
4
+ "type": "object",
5
+ "required": [
6
+ "schema",
7
+ "schemaVersion",
8
+ "catalog",
9
+ "entries"
10
+ ],
11
+ "additionalProperties": false,
12
+ "properties": {
13
+ "schema": {
14
+ "const": "azeforge.acceptance/v1"
15
+ },
16
+ "schemaVersion": {
17
+ "const": 1
18
+ },
19
+ "catalog": {
20
+ "type": "object",
21
+ "required": [
22
+ "id",
23
+ "version"
24
+ ],
25
+ "additionalProperties": false,
26
+ "properties": {
27
+ "id": {
28
+ "const": "azeforge.acceptance/v1"
29
+ },
30
+ "version": {
31
+ "const": 1
32
+ }
33
+ }
34
+ },
35
+ "entries": {
36
+ "type": "array",
37
+ "minItems": 1,
38
+ "items": {
39
+ "type": "object",
40
+ "required": [
41
+ "id",
42
+ "gate",
43
+ "area",
44
+ "given",
45
+ "when",
46
+ "then",
47
+ "evidence",
48
+ "required",
49
+ "contracts"
50
+ ],
51
+ "additionalProperties": false,
52
+ "properties": {
53
+ "id": {
54
+ "type": "string",
55
+ "pattern": "^P0[A-Z0-9]*-[A-Z]+-[0-9]{3}$"
56
+ },
57
+ "gate": {
58
+ "enum": [
59
+ "p0",
60
+ "p0.5"
61
+ ]
62
+ },
63
+ "area": {
64
+ "type": "string",
65
+ "minLength": 1
66
+ },
67
+ "given": {
68
+ "type": "string",
69
+ "minLength": 1
70
+ },
71
+ "when": {
72
+ "type": "string",
73
+ "minLength": 1
74
+ },
75
+ "then": {
76
+ "type": "array",
77
+ "minItems": 1,
78
+ "items": {
79
+ "type": "string",
80
+ "minLength": 1
81
+ }
82
+ },
83
+ "evidence": {
84
+ "enum": [
85
+ "automated",
86
+ "manual"
87
+ ]
88
+ },
89
+ "required": {
90
+ "const": true
91
+ },
92
+ "contracts": {
93
+ "type": "array",
94
+ "minItems": 1,
95
+ "items": {
96
+ "type": "string",
97
+ "minLength": 1
98
+ }
99
+ }
100
+ }
101
+ }
102
+ }
103
+ }
104
+ }