@flatkit/compiler 0.22.0 → 0.24.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.
@@ -1,5 +1,50 @@
1
- import { Diagnostic, ScriptUnit } from '@flatkit/engine/dsl';
2
1
  import { Doc, EditFrame } from '@flatkit/types';
2
+ import { MediaMap } from './compile.js';
3
+ import { Diagnostic, ScriptUnit } from '@flatkit/engine/dsl';
4
+
5
+ /** One diagnostic, positioned in the AUTHOR'S source. `scope` is `scene` or `object "Name"`. */
6
+ type CheckDiagnostic = {
7
+ scope: string;
8
+ line: number;
9
+ col: number;
10
+ severity: 'error' | 'warning';
11
+ message: string;
12
+ };
13
+ type CheckOptions = {
14
+ /** Text of each `.flat` symbol library the program draws on — the CLI auto-discovers them beside the file. */
15
+ assetSrcs?: string[];
16
+ /** Declared media, by path (only affects the returned Doc; diagnostics do not depend on it). */
17
+ media?: MediaMap;
18
+ };
19
+ type CheckResult = {
20
+ /** `false` as soon as one diagnostic is an error — the exit code of `flatc --check`. Warnings do not block. */
21
+ ok: boolean;
22
+ errors: number;
23
+ warnings: number;
24
+ diagnostics: CheckDiagnostic[];
25
+ /** The diagnostics as `flatc` prints them (`''` when there is nothing to say). */
26
+ report: string;
27
+ /** The compiled program, or `null` if the parser rejected the source outright. */
28
+ doc: Doc | null;
29
+ };
30
+ /** The diagnostics as `flatc` prints them: one `[scope] line:col: level: message` per line. */
31
+ declare const formatDiagnostics: (diagnostics: CheckDiagnostic[]) => string;
32
+ /**
33
+ * Every diagnostic of a program that HAS compiled: the source-level passes, then the semantic lint of the
34
+ * whole Doc (read against `src`, so positions point into the author's file). Exact-duplicate lines are
35
+ * dropped — a scene parse error is legitimately seen by both paths, which now both read the source.
36
+ */
37
+ declare function programDiagnostics(doc: Doc, src: string): CheckDiagnostic[];
38
+ /**
39
+ * Check a `.flatink` program — the same pass as `flatc --check`, on a string. Never throws: a source the
40
+ * parser rejects outright comes back as a diagnostic with `doc: null`, not an exception.
41
+ *
42
+ * ```ts
43
+ * const { ok, report } = checkProgram(srcFromAnLLM)
44
+ * if (!ok) regenerate(report) // the report is the repair prompt
45
+ * ```
46
+ */
47
+ declare function checkProgram(src: string, opts?: CheckOptions): CheckResult;
3
48
 
