@vosjs/cli 0.55.1 → 0.56.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/README.md CHANGED
@@ -195,7 +195,7 @@ vos build port/program/program.mjs # real functions → config.json; refuses a
195
195
  vos compare port/program --against ./piece/renders/render.mp4 # per-frame SSIM and source | vos | difference sheets; exit 1 under 0.95
196
196
  ```
197
197
 
198
- `inventory` reads the page as a browser renders it (computed styles, not CSS text): a HyperFrames composition's root `data-*`, its `<audio data-start data-volume>`, the scenes its timeline reveals, and each word laid out where it settles in its scene (the piece's own `window.__timelines`, seeked). A Remotion project is bundled with its own `@remotion/bundler` (its dependencies installed) and its first composition mounted the way Remotion's renderer mounts it: the `<Sequence>`s are the scenes, named by the component each holds (a sequence lying over a longer one is a transition, not a scene), the words are read nine tenths into each scene, the palette is named after the colour constants the source declares, and `<Audio>` is the score. Every scene's ground (the frame-filling colour behind it) is measured, and the scaffold stands each scene on it. A word animated one span per letter is read as one `split` word, in its letters' face. A page that paints on a canvas gets the words and faces its scripts name. `compare` needs ffmpeg on PATH; it judges every frame on its own, because one missing element is a frame's failure that an average would hide.
198
+ `inventory` reads the page as a browser renders it (computed styles, not CSS text): a HyperFrames composition's root `data-*`, its `<audio data-start data-volume>`, the scenes its timeline reveals, and each word laid out where it settles in its scene (the piece's own `window.__timelines`, seeked). A Remotion project is bundled with its own `@remotion/bundler` (its dependencies installed) and its first composition mounted the way Remotion's renderer mounts it: the `<Sequence>`s are the scenes, named by the component each holds (a sequence lying over a longer one is a transition, not a scene), the words are read nine tenths into each scene, the palette is named after the colour constants the source declares, and `<Audio>` is the score. Every scene's ground (the frame-filling colour behind it) is measured, and the scaffold stands each scene on it. A word animated one span per letter is read as one `split` word, in its letters' face. A page that paints on a canvas gets the words and faces its scripts name. When the piece needs a painter or its code reaches for a spring or noise, the scaffold writes the PAINTER STARTER into `createContent` as `content.refs.lib`: `spring` (Remotion's spring to the frame, `durationInFrames` included), `springTo` (that spring on the timeline, one linear step per frame), `interpolate`, `bezier`, seeded simplex `noise2D`/`noise3D` (`@remotion/noise`'s character, not its values) and `random`/`rng`, written from the maths, so a port never reads another engine's source for them. `compare` needs ffmpeg on PATH; it judges every frame on its own, because one missing element is a frame's failure that an average would hide.
199
199
 
200
200
  ## The take directory
201
201
 
@@ -9308,7 +9308,9 @@ function mergeSceneTexts(perScene) {
9308
9308
  textPlaced.add(shape);
9309
9309
  out.push({
9310
9310
  ...t,
9311
- id: `${t.id}-${out.length}`,
9311
+ // A tag-numbered id stays tag-numbered (the scaffold then names the
9312
+ // key after the words); a real id is kept as the source wrote it.
9313
+ id: /^[a-z][a-z0-9]*-\d+$/.test(t.id) ? `${t.tag}-${out.length}` : t.id,
9312
9314
  scene: shared ? null : s.scene
9313
9315
  });
9314
9316
  }
@@ -9531,6 +9533,7 @@ async function readRemotion(dir, log) {
9531
9533
  for (const g of read.gaps ?? []) gaps.add(g);
9532
9534
  perScene.push({ scene: s.name, texts: read.texts ?? [] });
9533
9535
  }
9536
+ const sources = sourceTexts(dir);
9534
9537
  const publicDir = join21(dir, "public");
9535
9538
  const media = tree.audio.map((a) => {
9536
9539
  const name = basename7(a.src.split("?")[0]);
@@ -9550,7 +9553,8 @@ async function readRemotion(dir, log) {
9550
9553
  fps: c.fps,
9551
9554
  duration: Math.round(total * 1e3) / 1e3,
9552
9555
  texts: mergeSceneTexts(perScene),
9553
- palette: themeColors(sourceTexts(dir)),
9556
+ palette: themeColors(sources),
9557
+ uses: sourceUses(sources.join("\n")),
9554
9558
  colors: [...colors],
9555
9559
  gaps: [...gaps],
9556
9560
  media,
@@ -9666,6 +9670,15 @@ function scriptFontFamilies(code) {
9666
9670
  }
9667
9671
  return [...out];
9668
9672
  }
9673
+ function sourceUses(code) {
9674
+ const out = [];
9675
+ if (/\bspring\s*\(|\bmeasureSpring\s*\(/.test(code)) out.push("spring");
9676
+ if (/@remotion\/noise|\bnoise[234]D\s*\(/.test(code)) out.push("noise");
9677
+ if (/\binterpolate\s*\(/.test(code)) out.push("interpolate");
9678
+ if (/Easing\.bezier\s*\(|cubic-bezier\(/.test(code)) out.push("bezier");
9679
+ if (/\brandom\s*\(\s*['"\w]/.test(code)) out.push("random");
9680
+ return out;
9681
+ }
9669
9682
  function catalogFamily2(family) {
9670
9683
  const clean = family.trim().replace(/^['"]|['"]$/g, "");
9671
9684
  return findFontFamily3(clean)?.family ?? null;
@@ -10017,6 +10030,7 @@ async function readInventory(source, opts) {
10017
10030
  gaps: read.gaps,
10018
10031
  variables: read.variables,
10019
10032
  scriptStrings,
10033
+ uses: read.uses ?? sourceUses(read.scriptText ?? ""),
10020
10034
  render: render ? relative2(process.cwd(), render) : null,
10021
10035
  stills
10022
10036
  };
@@ -10027,6 +10041,191 @@ import { spawnSync as spawnSync3 } from "child_process";
10027
10041
  import { copyFileSync, existsSync as existsSync19, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
10028
10042
  import { basename as basename8, dirname as dirname7, join as join23, resolve as resolve10 } from "path";
10029
10043
  import { findFontFamily as findFontFamily4, fontFaceUrl, nearestFontWeight } from "@vosjs/shared";
10044
+
10045
+ // src/plugin/painterLib.ts
10046
+ var PAINTER_LIB = ` // THE PAINTER STARTER (vos port): the maths every port re-wrote, in one
10047
+ // place: content.refs.lib in createTimeline and onFrame.
10048
+ const clamp = (v, lo, hi) => (v < lo ? lo : v > hi ? hi : v)
10049
+ const hashSeed = (seed) => {
10050
+ if (typeof seed === 'number') return seed | 0
10051
+ let h = 2166136261
10052
+ for (const ch of String(seed)) h = Math.imul(h ^ ch.charCodeAt(0), 16777619)
10053
+ return h | 0
10054
+ }
10055
+ const rng = (seed) => {
10056
+ let s = hashSeed(seed)
10057
+ return () => {
10058
+ s = (s + 0x6d2b79f5) | 0
10059
+ let r = Math.imul(s ^ (s >>> 15), 1 | s)
10060
+ r = (r + Math.imul(r ^ (r >>> 7), 61 | r)) ^ r
10061
+ return ((r ^ (r >>> 14)) >>> 0) / 4294967296
10062
+ }
10063
+ }
10064
+ const random = (seed) => rng(seed)()
10065
+ // interpolate(input, [a, b, ...], [x, y, ...], { extrapolateLeft, extrapolateRight, easing })
10066
+ const interpolate = (input, inR, outR, opts = {}) => {
10067
+ let i = 1
10068
+ while (i < inR.length - 1 && input > inR[i]) i++
10069
+ const a = inR[i - 1], b = inR[i]
10070
+ let t = b === a ? 0 : (input - a) / (b - a)
10071
+ if (t < 0) {
10072
+ if (opts.extrapolateLeft === 'clamp') t = 0
10073
+ else if (opts.extrapolateLeft === 'identity') return input
10074
+ }
10075
+ if (t > 1) {
10076
+ if (opts.extrapolateRight === 'clamp') t = 1
10077
+ else if (opts.extrapolateRight === 'identity') return input
10078
+ }
10079
+ const e = opts.easing ? opts.easing(t) : t
10080
+ return outR[i - 1] + (outR[i] - outR[i - 1]) * e
10081
+ }
10082
+ // bezier(x1, y1, x2, y2): a CSS cubic-bezier as an easing function.
10083
+ const bezier = (x1, y1, x2, y2) => {
10084
+ const cx = 3 * x1, bx = 3 * (x2 - x1) - cx, ax = 1 - cx - bx
10085
+ const cy = 3 * y1, by = 3 * (y2 - y1) - cy, ay = 1 - cy - by
10086
+ const sx = (t) => ((ax * t + bx) * t + cx) * t
10087
+ const sy = (t) => ((ay * t + by) * t + cy) * t
10088
+ const dx = (t) => (3 * ax * t + 2 * bx) * t + cx
10089
+ return (x) => {
10090
+ if (x <= 0) return 0
10091
+ if (x >= 1) return 1
10092
+ let t = x
10093
+ for (let k = 0; k < 8; k++) {
10094
+ const d = dx(t)
10095
+ if (Math.abs(d) < 1e-6) break
10096
+ const t2 = t - (sx(t) - x) / d
10097
+ if (t2 < 0 || t2 > 1) break
10098
+ t = t2
10099
+ }
10100
+ let lo = 0, hi = 1
10101
+ if (Math.abs(sx(t) - x) > 1e-6) {
10102
+ t = x
10103
+ for (let k = 0; k < 40; k++) {
10104
+ if (sx(t) < x) lo = t; else hi = t
10105
+ t = (lo + hi) / 2
10106
+ }
10107
+ }
10108
+ return sy(t)
10109
+ }
10110
+ }
10111
+ // spring({ frame, fps, config: { damping, mass, stiffness, overshootClamping }, from, to, delay })
10112
+ const springUnit = (t, config = {}) => {
10113
+ const m = config.mass ?? 1, k = config.stiffness ?? 100, c = config.damping ?? 10
10114
+ const w0 = Math.sqrt(k / m), z = c / (2 * Math.sqrt(k * m))
10115
+ if (t <= 0) return 0
10116
+ // A damping ratio of 1 or more settles CRITICALLY at the natural
10117
+ // frequency, as Remotion's spring does (measured to 1e-16 across
10118
+ // overdamped configs; true overdamped motion would crawl, and
10119
+ // \`damping: 200\` is the smooth spring sources reach for).
10120
+ if (z >= 1) return 1 - Math.exp(-w0 * t) * (1 + w0 * t)
10121
+ const wd = w0 * Math.sqrt(1 - z * z)
10122
+ return 1 - Math.exp(-z * w0 * t) * (Math.cos(wd * t) + ((z * w0) / wd) * Math.sin(wd * t))
10123
+ }
10124
+ // The frames a spring takes to settle within half a percent and stay there.
10125
+ const springFrames = (fps, config = {}) => {
10126
+ let last = 0
10127
+ for (let f = 0; f <= fps * 10; f++)
10128
+ if (Math.abs(springUnit(f / fps, config) - 1) >= 0.005) last = f
10129
+ return last + 1
10130
+ }
10131
+ // durationInFrames stretches the spring so it settles on that frame, and
10132
+ // past it the value IS \`to\` (as Remotion's does, measured).
10133
+ const spring = ({ frame, fps, config = {}, from = 0, to = 1, delay = 0, durationInFrames }) => {
10134
+ const f = Math.max(0, frame - delay)
10135
+ if (durationInFrames && f > durationInFrames) return to
10136
+ const scale = durationInFrames ? springFrames(fps, config) / durationInFrames : 1
10137
+ let x = springUnit((f * scale) / fps, config)
10138
+ if (config.overshootClamping && x > 1) x = 1
10139
+ return from + (to - from) * x
10140
+ }
10141
+ // springTo(tl, target, { x: [from, to] }, at, { fps, config, frames }): the
10142
+ // spring on the timeline, one linear step per frame; returns its end time.
10143
+ const springTo = (tl, target, props, at, opts = {}) => {
10144
+ const fps = opts.fps || 30
10145
+ const frames = opts.frames ?? springFrames(fps, opts.config)
10146
+ const keys = Object.keys(props)
10147
+ const start = {}
10148
+ for (const k of keys) start[k] = props[k][0]
10149
+ tl.set(target, start, at)
10150
+ for (let f = 1; f <= frames; f++) {
10151
+ const s = f === frames ? 1 : spring({ frame: f, fps, config: opts.config })
10152
+ const v = { duration: 1 / fps, ease: 'none' }
10153
+ for (const k of keys) v[k] = props[k][0] + (props[k][1] - props[k][0]) * s
10154
+ tl.to(target, v, at + (f - 1) / fps)
10155
+ }
10156
+ return at + frames / fps
10157
+ }
10158
+ // Seeded simplex noise in [-1, 1] (Gustavson's construction).
10159
+ const grad3 = [[1,1,0],[-1,1,0],[1,-1,0],[-1,-1,0],[1,0,1],[-1,0,1],[1,0,-1],[-1,0,-1],[0,1,1],[0,-1,1],[0,1,-1],[0,-1,-1]]
10160
+ const perms = new Map()
10161
+ const perm = (seed) => {
10162
+ const key = String(seed)
10163
+ let p = perms.get(key)
10164
+ if (!p) {
10165
+ const r = rng(seed)
10166
+ const base = Array.from({ length: 256 }, (_, i) => i)
10167
+ for (let i = 255; i > 0; i--) {
10168
+ const j = Math.floor(r() * (i + 1))
10169
+ const t = base[i]; base[i] = base[j]; base[j] = t
10170
+ }
10171
+ p = new Uint8Array(512)
10172
+ for (let i = 0; i < 512; i++) p[i] = base[i & 255]
10173
+ perms.set(key, p)
10174
+ }
10175
+ return p
10176
+ }
10177
+ const noise2D = (seed, x, y) => {
10178
+ const p = perm(seed)
10179
+ const F2 = 0.5 * (Math.sqrt(3) - 1), G2 = (3 - Math.sqrt(3)) / 6
10180
+ const s = (x + y) * F2
10181
+ const i = Math.floor(x + s), j = Math.floor(y + s)
10182
+ const t = (i + j) * G2
10183
+ const x0 = x - (i - t), y0 = y - (j - t)
10184
+ const i1 = x0 > y0 ? 1 : 0, j1 = x0 > y0 ? 0 : 1
10185
+ const x1 = x0 - i1 + G2, y1 = y0 - j1 + G2
10186
+ const x2 = x0 - 1 + 2 * G2, y2 = y0 - 1 + 2 * G2
10187
+ const ii = i & 255, jj = j & 255
10188
+ const corner = (gi, cx, cy) => {
10189
+ const tt = 0.5 - cx * cx - cy * cy
10190
+ if (tt < 0) return 0
10191
+ const g = grad3[gi % 12]
10192
+ return tt * tt * tt * tt * (g[0] * cx + g[1] * cy)
10193
+ }
10194
+ return 70 * (corner(p[ii + p[jj]], x0, y0) + corner(p[ii + i1 + p[jj + j1]], x1, y1) + corner(p[ii + 1 + p[jj + 1]], x2, y2))
10195
+ }
10196
+ const noise3D = (seed, x, y, z) => {
10197
+ const p = perm(seed)
10198
+ const F3 = 1 / 3, G3 = 1 / 6
10199
+ const s = (x + y + z) * F3
10200
+ const i = Math.floor(x + s), j = Math.floor(y + s), k = Math.floor(z + s)
10201
+ const t = (i + j + k) * G3
10202
+ const x0 = x - (i - t), y0 = y - (j - t), z0 = z - (k - t)
10203
+ let i1, j1, k1, i2, j2, k2
10204
+ if (x0 >= y0) {
10205
+ if (y0 >= z0) { i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 1; k2 = 0 }
10206
+ else if (x0 >= z0) { i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 0; k2 = 1 }
10207
+ else { i1 = 0; j1 = 0; k1 = 1; i2 = 1; j2 = 0; k2 = 1 }
10208
+ } else {
10209
+ if (y0 < z0) { i1 = 0; j1 = 0; k1 = 1; i2 = 0; j2 = 1; k2 = 1 }
10210
+ else if (x0 < z0) { i1 = 0; j1 = 1; k1 = 0; i2 = 0; j2 = 1; k2 = 1 }
10211
+ else { i1 = 0; j1 = 1; k1 = 0; i2 = 1; j2 = 1; k2 = 0 }
10212
+ }
10213
+ const ii = i & 255, jj = j & 255, kk = k & 255
10214
+ const corner = (gi, cx, cy, cz) => {
10215
+ const tt = 0.6 - cx * cx - cy * cy - cz * cz
10216
+ if (tt < 0) return 0
10217
+ const g = grad3[gi % 12]
10218
+ return tt * tt * tt * tt * (g[0] * cx + g[1] * cy + g[2] * cz)
10219
+ }
10220
+ return 32 * (
10221
+ corner(p[ii + p[jj + p[kk]]], x0, y0, z0) +
10222
+ corner(p[ii + i1 + p[jj + j1 + p[kk + k1]]], x0 - i1 + G3, y0 - j1 + G3, z0 - k1 + G3) +
10223
+ corner(p[ii + i2 + p[jj + j2 + p[kk + k2]]], x0 - i2 + 2 * G3, y0 - j2 + 2 * G3, z0 - k2 + 2 * G3) +
10224
+ corner(p[ii + 1 + p[jj + 1 + p[kk + 1]]], x0 - 1 + 3 * G3, y0 - 1 + 3 * G3, z0 - 1 + 3 * G3))
10225
+ }
10226
+ const lib = { clamp, interpolate, bezier, spring, springFrames, springTo, noise2D, noise3D, random, rng }`;
10227
+
10228
+ // src/plugin/portScaffold.ts
10030
10229
  var DESIGN_HEIGHT = 1080;
10031
10230
  function toHex(css) {
10032
10231
  const s = css.trim();
@@ -10220,6 +10419,9 @@ function planScaffold(inv, opts) {
10220
10419
  }
10221
10420
  ] : [];
10222
10421
  const painter = inv.canvases.length > 0 || inv.gaps.length > 0;
10422
+ const uses = inv.uses ?? [];
10423
+ const lib = painter || uses.length > 0;
10424
+ if (uses.includes("spring")) data.fps = inv.fps ?? 30;
10223
10425
  const duration = Math.round((inv.duration ?? 5) * 1e3) / 1e3;
10224
10426
  const program = programSource({
10225
10427
  source: inv.source,
@@ -10230,7 +10432,9 @@ function planScaffold(inv, opts) {
10230
10432
  fonts,
10231
10433
  elements,
10232
10434
  scenes: inv.scenes,
10233
- painter
10435
+ painter,
10436
+ lib,
10437
+ uses
10234
10438
  });
10235
10439
  const audio = [];
10236
10440
  const copies = [];
@@ -10280,6 +10484,7 @@ function planScaffold(inv, opts) {
10280
10484
  elements: elements.length,
10281
10485
  params: params.length,
10282
10486
  painter,
10487
+ uses,
10283
10488
  scores: audio.map((a) => String(a.key)),
10284
10489
  extra: report
10285
10490
  })
@@ -10290,6 +10495,12 @@ function programSource(p) {
10290
10495
  const sceneTodos = p.scenes.length ? p.scenes.map(
10291
10496
  (s) => ` // TODO scene "${s.name}" (${s.start}s${s.duration ? ` to ${s.start + s.duration}s` : ""}): translate its motion onto ctx.elements.get(id).props / .segments here`