4
49
  type LintContext = {
5
50
  /** Known variables in addition to those declared/assigned in the source. */
@@ -68,10 +113,12 @@ declare function docLayoutWarnings(doc: Doc): {
68
113
  diag: Diagnostic;
69
114
  }[];
70
115
  /** Semantic lint of a whole Doc (all the scopes) -> diagnostics labeled by scope.
71
- * The scope program contains `object` blocks (outside DSL) -> we lint each region
72
- * separately and re-project the lines (like the editor, cf. CodeEditor.lintFile).
73
- * Adds the structural warnings (phantom drop zones, dead variables). */
74
- declare function lintDoc(doc: Doc): {
116
+ * A scope's text contains `object` blocks (outside DSL) -> we lint each region separately and re-project
117
+ * the lines. `src` = the program SOURCE, when the caller has it (the CLI): the scene scope is then read
118
+ * from it, so positions and scopes describe the author's file. Without it the scene scope falls back to
119
+ * the text rebuilt from the Doc — right for the editor, where that rebuilt text IS the file being edited
120
+ * (cf. CodeEditor.lintFile). Adds the structural warnings (phantom drop zones, dead variables). */
121
+ declare function lintDoc(doc: Doc, src?: string): {
75
122
  scope: string;
76
123
  diag: Diagnostic;
77
124
  }[];
@@ -82,10 +129,11 @@ declare function docModifierWarnings(doc: Doc): {
82
129
  scope: string;
83
130
  diag: Diagnostic;
84
131
  }[];
85
- /** Lint report of a Doc ready to display: `''` = no issue, otherwise `[scope] line:col: level: message`. */
86
- declare function lintDocReport(doc: Doc): string;
132
+ /** Lint report of a Doc ready to display: `''` = no issue, otherwise `[scope] line:col: level: message`.
133
+ * Pass `src` (the program source) to get positions that point INTO IT rather than into a rebuilt program. */
134
+ declare function lintDocReport(doc: Doc, src?: string): string;
87
135
  /** `true` if the Doc has at least one ERROR (warnings alone do not block). */
88
- declare function docHasErrors(doc: Doc): boolean;
136
+ declare function docHasErrors(doc: Doc, src?: string): boolean;
89
137
 
90
138
  /** Splits a scope file: the `object "name" { … }` blocks on one side, the REST (var + lifecycle) on the other. */
91
139
  declare function splitScopeProgram(text: string): {
@@ -110,4 +158,4 @@ declare function joinScopeProgram(rest: string, objects: {
110
158
  body: string;
111
159
  }[]): string;
112
160
 
113
- export { type LintContext, allScopeVariables, docCelLayerWarnings, docHasErrors, docLayoutWarnings, docLintContext, docModifierWarnings, docPaintParamWarnings, docStructureWarnings, formatObjectBlock, joinScopeProgram, lint, lintDoc, lintDocReport, lintReport, localVariables, scopeProgram, scopeRegions, splitScopeProgram };
161
+ export { type CheckDiagnostic, type CheckOptions, type CheckResult, type LintContext, allScopeVariables, checkProgram, docCelLayerWarnings, docHasErrors, docLayoutWarnings, docLintContext, docModifierWarnings, docPaintParamWarnings, docStructureWarnings, formatDiagnostics, formatObjectBlock, joinScopeProgram, lint, lintDoc, lintDocReport, lintReport, localVariables, programDiagnostics, scopeProgram, scopeRegions, splitScopeProgram };
package/dist/analysis.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  allScopeVariables,
3
+ checkProgram,
3
4
  docCelLayerWarnings,
4
5
  docHasErrors,
5
6
  docLayoutWarnings,
@@ -7,6 +8,7 @@ import {
7
8
  docModifierWarnings,
8
9
  docPaintParamWarnings,
9
10
  docStructureWarnings,
11
+ formatDiagnostics,
10
12
  formatObjectBlock,
11
13
  joinScopeProgram,
12
14
  lint,
@@ -14,12 +16,15 @@ import {
14
16
  lintDocReport,
15
17
  lintReport,
16
18
  localVariables,
19
+ programDiagnostics,
17
20
  scopeProgram,
18
21
  scopeRegions,
19
22
  splitScopeProgram
20
- } from "./chunk-VB3ZWCNP.js";
23
+ } from "./chunk-7KBWT2PA.js";
24
+ import "./chunk-KXKX2RMX.js";
21
25
  export {
22
26
  allScopeVariables,
27
+ checkProgram,
23
28
  docCelLayerWarnings,
24
29
  docHasErrors,
25
30
  docLayoutWarnings,
@@ -27,6 +32,7 @@ export {
27
32
  docModifierWarnings,
28
33
  docPaintParamWarnings,
29
34
  docStructureWarnings,
35
+ formatDiagnostics,
30
36
  formatObjectBlock,
31
37
  joinScopeProgram,
32
38
  lint,
@@ -34,6 +40,7 @@ export {
34
40
  lintDocReport,
35
41
  lintReport,
36
42
  localVariables,
43
+ programDiagnostics,
37
44
  scopeProgram,
38
45
  scopeRegions,
39
46
  splitScopeProgram
@@ -1,7 +1,9 @@
1
1
  import {
2
2
  docHasErrors,
3
- lintDocReport
4
- } from "./chunk-VB3ZWCNP.js";
3
+ formatDiagnostics,
4
+ lintDocReport,
5
+ programDiagnostics
6
+ } from "./chunk-7KBWT2PA.js";
5
7
  import {
6
8
  compileFlatpack,
7
9
  packToJSON
@@ -10,7 +12,7 @@ import {
10
12
  // src/cli/flatc.ts
11
13
  import { readFileSync, writeFileSync, existsSync, readdirSync, watch, mkdirSync, copyFileSync } from "fs";
12
14
  import { resolve, dirname, basename, extname, join, relative, isAbsolute } from "path";
13
- import { parseProgramFull, parseFlatLib, behaviorDiagnostics } from "@flatkit/engine/flatFormat";
15
+ import { parseProgramFull, parseFlatLib } from "@flatkit/engine/flatFormat";
14
16
  import { hasPackage } from "@flatkit/engine/stdlib";
15
17
  import { parseUnits } from "@flatkit/engine/dsl";
16
18
  import { sanitizeDoc } from "@flatkit/engine/validateDoc";
@@ -62,6 +64,8 @@ Usage:
62
64
  play with sameOriginAssetResolver(<flatpackUrl>))
63
65
  --check semantic lint only (no .flatpack); exits \u22600 on ERROR (warnings do not stop). Lints a
64
66
  program .flatink OR an asset library .flat (per-symbol; several .flat are merged)
67
+ --no-libs do NOT auto-discover the .flat files sitting next to the program (use it in a working
68
+ folder, where a neighbouring scratch file is not a dependency)
65
69
  --watch recompile on every change in the folder (agent \u2192 player loop)
66
70
  --play run the file WITHOUT a canvas, replay --script and print { sends, vars } (JSON)
67
71
  --trace (with --play) HUMAN-READABLE log per gesture: emitted sends + variable diff (debug)
@@ -93,12 +97,12 @@ Usage:
93
97
  Media referenced by 'asset "id" "path" kind' are embedded (paths relative to the program).
94
98
  `);
95
99
  }
96
- function buildDocFromProgram(programPath, explicitFlats = [], assetMode = "inline", assetsDir = "") {
100
+ function buildDocFromProgram(programPath, explicitFlats = [], assetMode = "inline", assetsDir = "", noLibs = false) {
97
101
  const baseDir = dirname(programPath);
98
102
  const programSrc = readFileSync(programPath, "utf8");
99
103
  const prog = parseProgramFull(programSrc);
100
104
  const flatPaths = new Set(explicitFlats.map((p) => resolve(p)));
101
- if (!flatPaths.size) for (const f of readdirSync(baseDir).filter((f2) => f2.endsWith(".flat"))) flatPaths.add(join(baseDir, f));
105
+ if (!flatPaths.size && !noLibs) for (const f of readdirSync(baseDir).filter((f2) => f2.endsWith(".flat"))) flatPaths.add(join(baseDir, f));
102
106
  const pkgFunctions = [];
103
107
  const localResolved = /* @__PURE__ */ new Set();
104
108
  for (const name of prog.imports ?? []) {
@@ -123,7 +127,17 @@ function buildDocFromProgram(programPath, explicitFlats = [], assetMode = "inlin
123
127
  else process.stderr.write(`flatc: package not found: "${name}" (neither stdlib, nor ${name}.flatink / ${name}.flat)
124
128
  `);
125
129
  }
126
- const assetSrcs = [...flatPaths].map((p) => readFileSync(p, "utf8"));
130
+ const assetSrcs = [...flatPaths].map((p) => {
131
+ const src = readFileSync(p, "utf8");
132
+ try {
133
+ parseFlatLib(src);
134
+ } catch (e) {
135
+ throw new Error(`${basename(p)}: ${e.message} (pass --no-libs to ignore the .flat files sitting next to the program)`, { cause: e });
136
+ }
137
+ if (programConstructsIn(src).length) process.stderr.write(`flatc: ${basename(p)}: looks like a PROGRAM saved as .flat \u2014 loaded as a symbol library, so its scene/object blocks are ignored. Rename it to .flatink, or pass --no-libs.
138
+ `);
139
+ return src;
140
+ });
127
141
  const media = {};
128
142
  const mediaCopies = [];
129
143
  for (const a of prog.assets ?? []) {
@@ -151,27 +165,27 @@ function buildDocFromProgram(programPath, explicitFlats = [], assetMode = "inlin
151
165
  if (pkgFunctions.length) doc = { ...doc, functions: [...doc.functions ?? [], ...pkgFunctions] };
152
166
  const stdImports = (doc.imports ?? []).filter(hasPackage);
153
167
  doc = { ...doc, imports: stdImports.length ? stdImports : void 0 };
154
- return { doc, flatLibs: flatPaths.size, packages: localResolved.size, media: Object.keys(media).length, mediaCopies, behaviorDiags: behaviorDiagnostics(programSrc) };
168
+ return { doc, flatLibs: flatPaths.size, packages: localResolved.size, media: Object.keys(media).length, mediaCopies, src: programSrc };
155
169
  }
156
- function compileOnce(programPath, explicitFlats, out, checkOnly, assetMode = "inline") {
170
+ function compileOnce(programPath, explicitFlats, out, checkOnly, assetMode = "inline", noLibs = false) {
157
171
  const outPath = out ? resolve(out) : join(dirname(programPath), basename(programPath, extname(programPath)) + ".flatpack");
158
172
  const assetsDir = assetMode === "external" ? basename(outPath, extname(outPath)) + ".assets" : "";
159
173
  let built;
160
174
  try {
161
- built = buildDocFromProgram(programPath, explicitFlats, assetMode, assetsDir);
175
+ built = buildDocFromProgram(programPath, explicitFlats, assetMode, assetsDir, noLibs);
162
176
  } catch (e) {
163
177
  process.stderr.write(`flatc: compile error: ${e.message}
164
178
  `);
165
179
  return 1;
166
180
  }
167
181
  const { doc } = built;
168
- const behaviorReport = built.behaviorDiags.map(({ scope, diag }) => `[${scope}] ${diag.line}:${diag.col}: error: ${diag.message}`).join("\n");
169
- const report = [...new Set([behaviorReport, lintDocReport(doc)].flatMap((r) => r.split("\n")).filter(Boolean))].join("\n");
170
- const hasErrors = docHasErrors(doc) || built.behaviorDiags.length > 0;
182
+ const diagnostics = programDiagnostics(doc, built.src);
183
+ const report = formatDiagnostics(diagnostics);
184
+ const hasErrors = diagnostics.some((d) => d.severity === "error");
171
185
  if (checkOnly) {
172
186
  if (report) process.stderr.write(report + "\n");
173
187
  if (hasErrors) return 1;
174
- const warnings = report ? report.split("\n").filter(Boolean).length : 0;
188
+ const warnings = diagnostics.length;
175
189
  process.stdout.write(`flatc: check passed \u2713${warnings ? ` \xB7 ${warnings} warning(s)` : ""}
176
190
  `);
177
191
  return 0;
@@ -190,6 +204,12 @@ function compileOnce(programPath, explicitFlats, out, checkOnly, assetMode = "in
190
204
  `);
191
205
  return 0;
192
206
  }
207
+ function programConstructsIn(src) {
208
+ const found = [];
209
+ if (/^[ \t]*scene\s*\{/m.test(src)) found.push("a `scene { \u2026 }` block");
210
+ if (/^[ \t]*object\s+"/m.test(src)) found.push('`object "\u2026" { \u2026 }` blocks');
211
+ return found;
212
+ }
193
213
  function checkFlatLibs(flatPaths) {
194
214
  const symbols = [];
195
215
  for (const p of flatPaths) {
@@ -198,6 +218,12 @@ function checkFlatLibs(flatPaths) {
198
218
  src = readFileSync(p, "utf8");
199
219
  } catch (e) {
200
220
  process.stderr.write(`flatc: cannot read: ${e.message}
221
+ `);
222
+ return 1;
223
+ }
224
+ const disguised = programConstructsIn(src);
225
+ if (disguised.length) {
226
+ process.stderr.write(`flatc: ${basename(p)}: this is a PROGRAM, not a symbol library \u2014 it contains ${disguised.join(" and ")}, which a .flat never carries and which --check therefore does NOT verify. Rename it to .flatink.
201
227
  `);
202
228
  return 1;
203
229
  }
@@ -422,7 +448,7 @@ async function previewOnce(flatPath, symbolName, out, frame, vars, scale, steps,
422
448
  function run(argv) {
423
449
  const args = argv.slice(2);
424
450
  let out = "", scriptPath = "", symbolName = "";
425
- let checkOnly = false, doWatch = false, doPlay = false, doRender = false, doTrace = false, doPreview = false;
451
+ let checkOnly = false, doWatch = false, doPlay = false, doRender = false, doTrace = false, doPreview = false, noLibs = false;
426
452
  let frame = 0, scale = 2, steps = 0, pad = 24;
427
453
  let scaleAuto = false;
428
454
  let bboxMode = "all";
@@ -436,6 +462,7 @@ function run(argv) {
436
462
  else if (a === "--script") scriptPath = resolve(args[++i] ?? "");
437
463
  else if (a === "--assets") assetMode = args[++i] === "external" ? "external" : "inline";
438
464
  else if (a === "--check") checkOnly = true;
465
+ else if (a === "--no-libs") noLibs = true;
439
466
  else if (a === "--watch") doWatch = true;
440
467
  else if (a === "--play") doPlay = true;
441
468
  else if (a === "--trace") doTrace = true;
@@ -474,7 +501,7 @@ function run(argv) {
474
501
  if (doPreview) return previewOnce(filePath, symbolName, out, frame, vars, scale, steps, doRender, pad, bboxMode, setSpec, scaleAuto);
475
502
  if (doRender) return renderOnce(filePath, out, frame, vars, scale, steps, scaleAuto);
476
503
  if (doPlay) return playOnce(filePath, scriptPath, doTrace);
477
- const action = checkOnly && filePath.endsWith(".flat") ? () => checkFlatLibs([filePath, ...explicitFlats]) : () => compileOnce(filePath, explicitFlats, out, checkOnly, assetMode);
504
+ const action = checkOnly && filePath.endsWith(".flat") ? () => checkFlatLibs([filePath, ...explicitFlats]) : () => compileOnce(filePath, explicitFlats, out, checkOnly, assetMode, noLibs);
478
505
  if (doWatch) {
479
506
  const code = action();
480
507
  const baseDir = dirname(filePath);
@@ -494,4 +521,4 @@ function run(argv) {
494
521
  export {
495
522
  run
496
523
  };
497
- //# sourceMappingURL=chunk-AVUH5CVJ.js.map
524
+ //# sourceMappingURL=chunk-5WQFNGZQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/flatc.ts"],"sourcesContent":["// ─────────────────────────────────────────────────────────────────────────────\n// flatc — the \"modern SWF\" command-line compiler.\n//\n// The VSCode-first flow: you write a `.flatink` program (composition + logic, DSL)\n// + `.flat` asset libs (visuals, exported by the editor) + media, then:\n//\n// flatc game.flatink hero.flat decor.flat -o game.flatpack\n//\n// → a single `.flatpack` (the baked Doc as JSON) that the player runs. Media referenced\n// by `asset \"id\" \"path\" kind` are EMBEDDED (paths relative to the program).\n// ─────────────────────────────────────────────────────────────────────────────\nimport { readFileSync, writeFileSync, existsSync, readdirSync, watch, mkdirSync, copyFileSync } from 'node:fs'\nimport { resolve, dirname, basename, extname, join, relative, isAbsolute } from 'node:path'\nimport { compileFlatpack, packToJSON, type MediaMap } from '../compile'\nimport { parseProgramFull, parseFlatLib } from '@flatkit/engine/flatFormat'\nimport { hasPackage } from '@flatkit/engine/stdlib'\nimport { parseUnits } from '@flatkit/engine/dsl'\nimport { sanitizeDoc } from '@flatkit/engine/validateDoc'\nimport { unitsToFunctions } from '@flatkit/engine/scriptDoc'\nimport { containerBBox, containerBBoxUnion } from '@flatkit/engine/groups'\nimport { isInstance, isGroup } from '@flatkit/engine/layers'\nimport { IDENTITY } from '@flatkit/engine/transform'\nimport { lintDocReport, docHasErrors } from '../programDoc'\nimport { formatDiagnostics, programDiagnostics } from '../check'\nimport { playHeadless, type Gesture } from '@flatkit/player/debug'\nimport type { FuncDef } from '@flatkit/engine/actions'\nimport type { Doc, Instance, Item, Layer, SymbolDef } from '@flatkit/types'\n\nconst MIME: Record<string, string> = {\n '.png': 'image/png', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.gif': 'image/gif',\n '.webp': 'image/webp', '.svg': 'image/svg+xml', '.avif': 'image/avif',\n '.mp3': 'audio/mpeg', '.wav': 'audio/wav', '.ogg': 'audio/ogg', '.m4a': 'audio/mp4',\n // Fonts (RFC 8081 media types) — matches the editor's import (`font/woff2` default, FontFace API).\n '.woff2': 'font/woff2', '.woff': 'font/woff', '.ttf': 'font/ttf', '.otf': 'font/otf',\n // NB: video (.mp4/.webm/…) intentionally omitted — no video runtime in the editor or player yet.\n}\nconst mimeFor = (path: string): string => MIME[extname(path).toLowerCase()] ?? 'application/octet-stream'\n\n/**\n * True if `target` resolves to a file inside `baseDir` (or baseDir itself). Guards against a hostile\n * program escaping its folder via `../` in a media path or a `use` package name — compiling an untrusted\n * `.flatink` must never read (and embed) arbitrary host files.\n */\nfunction isWithin(baseDir: string, target: string): boolean {\n const rel = relative(baseDir, target)\n return rel === '' || (!rel.startsWith('..') && !isAbsolute(rel))\n}\n\nfunction printHelp(): void {\n process.stdout.write(`flatc — compile a FlatInk program into a .flatpack\n\nUsage:\n flatc <program.flatink> [assets.flat …] [-o output.flatpack]\n flatc <program.flatink> --watch\n flatc --play <program.flatink | scene.flatpack> --script <gestures.json>\n flatc --render <program.flatink | scene.flatpack> -o out.png [--frame N] [--at k=v[,k2=v2]] [--scale S]\n flatc --preview <library.flat> [--symbol NAME] [-o out.flatpack | --render -o out.png]\n flatc <library.flat> [more.flat …] --check\n\n program.flatink the program (composition + logic, text DSL)\n assets.flat visual asset libs (default: every .flat in the program's folder)\n -o, --out output file (default: <program>.flatpack — the CANONICAL name, JSON inside)\n --assets MODE media baking: 'inline' (default, base64 in the .flatpack) or 'external'\n (sidecar <out>.assets/ folder; asset.data = relative key — serve the folder and\n play with sameOriginAssetResolver(<flatpackUrl>))\n --check semantic lint only (no .flatpack); exits ≠0 on ERROR (warnings do not stop). Lints a\n program .flatink OR an asset library .flat (per-symbol; several .flat are merged)\n --no-libs do NOT auto-discover the .flat files sitting next to the program (use it in a working\n folder, where a neighbouring scratch file is not a dependency)\n --watch recompile on every change in the folder (agent → player loop)\n --play run the file WITHOUT a canvas, replay --script and print { sends, vars } (JSON)\n --trace (with --play) HUMAN-READABLE log per gesture: emitted sends + variable diff (debug)\n --script <f> JSON gesture script: [{ \"type\": \"down|move|up|cancel\", \"x\", \"y\" }, { \"type\": \"set\", \"name\", \"value\" }, { \"type\": \"wait\", \"frames\": N }, { \"type\": \"wheel\", \"dy\": N }]\n semantic (by NAME, the engine resolves coords): { \"type\": \"drag\", \"source\", \"target\" } · { \"type\": \"tap\", \"target\" }\n · { \"type\": \"scratch\", \"target\" } (sweeps a reveal zone) · { \"type\": \"connect\", \"source\", \"target\" } (pulls a link wire)\n { \"type\": \"key\", \"name\": \"ArrowRight\", \"frames\": N } holds a key (keys.<name> = 1) N steps, then releases it\n \"wait\" lets the simulation run N fixed steps (60 Hz): \"every frame\" + playhead advance like in real playback\n \"expect\" self-verifies: { \"type\": \"expect\", \"sends\": [\"done\"], \"vars\": { \"score\": 3 } } → exits ≠0 on mismatch\n (sends = sequence of names emitted SINCE the last expect; vars = current state). Great in CI.\n --render render a PNG IMAGE (headless skia): see what we draw (positioning)\n --preview wrap ONE symbol of a <library.flat> into a playable Doc (a single centered instance on an\n auto-sized stage) → a .flatpack to drop in the browser player, or a PNG with --render.\n No wrapper .flatink to author by hand. Output defaults to <library>.<symbol>.flatpack/.png\n --symbol NAME (with --preview) which symbol to wrap (default: the first in the lib)\n --bbox all|frame0 (with --preview) auto-size to the UNION over all frames (default 'all', no clipping of\n drifting/rotating/growing motion) or just frame 0 ('frame0', the old behavior)\n --pad N (with --preview) padding in px around the symbol's bounds (default 24)\n --set p=v[,p2=v2] (with --preview) set the symbol's exposed params; a state param takes a state NAME\n or a number (e.g. --set door=open), others take a number → baked into the preview\n --frame N (with --render) target frame (default 0)\n --at k=v[,k2=v2] (with --render) force variables → capture a given state (e.g. a step of an escape)\n --steps N (with --render) run N fixed sim steps (60 Hz, every-frame) BEFORE capture → see a\n stateful act unfold without forcing every derived variable by hand in --at\n --scale S|auto (with --render) resolution factor (default 2); 'auto' picks one from the canvas size\n (enlarges small/thin assets so fine filaments stay legible, large assets stay 1x)\n -h, --help this help\n\nMedia referenced by 'asset \"id\" \"path\" kind' are embedded (paths relative to the program).\n`)\n}\n\n/** How media is baked: `inline` = base64 data-URI in the .flatpack; `external` = relative key + sidecar files. */\ntype AssetMode = 'inline' | 'external'\ntype MediaCopy = { src: string; key: string } // external mode: source file → relative key (forward slashes)\ntype BuildResult = { doc: Doc; flatLibs: number; packages: number; media: number; mediaCopies: MediaCopy[]; src: string }\n\n/**\n * Reads a `.flatink`, resolves libs/packages/media, compiles → standalone Doc. Throws on compile error.\n * `assetMode`: `inline` embeds each media as a base64 data-URI (default); `external` keeps `asset.data` as a\n * relative key (`<assetsDir>/<path>`) and returns the files to copy beside the .flatpack (no base64 bloat).\n */\nfunction buildDocFromProgram(programPath: string, explicitFlats: string[] = [], assetMode: AssetMode = 'inline', assetsDir = '', noLibs = false): BuildResult {\n const baseDir = dirname(programPath)\n const programSrc = readFileSync(programPath, 'utf8')\n const prog = parseProgramFull(programSrc)\n\n // .flat libs: explicit if provided, otherwise auto-discover the .flat files in the program's folder\n // (`--no-libs` opts out — in a working folder, a neighbouring scratch file is not a dependency).\n const flatPaths = new Set<string>(explicitFlats.map((p) => resolve(p)))\n if (!flatPaths.size && !noLibs) for (const f of readdirSync(baseDir).filter((f) => f.endsWith('.flat'))) flatPaths.add(join(baseDir, f))\n\n // PACKAGES: non-stdlib `use \"x\"` → local files inlined (x.flatink = functions, x.flat = symbols).\n const pkgFunctions: FuncDef[] = []\n const localResolved = new Set<string>()\n for (const name of prog.imports ?? []) {\n if (hasPackage(name)) continue // stdlib → left as a reference\n const fink = join(baseDir, name + '.flatink')\n const fflat = join(baseDir, name + '.flat')\n if (!isWithin(baseDir, fink) || !isWithin(baseDir, fflat)) { process.stderr.write(`flatc: package outside the program folder (ignored): \"${name}\"\\n`); continue }\n let found = false\n if (existsSync(fink)) { for (const f of unitsToFunctions(parseUnits(readFileSync(fink, 'utf8')).units)) pkgFunctions.push(f, { ...f, name: `${name}.${f.name}` }); found = true }\n if (existsSync(fflat)) { flatPaths.add(fflat); found = true }\n if (found) localResolved.add(name)\n else process.stderr.write(`flatc: package not found: \"${name}\" (neither stdlib, nor ${name}.flatink / ${name}.flat)\\n`)\n }\n // Parse each lib HERE so a failure names the FILE. Libs are auto-discovered from the folder, so the one\n // that fails is often a neighbour the author never mentioned — a bare \"compile error: …\" sent them hunting\n // through their own program for a fault that was never in it.\n const assetSrcs = [...flatPaths].map((p) => {\n const src = readFileSync(p, 'utf8')\n try { parseFlatLib(src) } catch (e) { throw new Error(`${basename(p)}: ${(e as Error).message} (pass --no-libs to ignore the .flat files sitting next to the program)`, { cause: e }) }\n if (programConstructsIn(src).length) process.stderr.write(`flatc: ${basename(p)}: looks like a PROGRAM saved as .flat — loaded as a symbol library, so its scene/object blocks are ignored. Rename it to .flatink, or pass --no-libs.\\n`)\n return src\n })\n\n // Media: each `asset … \"path\" …` resolved relative to the program. `inline` → base64 data-URI baked in;\n // `external` → `asset.data` becomes a relative key and the file is copied next to the .flatpack.\n const media: MediaMap = {}\n const mediaCopies: MediaCopy[] = []\n for (const a of prog.assets ?? []) {\n const mp = resolve(baseDir, a.data)\n if (!isWithin(baseDir, mp)) { process.stderr.write(`flatc: media outside the program folder (ignored): ${a.data}\\n`); continue }\n if (!existsSync(mp)) { process.stderr.write(`flatc: missing media (ignored): ${a.data}\\n`); continue }\n const mime = mimeFor(mp)\n if (assetMode === 'external') {\n const key = `${assetsDir}/${a.data.replace(/\\\\/g, '/')}` // URL-form relative key (resolved by the host)\n media[a.data] = { mime, data: key }\n mediaCopies.push({ src: mp, key })\n } else {\n media[a.data] = { mime, data: `data:${mime};base64,${readFileSync(mp).toString('base64')}` }\n }\n }\n\n let doc = compileFlatpack(programSrc, assetSrcs, media)\n if (pkgFunctions.length) doc = { ...doc, functions: [...(doc.functions ?? []), ...pkgFunctions] }\n const stdImports = (doc.imports ?? []).filter(hasPackage)\n doc = { ...doc, imports: stdImports.length ? stdImports : undefined }\n // The source travels with the Doc: the source-level passes (`programDiagnostics`) need the author's text,\n // since a parse-level drop and an `object` block binding to nothing leave no trace in the compiled Doc.\n return { doc, flatLibs: flatPaths.size, packages: localResolved.size, media: Object.keys(media).length, mediaCopies, src: programSrc }\n}\n\n/** Compile once (write or --check). Returns the exit code. */\nfunction compileOnce(programPath: string, explicitFlats: string[], out: string, checkOnly: boolean, assetMode: AssetMode = 'inline', noLibs = false): number {\n const outPath = out ? resolve(out) : join(dirname(programPath), basename(programPath, extname(programPath)) + '.flatpack')\n // External mode: sidecar folder next to the .flatpack, e.g. `game.flatpack` → `game.assets/`.\n const assetsDir = assetMode === 'external' ? basename(outPath, extname(outPath)) + '.assets' : ''\n let built: BuildResult\n try { built = buildDocFromProgram(programPath, explicitFlats, assetMode, assetsDir, noLibs) }\n catch (e) { process.stderr.write(`flatc: compile error: ${(e as Error).message}\\n`); return 1 }\n const { doc } = built\n // The SAME pass the `checkProgram` API runs — source-level diagnostics (statements the parser dropped,\n // `object` blocks binding to nothing) merged with the semantic lint of the Doc. Shared on purpose: a\n // check that lives only in the CLI is a check an integrator has to shell out for.\n const diagnostics = programDiagnostics(doc, built.src)\n const report = formatDiagnostics(diagnostics)\n const hasErrors = diagnostics.some((d) => d.severity === 'error')\n if (checkOnly) {\n if (report) process.stderr.write(report + '\\n')\n if (hasErrors) return 1\n // Success line deliberately avoids the word \"error\" (the report on a FAILURE already prints \"error\" to\n // stderr + exits ≠0) so a `grep error` over the output can't false-positive — the real signal is the exit\n // code; on success, only warnings remain (non-blocking), surfaced as a count.\n const warnings = diagnostics.length\n process.stdout.write(`flatc: check passed ✓${warnings ? ` · ${warnings} warning(s)` : ''}\\n`)\n return 0\n }\n if (report) process.stderr.write(report + '\\n') // compile anyway: diagnostics as warnings\n writeFileSync(outPath, packToJSON(doc))\n const outDir = dirname(outPath)\n for (const c of built.mediaCopies) {\n const dest = join(outDir, ...c.key.split('/'))\n if (!isWithin(outDir, dest)) continue // defensive: never write outside the output folder\n mkdirSync(dirname(dest), { recursive: true })\n copyFileSync(c.src, dest)\n }\n const where = assetMode === 'external' ? ` (external → ${assetsDir}/)` : ''\n process.stdout.write(`flatc: ${basename(outPath)} ✓ ${doc.symbols.length} symbol(s) · ${built.flatLibs} lib(s) · ${built.packages} package(s) · ${built.media} media${where}\\n`)\n return 0\n}\n\n/** PROGRAM-only constructs found in what is supposed to be a `.flat` symbol library. `parseFlatLib` reads a\n * `.flat` as a bag of symbols and silently ignores everything else, so a whole program saved under the wrong\n * extension parsed to \"0 symbol(s)\" and passed `--check` with nothing verified — the worst possible answer\n * for tooling, since a check written against the wrong extension ALWAYS passes and looks like a safety net.\n * Both constructs are anchored at line start: only a real block matches, not a mention inside a string. */\nfunction programConstructsIn(src: string): string[] {\n const found: string[] = []\n if (/^[ \\t]*scene\\s*\\{/m.test(src)) found.push('a `scene { … }` block')\n if (/^[ \\t]*object\\s+\"/m.test(src)) found.push('`object \"…\" { … }` blocks')\n return found\n}\n\n/**\n * `--check` for a `.flat` asset LIBRARY (one or several): parse via `parseFlatLib` (NOT the program parser,\n * which would choke on `symbol`/`params`/`layer`), merge the symbols into an empty-scene Doc, and run the SAME\n * Doc lint as a program -> per-symbol diagnostics (`[<Symbol>] line:col: …`). Reuses `lintDocReport`/\n * `docHasErrors`, so every existing check (params-in-expr, undeclared color param in a paint, unknown\n * functions/objects…) applies for free, with the same `[scope] line:col: level: msg` format and exit code.\n * No `behaviorDiagnostics` (those are scene-level — a pure lib has no scene).\n */\nfunction checkFlatLibs(flatPaths: string[]): number {\n const symbols: SymbolDef[] = []\n for (const p of flatPaths) {\n let src: string\n try { src = readFileSync(p, 'utf8') } catch (e) { process.stderr.write(`flatc: cannot read: ${(e as Error).message}\\n`); return 1 }\n const disguised = programConstructsIn(src)\n if (disguised.length) { // a PROGRAM saved as `.flat` — see programConstructsIn\n process.stderr.write(`flatc: ${basename(p)}: this is a PROGRAM, not a symbol library — it contains ${disguised.join(' and ')}, which a .flat never carries and which --check therefore does NOT verify. Rename it to .flatink.\\n`)\n return 1\n }\n try { symbols.push(...parseFlatLib(src).symbols) } // ids are uid-unique across calls -> safe to merge libs\n catch (e) { process.stderr.write(`flatc: ${basename(p)}: ${(e as Error).message}\\n`); return 1 } // a malformed lib -> a clean parse error (not \"[scene] …\")\n }\n const doc: Doc = { width: 1, height: 1, timeline: { fps: 24, durationFrames: 1, tracks: [] }, variables: {}, layers: [], symbols }\n const report = lintDocReport(doc) // scene scope is empty -> only per-symbol diagnostics\n if (report) process.stderr.write(report + '\\n')\n if (docHasErrors(doc)) return 1\n // \"check passed\", NOT \"no errors\" — the word \"error\" must not appear on success (a `grep error` trap); the\n // exit code is the signal, and any remaining lines are warnings (non-blocking), reported as a count.\n const warnings = report ? report.split('\\n').filter(Boolean).length : 0\n process.stdout.write(`flatc: check passed ✓ ${symbols.length} symbol(s)${warnings ? ` · ${warnings} warning(s)` : ''}\\n`)\n return 0\n}\n\n/** Loads a Doc from a `.flatink` (compiled) or a `.flatpack`/`.flatpack.json` (already-baked JSON). */\nfunction loadDoc(filePath: string): Doc {\n if (filePath.endsWith('.flatink')) return buildDocFromProgram(filePath).doc\n // .flatpack (canonical) or .flatpack.json (alias): untrusted JSON → normalize before use.\n return sanitizeDoc(JSON.parse(readFileSync(filePath, 'utf8')))\n}\n\n/** --play: runs the file headless, replays --script, prints { sends, vars }. */\nfunction playOnce(filePath: string, scriptPath: string, trace: boolean): number {\n if (!scriptPath) { process.stderr.write('flatc: --play requires --script <gestures.json>\\n'); return 1 }\n if (!existsSync(scriptPath)) { process.stderr.write(`flatc: script not found: ${scriptPath}\\n`); return 1 }\n let doc: Doc, gestures: Gesture[]\n try { doc = loadDoc(filePath) } catch (e) { process.stderr.write(`flatc: cannot read: ${(e as Error).message}\\n`); return 1 }\n try { gestures = JSON.parse(readFileSync(scriptPath, 'utf8')) as Gesture[] } catch (e) { process.stderr.write(`flatc: invalid JSON script: ${(e as Error).message}\\n`); return 1 }\n if (!Array.isArray(gestures)) { process.stderr.write('flatc: the script must be an array of gestures\\n'); return 1 }\n const res = playHeadless(doc, gestures, { trace })\n if (!trace) process.stdout.write(JSON.stringify(res, null, 2) + '\\n')\n else // --trace: readable log (one gesture per line) → inspection / debug-player.\n for (const s of res.steps ?? []) {\n // `name` · `name=value` · `name{a=1, b=2}` (record payload) — the three shapes the host receives.\n const send = (e: { name: string; value?: number | string; fields?: Record<string, number> }): string =>\n e.fields ? `${e.name}{${Object.entries(e.fields).map(([k, v]) => `${k}=${v}`).join(', ')}}`\n : e.value !== undefined ? `${e.name}=${e.value}` : e.name\n const sends = s.sends.length ? ' sends:[' + s.sends.map(send).join(', ') + ']' : ''\n const vars = Object.entries(s.changed).map(([k, [a, b]]) => `${k}:${JSON.stringify(a)}→${JSON.stringify(b)}`)\n process.stdout.write(`${s.gesture.padEnd(28)}${sends}${vars.length ? ' vars{' + vars.join(' ') + '}' : ''}\\n`)\n }\n // `expect`: any detected mismatch → stderr log + exit code ≠0 (CI self-verification).\n if (res.expectFailures?.length) {\n for (const f of res.expectFailures) process.stderr.write(`flatc: ✗ ${f}\\n`)\n return 1\n }\n return 0\n}\n\n/** Parses `--at`: \"k=v[,k2=v2]\" → variable table (state override for rendering). */\nfunction parseVars(spec: string, into: Record<string, number>): void {\n for (const pair of spec.split(',')) {\n const i = pair.indexOf('=')\n if (i < 0) continue\n const k = pair.slice(0, i).trim(); const v = Number(pair.slice(i + 1).trim())\n if (k && Number.isFinite(v)) into[k] = v\n }\n}\n\n/** `--scale auto`: pick a resolution factor from the canvas size — enlarge small/thin content (so fine\n * filaments stay legible) while leaving large content at 1×. `max(160/long, 48/short)`, clamped [1, 8]. */\nfunction autoScale(w: number, h: number): number {\n const maxSide = Math.max(1, w, h), minSide = Math.max(1, Math.min(w, h))\n return Math.max(1, Math.min(8, Math.round(Math.max(160 / maxSide, 48 / minSide))))\n}\n\n/** Renders a Doc to a PNG file (headless skia). Async (SVG decode + raster). Shared by --render and --preview. */\nasync function renderDocToFile(doc: Doc, outPath: string, frame: number, vars: Record<string, number>, scale: number, steps: number): Promise<number> {\n try {\n const { renderDocToPng } = await import('./render')\n const png = await renderDocToPng(doc, { frame, vars: Object.keys(vars).length ? vars : undefined, scale, steps: steps || undefined })\n writeFileSync(outPath, png)\n } catch (e) {\n process.stderr.write(`flatc: render failed: ${(e as Error).message}\\n`)\n if (process.env.FLATC_DEBUG && (e as Error).stack) process.stderr.write(`${(e as Error).stack}\\n`) // FLATC_DEBUG=1 → full stack for diagnosis\n return 1\n }\n process.stdout.write(`flatc: ${basename(outPath)} ✓ ${doc.width}×${doc.height} ×${scale}${frame ? ` · frame ${frame}` : ''}${steps ? ` · ${steps} step(s)` : ''}${Object.keys(vars).length ? ` · ${Object.entries(vars).map(([k, v]) => `${k}=${v}`).join(' ')}` : ''}\\n`)\n return 0\n}\n\n/** --render: renders the file to PNG (headless skia). Async (SVG decode + raster). */\nasync function renderOnce(filePath: string, out: string, frame: number, vars: Record<string, number>, scale: number, steps: number, scaleAuto: boolean): Promise<number> {\n let doc: Doc\n try { doc = loadDoc(filePath) } catch (e) { process.stderr.write(`flatc: cannot read: ${(e as Error).message}\\n`); return 1 }\n const outPath = out ? resolve(out) : join(dirname(filePath), basename(filePath, extname(filePath)) + '.png')\n return renderDocToFile(doc, outPath, frame, vars, scaleAuto ? autoScale(doc.width, doc.height) : scale, steps)\n}\n\nconst gcd = (a: number, b: number): number => { a = Math.abs(a); b = Math.abs(b); while (b) { const t = a % b; a = b; b = t } return a || 1 }\nconst lcm = (a: number, b: number): number => Math.max(1, Math.round((a / gcd(a, b)) * b))\n\n/** Every instance in a symbol's subtree (descends into local groups; does NOT cross into other symbols). */\nfunction* instancesOf(sym: SymbolDef): Generator<Instance> {\n const stack: Item[] = []\n for (const l of sym.layers) stack.push(...l.items)\n for (let it = stack.pop(); it; it = stack.pop()) {\n if (isInstance(it)) yield it\n else if (isGroup(it)) for (const l of it.layers) stack.push(...l.items)\n }\n}\n\n/**\n * Preview window length (frames). A `synced` instance loops on the PARENT's frame, so the symbol's own\n * duration suffices — that's the historical behavior, kept for every symbol with no MovieClip descendant.\n * But an `independent` (`loop`) descendant runs on its OWN duration, immune to the parent's wrap: to SHOW it\n * loop CLEANLY the window must be a common multiple of every such clip's duration (and the root's) — its\n * \"loop seam\". `once` clips only need the window to REACH their last frame (they hold afterwards). We walk\n * the subtree, fold each independent clip's duration into the seam (LCM), and extend past the longest clip,\n * keeping the window a whole number of seams. Capped, so coprime durations can't blow the window up.\n */\nfunction previewDuration(root: SymbolDef, symbols: SymbolDef[]): number {\n const byId = new Map(symbols.map((s) => [s.id, s]))\n const seen = new Set<string>()\n let seam = Math.max(1, root.timeline?.durationFrames ?? 1) // clean-loop period (multiple of every loop clip)\n let longest = seam // window must reach the last frame of any clip\n const walk = (sym: SymbolDef | undefined): void => {\n if (!sym || seen.has(sym.id)) return\n seen.add(sym.id)\n for (const it of instancesOf(sym)) {\n const child = byId.get(it.symbolId)\n const cdur = Math.max(1, child?.timeline?.durationFrames ?? 1)\n const mode = it.playback?.mode\n if (mode === 'independent') { seam = lcm(seam, cdur); longest = Math.max(longest, cdur) }\n else if (mode === 'once') longest = Math.max(longest, cdur)\n walk(child)\n }\n }\n walk(root)\n let dur = seam\n while (dur < longest) dur += seam // keep a clean loop seam while covering the longest MovieClip\n return Math.min(dur, 6000) // hard cap (~4 min @24fps) against a pathological coprime-duration blow-up\n}\n\n/**\n * Wraps ONE symbol from a `.flat` library into a minimal, playable Doc: a single centered instance on a\n * canvas auto-sized to the symbol's frame-0 bounds (+ padding). Lets you preview a library asset without\n * hand-authoring a wrapper `.flatink`. The root timeline borrows the symbol's own fps and a duration long\n * enough to show every nested MovieClip (`loop`/`once`) loop cleanly (`previewDuration`). Throws if the lib\n * is empty or the named symbol is missing.\n */\nfunction buildPreviewDoc(flatPath: string, symbolName: string, pad: number, bboxMode: 'all' | 'frame0', setSpec: Record<string, string> = {}): { doc: Doc; symbol: SymbolDef; others: string[] } {\n const { symbols } = parseFlatLib(readFileSync(flatPath, 'utf8'))\n if (!symbols.length) throw new Error('no symbols found in this .flat library')\n let symbol = symbols[0]\n if (symbolName) {\n const found = symbols.find((s) => s.name === symbolName)\n if (!found) throw new Error(`symbol \"${symbolName}\" not found — available: ${symbols.map((s) => s.name).join(', ')}`)\n symbol = found\n }\n\n const instance: Instance = { id: 'preview_instance', kind: 'instance', name: symbol.name, transform: { ...IDENTITY }, symbolId: symbol.id }\n const layer: Layer = { id: 'preview_layer', name: 'preview', visible: true, locked: false, opacity: 1, items: [instance] }\n const tl = symbol.timeline\n const dur = previewDuration(symbol, symbols)\n const timeline = { fps: tl?.fps ?? 24, durationFrames: dur, tracks: [] }\n // ALL symbols stay in the library (the chosen one may instance the others) — only `instance` is on stage.\n let doc: Doc = { width: 1, height: 1, layers: [layer], symbols, timeline }\n\n // Auto-size & center. Default `--bbox all`: UNION over every frame of the symbol (sub-timelines NOT\n // frozen) so motion that drifts/rotates/grows is never clipped. `--bbox frame0` keeps the old frame-0\n // measure (+`--pad` to absorb motion).\n // Sample at most ~240 evenly-spaced frames (+ the last) so a long/abusive `durationFrames` can't blow\n // up memory/time; a sparse union is virtually as tight as every-frame for real motion.\n const sampleFrames = (n: number): number[] => {\n const step = Math.max(1, Math.ceil(n / 240))\n const fs: number[] = []\n for (let f = 0; f < n; f += step) fs.push(f)\n if (fs[fs.length - 1] !== n - 1) fs.push(n - 1)\n return fs\n }\n const bb = bboxMode === 'all' ? containerBBoxUnion(doc, instance, sampleFrames(dur)) : containerBBox(doc, instance, 0)\n if (bb) {\n doc = { ...doc, width: Math.max(1, Math.ceil(bb.maxX - bb.minX) + pad * 2), height: Math.max(1, Math.ceil(bb.maxY - bb.minY) + pad * 2) }\n instance.transform = { ...IDENTITY, e: pad - bb.minX, f: pad - bb.minY }\n } else {\n doc = { ...doc, width: 512, height: 512 } // empty/degenerate symbol: fall back to a fixed centered stage\n instance.transform = { ...IDENTITY, e: 256, f: 256 }\n }\n\n // `--set param=value`: set the preview instance's exposed params (call-site values, raw literals). The\n // renderer resolves them per the symbol's ParamDef / state machines (color → fill, number/bool → scope,\n // state name → driven frame). A light validation warns on names the symbol does not expose.\n const entries = Object.entries(setSpec)\n if (entries.length) {\n const known = new Set([...(symbol.states ?? []).map((s) => s.param), ...(symbol.params ?? []).map((p) => p.name)])\n for (const [k, v] of entries) {\n if (!known.has(k)) process.stderr.write(`flatc: --set ${k}: \"${symbol.name}\" exposes no such param (${[...known].join(', ') || 'none'})\\n`)\n else (instance.params ??= {})[k] = v\n }\n }\n return { doc, symbol, others: symbols.filter((s) => s !== symbol).map((s) => s.name) }\n}\n\n/** --preview: wraps one symbol of a `.flat` into a playable Doc, then writes a .flatpack (default) or a PNG (with --render). */\nasync function previewOnce(flatPath: string, symbolName: string, out: string, frame: number, vars: Record<string, number>, scale: number, steps: number, doRender: boolean, pad: number, bboxMode: 'all' | 'frame0', setSpec: Record<string, string>, scaleAuto: boolean): Promise<number> {\n let built: { doc: Doc; symbol: SymbolDef; others: string[] }\n try { built = buildPreviewDoc(flatPath, symbolName, pad, bboxMode, setSpec) }\n catch (e) { process.stderr.write(`flatc: ${(e as Error).message}\\n`); return 1 }\n const { doc, symbol, others } = built\n const stem = `${basename(flatPath, extname(flatPath))}.${symbol.name}`\n let code: number\n if (doRender) {\n // auto scale from the CONTENT size (minus the padding), so thin filaments still trigger an upscale.\n const sc = scaleAuto ? autoScale(doc.width - 2 * pad, doc.height - 2 * pad) : scale\n code = await renderDocToFile(doc, out ? resolve(out) : join(dirname(flatPath), stem + '.png'), frame, vars, sc, steps)\n } else {\n const outPath = out ? resolve(out) : join(dirname(flatPath), stem + '.flatpack')\n writeFileSync(outPath, packToJSON(doc))\n process.stdout.write(`flatc: ${basename(outPath)} ✓ preview of \"${symbol.name}\" · ${doc.width}×${doc.height} · play it in the browser player\\n`)\n code = 0\n }\n if (!symbolName && others.length) process.stderr.write(`flatc: previewed \"${symbol.name}\"; other symbols in this lib: ${others.join(', ')} (pick with --symbol <name>)\\n`)\n return code\n}\n\nexport function run(argv: string[]): number | Promise<number> {\n const args = argv.slice(2)\n let out = '', scriptPath = '', symbolName = ''\n let checkOnly = false, doWatch = false, doPlay = false, doRender = false, doTrace = false, doPreview = false, noLibs = false\n let frame = 0, scale = 2, steps = 0, pad = 24\n let scaleAuto = false\n let bboxMode: 'all' | 'frame0' = 'all'\n let assetMode: AssetMode = 'inline'\n const vars: Record<string, number> = {}\n const setSpec: Record<string, string> = {} // `--set param=value` (state name or number) for --preview\n const positional: string[] = []\n for (let i = 0; i < args.length; i++) {\n const a = args[i]\n if (a === '-o' || a === '--out') out = args[++i] ?? ''\n else if (a === '--script') scriptPath = resolve(args[++i] ?? '')\n else if (a === '--assets') assetMode = args[++i] === 'external' ? 'external' : 'inline'\n else if (a === '--check') checkOnly = true\n else if (a === '--no-libs') noLibs = true\n else if (a === '--watch') doWatch = true\n else if (a === '--play') doPlay = true\n else if (a === '--trace') doTrace = true\n else if (a === '--render') doRender = true\n else if (a === '--preview') doPreview = true\n else if (a === '--symbol') symbolName = args[++i] ?? ''\n else if (a === '--pad') pad = Math.max(0, Number(args[++i] ?? '24') || 0)\n else if (a === '--bbox') bboxMode = args[++i] === 'frame0' ? 'frame0' : 'all'\n else if (a === '--frame') frame = Number(args[++i] ?? '0') || 0\n else if (a === '--steps') steps = Math.max(0, Number(args[++i] ?? '0') || 0)\n else if (a === '--scale') { const v = args[++i] ?? '2'; if (v === 'auto') scaleAuto = true; else scale = Number(v) || 2 }\n else if (a === '--at') parseVars(args[++i] ?? '', vars)\n else if (a === '--set') for (const pair of (args[++i] ?? '').split(',')) { const j = pair.indexOf('='); if (j > 0) setSpec[pair.slice(0, j).trim()] = pair.slice(j + 1).trim() }\n else if (a === '-h' || a === '--help') { printHelp(); return 0 }\n else positional.push(a)\n }\n if (!positional.length) { printHelp(); return 1 }\n\n const filePath = resolve(positional[0])\n if (!existsSync(filePath)) { process.stderr.write(`flatc: not found: ${filePath}\\n`); return 1 }\n\n const explicitFlats = positional.slice(1)\n if (doPreview) return previewOnce(filePath, symbolName, out, frame, vars, scale, steps, doRender, pad, bboxMode, setSpec, scaleAuto)\n if (doRender) return renderOnce(filePath, out, frame, vars, scale, steps, scaleAuto)\n if (doPlay) return playOnce(filePath, scriptPath, doTrace)\n // `--check <library>.flat`: a `.flat` first positional is an asset LIB, not a program → lint via parseFlatLib\n // (the following positionals are more `.flat` libs to merge). Every other path is unchanged.\n const action: () => number = checkOnly && filePath.endsWith('.flat')\n ? () => checkFlatLibs([filePath, ...explicitFlats])\n : () => compileOnce(filePath, explicitFlats, out, checkOnly, assetMode, noLibs)\n if (doWatch) {\n const code = action()\n const baseDir = dirname(filePath)\n let timer: ReturnType<typeof setTimeout> | undefined\n // We ignore changes to the OUTPUT (.flatpack) — otherwise writing it would re-trigger the compile in a loop.\n watch(baseDir, { recursive: false }, (_e, filename) => {\n if (filename && (filename.endsWith('.flatpack') || filename.endsWith('.flatpack.json'))) return\n clearTimeout(timer); timer = setTimeout(action, 80)\n })\n process.stdout.write(`flatc: watching ${baseDir} … (Ctrl+C to stop)\\n`)\n return code\n }\n return action()\n}\n"],"mappings":"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","names":["f"]}