10292
10497
  ).join("\n") : " // TODO: translate the source's motion here, one block per scene (tl.addLabel above names them)";
10498
+ const springHint = p.uses.includes("spring") ? `
10499
+ // The source springs: content.refs.lib.springTo(tl, target, { y: [120, 0] }, at,
10500
+ // { fps: ctx.data.fps, config: { damping: 200 } }) puts Remotion's spring on
10501
+ // the timeline frame by frame (spring({ frame, fps, config }) for a value).` : "";
10502
+ const libBlock = p.lib ? `
10503
+ ${PAINTER_LIB}` : "";
10293
10504
  const painterContent = p.painter ? `
10294
10505
  // THE PAINTER (vos-port rule 6): one canvas, only for what no element can
10295
10506
  // say (the inventory's gaps and canvases). It reads every value from
@@ -10309,30 +10520,8 @@ function programSource(p) {
10309
10520
  plane.renderOrder = 100.995
10310
10521
  plane.frustumCulled = false
10311
10522
  ctx.overlayScene.add(plane)
10312
- // The starter's helpers: Remotion's interpolate, a seeded PRNG, smooth noise.
10313
- const clamp01 = (v) => (v < 0 ? 0 : v > 1 ? 1 : v)
10314
- const interpolate = (v, [a, b], [x, y], ease = (t) => t) =>
10315
- x + (y - x) * ease(clamp01((v - a) / (b - a)))
10316
- const rand = (seed) => () => {
10317
- seed |= 0
10318
- seed = (seed + 0x6d2b79f5) | 0
10319
- let r = Math.imul(seed ^ (seed >>> 15), 1 | seed)
10320
- r = (r + Math.imul(r ^ (r >>> 7), 61 | r)) ^ r
10321
- return ((r ^ (r >>> 14)) >>> 0) / 4294967296
10322
- }
10323
- const hash = (x, y) => {
10324
- const s = Math.sin(x * 127.1 + y * 311.7) * 43758.5453
10325
- return s - Math.floor(s)
10326
- }
10327
- const noise2 = (x, y) => {
10328
- const xi = Math.floor(x), yi = Math.floor(y)
10329
- const xf = x - xi, yf = y - yi
10330
- const u = xf * xf * (3 - 2 * xf), v = yf * yf * (3 - 2 * yf)
10331
- const a = hash(xi, yi), b = hash(xi + 1, yi), c = hash(xi, yi + 1), d = hash(xi + 1, yi + 1)
10332
- return (a + (b - a) * u + (c - a) * v + (a - b - c + d) * u * v) * 2 - 1
10333
- }
10334
- return { objects: [], refs: { canvas, g: canvas.getContext('2d'), tex, lib: { interpolate, rand, noise2 } } }` : `
10335
- return { objects: [], refs: {} }`;
10523
+ return { objects: [], refs: { canvas, g: canvas.getContext('2d'), tex${p.lib ? ", lib" : ""} } }` : `
10524
+ return { objects: [], refs: {${p.lib ? " lib " : ""}} }`;
10336
10525
  const painterFrame = p.painter ? `
10337
10526
  // Paint the procedural layer from ctx.time and ctx.data, then upload it.
10338
10527
  const { canvas, g, tex } = content.refs
@@ -10356,7 +10545,7 @@ export default {
10356
10545
  elements: ${j(p.elements)},
10357
10546
 
10358
10547
  createContent(ctx) {
10359
- ctx.scene.background = new ctx.THREE.Color(ctx.data.bg)${painterContent}
10548
+ ctx.scene.background = new ctx.THREE.Color(ctx.data.bg)${libBlock}${painterContent}
10360
10549
  },
10361
10550
 
10362
10551
  createTimeline(ctx, content, duration) {
@@ -10375,7 +10564,7 @@ export default {
10375
10564
  if (s.until != null && s.until < duration) tl.set(p, { opacity: 0 }, s.until)
10376
10565
  }
10377
10566
  }
10378
- ${sceneTodos}
10567
+ ${sceneTodos}${springHint}
10379
10568
  tl.to({}, { duration }, 0)
10380
10569
  return tl
10381
10570
  },
@@ -10401,6 +10590,9 @@ function reportText(inv, r) {
10401
10590
  "",
10402
10591
  `- ${r.elements} words as bound text elements, ${Object.keys(inv.palette).length} palette colours the source names (its custom properties or colour constants), ${r.params} knobs.`,
10403
10592
  `- ${inv.scenes.length} scenes as labels${inv.scenes.length ? "" : " (none declared: name them as you translate)"}.`,
10593
+ ...r.painter || r.uses.length ? [
10594
+ `- the painter starter as \`content.refs.lib\`${r.uses.length ? ` (the source uses ${r.uses.join(", ")})` : ""}: \`spring\` (Remotion's, to the frame, \`durationInFrames\` included) and \`springTo\` (a spring on the timeline, a step per frame), \`interpolate\`, \`bezier\`, \`noise2D\`/\`noise3D\` (simplex: \`@remotion/noise\`'s character, not its values, so match blobs by eye), \`random\`/\`rng\`. Use these instead of reading the source engine's code.`
10595
+ ] : [],
10404
10596
  ...r.scores.length ? [
10405
10597
  `- the score as a doc.json track (${r.scores.join(", ")}, copied beside the program; vos push uploads it).`
10406
10598
  ] : [],
@@ -14497,4 +14689,4 @@ export {
14497
14689
  verbHelp,
14498
14690
  run
14499
14691
  };
14500
- //# sourceMappingURL=chunk-FQA7LFXG.js.map
14692
+ //# sourceMappingURL=chunk-XXAY42XS.js.map