@vosjs/cli 0.37.0 → 0.38.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 +1 -1
- package/dist/{chunk-NHKHTIDR.js → chunk-FACYY7VV.js} +98 -6
- package/dist/chunk-FACYY7VV.js.map +1 -0
- package/dist/{chunk-DD6OXVFJ.js → chunk-LGRNHJ2U.js} +176 -35
- package/dist/chunk-LGRNHJ2U.js.map +1 -0
- package/dist/cli.js +22 -4
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.js +2 -2
- package/dist/run-ZNQKSGAF.js +15 -0
- package/package.json +3 -3
- package/dist/chunk-DD6OXVFJ.js.map +0 -1
- package/dist/chunk-NHKHTIDR.js.map +0 -1
- package/dist/run-6T4NK5P2.js +0 -9
- /package/dist/{run-6T4NK5P2.js.map → run-ZNQKSGAF.js.map} +0 -0
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
BrowserUnavailableError,
|
|
4
4
|
directoryKind,
|
|
5
|
-
launchBrowser
|
|
6
|
-
|
|
5
|
+
launchBrowser,
|
|
6
|
+
noteGivenFlag,
|
|
7
|
+
trackFlags
|
|
8
|
+
} from "./chunk-FACYY7VV.js";
|
|
7
9
|
|
|
8
10
|
// src/plugin/run.ts
|
|
9
11
|
import { mkdir as mkdir10, readFile as readFile15, rm as rm5 } from "fs/promises";
|
|
@@ -52,7 +54,9 @@ function parseArgs(argv, booleanFlags, multiFlags = /* @__PURE__ */ new Set()) {
|
|
|
52
54
|
}
|
|
53
55
|
positionals.push(arg);
|
|
54
56
|
}
|
|
55
|
-
|
|
57
|
+
for (const name of Object.keys(flags)) noteGivenFlag(name);
|
|
58
|
+
for (const name of Object.keys(multi)) noteGivenFlag(name);
|
|
59
|
+
return { positionals, flags: trackFlags(flags), multi: trackFlags(multi) };
|
|
56
60
|
}
|
|
57
61
|
function numFlag(flags, name, fallback) {
|
|
58
62
|
const v = flags[name];
|
|
@@ -943,6 +947,17 @@ function lintDoc(docIn) {
|
|
|
943
947
|
}
|
|
944
948
|
const TRANSITIONS = ["none", "fade", "rise"];
|
|
945
949
|
const PRESETS = ["title", "caption", "label"];
|
|
950
|
+
let footageEnd = null;
|
|
951
|
+
if (recording && Array.isArray(doc.segments)) {
|
|
952
|
+
try {
|
|
953
|
+
footageEnd = ratedSegments(doc).reduce(
|
|
954
|
+
(a, s) => a + (s.out - s.in) / (s.rate ?? 1),
|
|
955
|
+
0
|
|
956
|
+
);
|
|
957
|
+
} catch {
|
|
958
|
+
footageEnd = null;
|
|
959
|
+
}
|
|
960
|
+
}
|
|
946
961
|
for (let i = 0; i < (overlays?.length ?? 0); i++) {
|
|
947
962
|
const o = overlays[i];
|
|
948
963
|
const name = `overlays[${i}]`;
|
|
@@ -960,6 +975,14 @@ function lintDoc(docIn) {
|
|
|
960
975
|
if (!isNum(o.duration) || o.duration <= 0) {
|
|
961
976
|
problems.push(`${name}.duration must be > 0 (seconds)`);
|
|
962
977
|
}
|
|
978
|
+
if (footageEnd !== null && footageEnd > 0 && isNum(o.start) && isNum(o.duration)) {
|
|
979
|
+
const over = o.start + o.duration - footageEnd;
|
|
980
|
+
if (over > 0.05) {
|
|
981
|
+
warnings.push(
|
|
982
|
+
o.start >= footageEnd ? `${name} starts at ${o.start.toFixed(2)}s, after the footage ends (${footageEnd.toFixed(2)}s): it plays on bare backdrop and lengthens the output by ${over.toFixed(2)}s. A trim moves the footage, never an OUTPUT-anchored layer: re-place it (vos callout with the same --id), or put a freeze under it` : `${name} ends ${over.toFixed(2)}s after the footage (${footageEnd.toFixed(2)}s): the output extends over bare backdrop. Shorten it, or put a freeze under it`
|
|
983
|
+
);
|
|
984
|
+
}
|
|
985
|
+
}
|
|
963
986
|
checkPin(o, name, docIn, recording, problems, warnings);
|
|
964
987
|
if (o.kind === "text") {
|
|
965
988
|
if (typeof o.text !== "string")
|
|
@@ -1635,7 +1658,7 @@ function framingWarnings(docIn, doc, zoom, overlays, warnings) {
|
|
|
1635
1658
|
if (pinned) {
|
|
1636
1659
|
if (pinned.clamped > 4) {
|
|
1637
1660
|
warnings.push(
|
|
1638
|
-
`overlays[${i}] is pinned ${pinned.side} of its referent but the frame has no room there \u2014 it sits ${Math.round(pinned.clamped)} design px off; a smaller box, another side, or a lower zoom level keeps it beside what it names`
|
|
1661
|
+
`overlays[${i}] is pinned ${pinned.side} of its referent but the frame has no room there \u2014 it sits ${Math.round(pinned.clamped)} design px off; a smaller box, another side, or a lower zoom level keeps it beside what it names. A pin resolves THROUGH the camera, so author the zoom first: a callout composed before it is measured against a frame the viewer never sees`
|
|
1639
1662
|
);
|
|
1640
1663
|
}
|
|
1641
1664
|
return;
|
|
@@ -1798,7 +1821,7 @@ import { pipeline } from "stream/promises";
|
|
|
1798
1821
|
|
|
1799
1822
|
// src/plugin/take.ts
|
|
1800
1823
|
import { mkdir, readFile, rename, rm, writeFile } from "fs/promises";
|
|
1801
|
-
import { existsSync } from "fs";
|
|
1824
|
+
import { existsSync, readdirSync, statSync } from "fs";
|
|
1802
1825
|
import { basename, join } from "path";
|
|
1803
1826
|
var RECORDING_NAME = "recording.webm";
|
|
1804
1827
|
function takeMediaFiles(dir, stem) {
|
|
@@ -1829,6 +1852,20 @@ async function ensureTakeDir(dir) {
|
|
|
1829
1852
|
await mkdir(p.framesDir, { recursive: true });
|
|
1830
1853
|
return p;
|
|
1831
1854
|
}
|
|
1855
|
+
async function dropScreencastFrames(p) {
|
|
1856
|
+
if (!existsSync(p.recording) || statSync(p.recording).size === 0) return 0;
|
|
1857
|
+
if (!existsSync(p.framesDir)) return 0;
|
|
1858
|
+
let freed = 0;
|
|
1859
|
+
for (const name of readdirSync(p.framesDir)) {
|
|
1860
|
+
try {
|
|
1861
|
+
freed += statSync(join(p.framesDir, name)).size;
|
|
1862
|
+
} catch {
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
await rm(p.framesDir, { recursive: true, force: true });
|
|
1866
|
+
await rm(p.framesIndex, { force: true });
|
|
1867
|
+
return freed;
|
|
1868
|
+
}
|
|
1832
1869
|
async function prepareReRecord(dir) {
|
|
1833
1870
|
const p = takePaths(dir);
|
|
1834
1871
|
const kept = [];
|
|
@@ -2154,7 +2191,7 @@ import {
|
|
|
2154
2191
|
|
|
2155
2192
|
// src/plugin/server.ts
|
|
2156
2193
|
import { createServer } from "http";
|
|
2157
|
-
import { existsSync as existsSync3, readFileSync, statSync } from "fs";
|
|
2194
|
+
import { existsSync as existsSync3, readFileSync, statSync as statSync2 } from "fs";
|
|
2158
2195
|
import { writeFile as writeFile3 } from "fs/promises";
|
|
2159
2196
|
import { extname, join as join3 } from "path";
|
|
2160
2197
|
var MIME = {
|
|
@@ -2203,8 +2240,8 @@ function startTakeServer(rootDir, pages) {
|
|
|
2203
2240
|
return;
|
|
2204
2241
|
}
|
|
2205
2242
|
const file = join3(rootDir, decodeURIComponent(url.pathname));
|
|
2206
|
-
if (existsSync3(file) &&
|
|
2207
|
-
const size =
|
|
2243
|
+
if (existsSync3(file) && statSync2(file).isFile()) {
|
|
2244
|
+
const size = statSync2(file).size;
|
|
2208
2245
|
const buf = readFileSync(file);
|
|
2209
2246
|
const type = sniffMediaType(buf.subarray(0, MEDIA_HEAD_BYTES)) ?? MIME[extname(file)] ?? "application/octet-stream";
|
|
2210
2247
|
const range = req.headers.range;
|
|
@@ -5659,6 +5696,19 @@ function winRate(verdicts) {
|
|
|
5659
5696
|
};
|
|
5660
5697
|
}
|
|
5661
5698
|
|
|
5699
|
+
// src/plugin/fontName.ts
|
|
5700
|
+
import { findFontFamily as findFontFamily2 } from "@vosjs/shared";
|
|
5701
|
+
function catalogFamily(family) {
|
|
5702
|
+
const name = family.trim();
|
|
5703
|
+
if (findFontFamily2(name)) return name;
|
|
5704
|
+
const base = name.replace(/\s+Variable$/i, "");
|
|
5705
|
+
if (base !== name) {
|
|
5706
|
+
const hit = findFontFamily2(base);
|
|
5707
|
+
if (hit) return hit.family;
|
|
5708
|
+
}
|
|
5709
|
+
return family;
|
|
5710
|
+
}
|
|
5711
|
+
|
|
5662
5712
|
// src/plugin/callout.ts
|
|
5663
5713
|
import { existsSync as existsSync10 } from "fs";
|
|
5664
5714
|
import { readFile as readFile9 } from "fs/promises";
|
|
@@ -5668,6 +5718,7 @@ import {
|
|
|
5668
5718
|
CALLOUT_DEFAULT_BODY_PX,
|
|
5669
5719
|
CALLOUT_SHAPES,
|
|
5670
5720
|
calloutClip,
|
|
5721
|
+
calloutLook,
|
|
5671
5722
|
calloutGroundOf,
|
|
5672
5723
|
cameraModel as cameraModel2,
|
|
5673
5724
|
deltaE,
|
|
@@ -5686,10 +5737,11 @@ var CALLOUT_DELTA_E_PROBLEM = 8;
|
|
|
5686
5737
|
var CALLOUT_DELTA_E_WARNING = 16;
|
|
5687
5738
|
function registerFrom(roles, flags) {
|
|
5688
5739
|
const ground = flags.ground ?? roles?.bgA;
|
|
5689
|
-
const accent = flags.accent ?? roles?.accent;
|
|
5740
|
+
const accent = flags.accent ?? roles?.callout ?? roles?.accent;
|
|
5690
5741
|
if (!ground || !accent) return null;
|
|
5691
5742
|
if (!hexToRgb(ground) || !hexToRgb(accent)) return null;
|
|
5692
|
-
const
|
|
5743
|
+
const named = flags.face ?? roles?.fontBody;
|
|
5744
|
+
const face = named ? catalogFamily(named) : named;
|
|
5693
5745
|
return {
|
|
5694
5746
|
ground,
|
|
5695
5747
|
accent,
|
|
@@ -5755,16 +5807,28 @@ function composeCallout(doc, register, ask) {
|
|
|
5755
5807
|
let n = 2;
|
|
5756
5808
|
while (taken.has(id) && !ask.id)
|
|
5757
5809
|
id = `${ask.shape}-${ask.step ?? Math.round(window2.start * 10)}-${n++}`;
|
|
5810
|
+
const seen = appScaleAt(doc, window2.start + 0.35);
|
|
5811
|
+
const scale = ask.bodyPxGiven ? 1 : seen;
|
|
5812
|
+
const look = calloutLook(register, scale);
|
|
5758
5813
|
const clip = calloutClip(ask.shape, register, ask.words, {
|
|
5759
5814
|
id,
|
|
5760
5815
|
start: window2.start,
|
|
5761
5816
|
duration: window2.duration,
|
|
5762
|
-
scale
|
|
5817
|
+
scale,
|
|
5763
5818
|
pin,
|
|
5764
5819
|
// The fallback place, in the margin: the lower third.
|
|
5765
5820
|
at: { x: 0.5, y: 0.82 }
|
|
5766
5821
|
});
|
|
5767
|
-
return {
|
|
5822
|
+
return {
|
|
5823
|
+
clip,
|
|
5824
|
+
window: window2,
|
|
5825
|
+
sizes: {
|
|
5826
|
+
scale: +seen.toFixed(3),
|
|
5827
|
+
kickerPx: look.kickerPx,
|
|
5828
|
+
titlePx: look.titlePx,
|
|
5829
|
+
bodyPx: look.bodyPx
|
|
5830
|
+
}
|
|
5831
|
+
};
|
|
5768
5832
|
}
|
|
5769
5833
|
function isCalloutShape(s) {
|
|
5770
5834
|
return CALLOUT_SHAPES.includes(s);
|
|
@@ -6585,7 +6649,8 @@ async function recordTake(browser, url, actions, paths, log, opts = {}) {
|
|
|
6585
6649
|
const vh = actions.viewport?.height ?? 720;
|
|
6586
6650
|
const context = await browser.newContext({
|
|
6587
6651
|
viewport: { width: vw, height: vh },
|
|
6588
|
-
deviceScaleFactor: 1
|
|
6652
|
+
deviceScaleFactor: 1,
|
|
6653
|
+
...opts.storageState ? { storageState: opts.storageState } : {}
|
|
6589
6654
|
});
|
|
6590
6655
|
const page = await context.newPage();
|
|
6591
6656
|
page.on("console", (m) => {
|
|
@@ -7890,6 +7955,15 @@ function printChanges(r, changes, protectedIds) {
|
|
|
7890
7955
|
r.event({ event: "protected", nodes: protectedIds });
|
|
7891
7956
|
}
|
|
7892
7957
|
}
|
|
7958
|
+
function takePushRefusal(ask) {
|
|
7959
|
+
if (ask.programOnly.length) {
|
|
7960
|
+
const list = ask.programOnly.map((f) => `--${f}`).join(", ");
|
|
7961
|
+
return `${list} ${ask.programOnly.length > 1 ? "belong" : "belongs"} to a PROGRAM push (a config.json); a take push reads --vos, --title, --label, --note, --folder, --override and --yes`;
|
|
7962
|
+
}
|
|
7963
|
+
if (ask.vos !== void 0 && ask.trackedVosId !== null && ask.trackedVosId !== ask.vos)
|
|
7964
|
+
return `this take tracks vos ${ask.trackedVosId} (its vos.json), not ${ask.vos}. Drop --vos to push there, or remove vos.json to adopt ${ask.vos} instead`;
|
|
7965
|
+
return null;
|
|
7966
|
+
}
|
|
7893
7967
|
async function pushTake(dir, flags, r) {
|
|
7894
7968
|
const take = await loadTake(dir);
|
|
7895
7969
|
if (!take.doc) {
|
|
@@ -7906,7 +7980,22 @@ async function pushTake(dir, flags, r) {
|
|
|
7906
7980
|
);
|
|
7907
7981
|
}
|
|
7908
7982
|
const ctx = apiContext(flags);
|
|
7909
|
-
const
|
|
7983
|
+
const tracked = readSyncState(dir);
|
|
7984
|
+
const firstPush = tracked === null;
|
|
7985
|
+
let state = tracked;
|
|
7986
|
+
if (!state && flags.vos) {
|
|
7987
|
+
const meta = await api(ctx, `/vos/${flags.vos}`);
|
|
7988
|
+
const head = meta.json.vos?.currentVersionId;
|
|
7989
|
+
if (meta.status !== 200 || !head) {
|
|
7990
|
+
throw new Error(
|
|
7991
|
+
`--vos ${flags.vos}: cannot adopt it (${meta.status}${meta.json.error ? `: ${String(meta.json.error)}` : ""}) \u2014 it must be a vos this credential can read, with a version to build on`
|
|
7992
|
+
);
|
|
7993
|
+
}
|
|
7994
|
+
r.log(
|
|
7995
|
+
`adopting vos ${flags.vos}: this take becomes the next version after its head (${head})`
|
|
7996
|
+
);
|
|
7997
|
+
state = { vosId: flags.vos, versionId: head };
|
|
7998
|
+
}
|
|
7910
7999
|
let folderId;
|
|
7911
8000
|
if (flags.folder) {
|
|
7912
8001
|
if (state) {
|
|
@@ -7919,7 +8008,7 @@ async function pushTake(dir, flags, r) {
|
|
|
7919
8008
|
flags.folder
|
|
7920
8009
|
).id;
|
|
7921
8010
|
}
|
|
7922
|
-
if (
|
|
8011
|
+
if (firstPush && !flags.yes) {
|
|
7923
8012
|
if (!process.stdin.isTTY) {
|
|
7924
8013
|
throw new Error(
|
|
7925
8014
|
"first push of this take uploads its recording \u2014 pass --yes to consent headlessly"
|
|
@@ -9311,10 +9400,12 @@ function composeBrand(input) {
|
|
|
9311
9400
|
const bgC = mixHex(bgA, accent, 0.14);
|
|
9312
9401
|
p.bgC = `bgA tinted 14% toward the accent (a highlight ground)`;
|
|
9313
9402
|
p.ink = w.h1 ? `the h1's colour` : `the body's colour`;
|
|
9314
|
-
const fontDisplay =
|
|
9403
|
+
const fontDisplay = catalogFamily(
|
|
9404
|
+
design?.fonts[0] ?? (w.h1 ? firstFamily(w.h1.fontFamily) : firstFamily(w.body.fontFamily))
|
|
9405
|
+
);
|
|
9315
9406
|
p.fontDisplay = design?.fonts[0] ? `named in design.md` : w.h1 ? `the h1's computed face` : `the body's computed face (no h1)`;
|
|
9316
9407
|
const designBody = design?.fonts.slice(1).find((f) => !/\bmono\b/i.test(f));
|
|
9317
|
-
const fontBody = designBody ?? firstFamily(w.body.fontFamily);
|
|
9408
|
+
const fontBody = catalogFamily(designBody ?? firstFamily(w.body.fontFamily));
|
|
9318
9409
|
p.fontBody = designBody ? `named in design.md` : `the body's computed face`;
|
|
9319
9410
|
const isIcon = (u) => /favicon|apple-touch|icon/i.test(u);
|
|
9320
9411
|
const onDark = (u) => /on-dark|white/i.test(u);
|
|
@@ -10016,14 +10107,15 @@ var BOOLEAN_FLAGS5 = /* @__PURE__ */ new Set([
|
|
|
10016
10107
|
"composed",
|
|
10017
10108
|
"check",
|
|
10018
10109
|
"motion",
|
|
10019
|
-
"leader"
|
|
10110
|
+
"leader",
|
|
10111
|
+
"keep-frames"
|
|
10020
10112
|
]);
|
|
10021
|
-
var MULTI_FLAGS2 = /* @__PURE__ */ new Set(["set", "override"]);
|
|
10113
|
+
var MULTI_FLAGS2 = /* @__PURE__ */ new Set(["set", "override", "browser-arg"]);
|
|
10022
10114
|
var HELP = `vos \u2014 record a browser flow, plan effects, render a product video; sync with vos.so
|
|
10023
10115
|
|
|
10024
10116
|
Take pipeline
|
|
10025
|
-
vos create --actions actions.json [--url <url>] [--out take] [out.webm] [--strict] [--max-duration <s>] [--background <slug|url|none>] [render flags] [--json]
|
|
10026
|
-
vos record --actions actions.json [--url <url>] [--out take] [--strict] [--max-duration <s>] [--background <slug|url|none>] [--json]
|
|
10117
|
+
vos create --actions actions.json [--url <url>] [--out take] [out.webm] [--strict] [--keep-frames] [--max-duration <s>] [--storage-state <file>] [--browser-arg=<switch>]... [--background <slug|url|none>] [render flags] [--json]
|
|
10118
|
+
vos record --actions actions.json [--url <url>] [--out take] [--strict] [--keep-frames] [--max-duration <s>] [--storage-state <file>] [--browser-arg=<switch>]... [--background <slug|url|none>] [--json]
|
|
10027
10119
|
vos plan <take> [--fresh] [--reuse [--from <doc.json>]] [--style <doc.json|vosId>] [--with <doc.json|vosId>[@end|@start|@step:<id>|@<s>]]... [--background <slug|url|none>] [--motion] [--headline "\u2026"] [--kicker "\u2026"] [--launch LAUNCH.md] [--brand BRAND.md] [--music <slug|mood|none>] [--entrance tilt-in|pull-out|rise|fade|slide|none] [--transitions slide|fade|scale|none] [--end-card on|none|<doc.json|vosId>] [--captions none] [--clicks none] [--still <t>] [--release v2.1] [--json]
|
|
10028
10120
|
vos render <take> [out.webm] [--width] [--height] [--fps] [--format webm|mp4] [--parallel N] [--range a..b] [--draft] [--frame <kind>] [--background <url|slug>] [--set <path=value>]... [--json]
|
|
10029
10121
|
vos frames <take> [--times 0,25%,50%,75%,100%] [--frame <t>] [--at-zooms] [--at-moments] [--at-still] [--size WxH] [--out dir] [--background <url|slug>] [--set <path=value>]... [--json]
|
|
@@ -10031,7 +10123,7 @@ Take pipeline
|
|
|
10031
10123
|
vos digest <take> [--out dir] [--full 960] [--crop 640] [--no-frames] [--transcript <file.json>] [--style <doc.json|vosId>] [--json]
|
|
10032
10124
|
vos brand <url> [--out BRAND.md] [--json]
|
|
10033
10125
|
vos open <take> [--studio <url>] [--print]
|
|
10034
|
-
vos callout <take> <note|tag|code> --step <id> [--title "\u2026"] [--body "\u2026"] [--kicker "\u2026"] [--code "\u2026"|--code-file f] [--seconds 3] [--side auto|right|left|below|above] [--mark ring|underline|none] [--leader] [--color #hex] [--brand BRAND.md] [--ground #hex] [--accent #hex] [--font "\u2026"] [--body-px
|
|
10126
|
+
vos callout <take> <note|tag|code> --step <id> [--title "\u2026"] [--body "\u2026"] [--kicker "\u2026"] [--code "\u2026"|--code-file f] [--seconds 3] [--side auto|right|left|below|above] [--mark ring|underline|none] [--leader] [--color #hex (the mark and leader; the kicker is --accent)] [--brand BRAND.md] [--ground #hex] [--accent #hex] [--font "\u2026"] [--body-px <n> (the body size on the delivered frame)] [--id x] [--print] [--json]
|
|
10035
10127
|
vos validate <actions.json|take|kit.json> [--picture] [--json]
|
|
10036
10128
|
vos judge <kit.json> --against <MANIFEST.json> [--out dir] [--json]
|
|
10037
10129
|
vos actions from-agent-browser <steps.jsonl> [--out actions.json] [--url <url>] [--viewport WxH] [--json]
|
|
@@ -10051,7 +10143,10 @@ Platform (vos.so) \u2014 fetch, edit, push, pull, repeat
|
|
|
10051
10143
|
a take DIRECTORY (doc.json) pushes recording + doc; a config.json
|
|
10052
10144
|
pushes the program. No --vos: create a PRIVATE vos; with --vos:
|
|
10053
10145
|
add a version against the tracked base \u2014 a stale push 409s WITH
|
|
10054
|
-
the platform's typed changelog.
|
|
10146
|
+
the platform's typed changelog. A TAKE pushes to the vos in its
|
|
10147
|
+
vos.json; --vos on a take with none ADOPTS that vos (the take
|
|
10148
|
+
becomes its next version, built on its head), and --vos that
|
|
10149
|
+
disagrees with vos.json is refused before anything uploads. --claimable (programs only, NO
|
|
10055
10150
|
credential): creates a 72h claim link instead \u2014 hand it to the
|
|
10056
10151
|
user and nowhere else; unclaimed work is deleted after 72h.
|
|
10057
10152
|
--override consents to touching
|
|
@@ -10298,6 +10393,18 @@ function strictReason(rec) {
|
|
|
10298
10393
|
if (rec.capped) parts.push("stopped at --max-duration");
|
|
10299
10394
|
return parts.join(" + ");
|
|
10300
10395
|
}
|
|
10396
|
+
function takeBrowserArgs(multi) {
|
|
10397
|
+
const given = multi["browser-arg"];
|
|
10398
|
+
return (given ?? []).filter(Boolean);
|
|
10399
|
+
}
|
|
10400
|
+
function takeStorageState(flags) {
|
|
10401
|
+
const raw = strFlag(flags, "storage-state");
|
|
10402
|
+
if (!raw) return void 0;
|
|
10403
|
+
const path = resolve9(raw);
|
|
10404
|
+
if (!existsSync15(path))
|
|
10405
|
+
throw new UsageError(`--storage-state: no such file: ${path}`);
|
|
10406
|
+
return path;
|
|
10407
|
+
}
|
|
10301
10408
|
async function takeBackdrop(flags, r) {
|
|
10302
10409
|
const { backdrop, note } = await openingBackdrop(
|
|
10303
10410
|
strFlag(flags, "background"),
|
|
@@ -10309,8 +10416,20 @@ async function takeBackdrop(flags, r) {
|
|
|
10309
10416
|
if (note) r.log(`note: ${note}`);
|
|
10310
10417
|
return backdrop;
|
|
10311
10418
|
}
|
|
10419
|
+
async function releaseFrames(paths, flags, log) {
|
|
10420
|
+
if (flags["keep-frames"] === true) return;
|
|
10421
|
+
const freed = await dropScreencastFrames(paths);
|
|
10422
|
+
if (freed >= 1e6)
|
|
10423
|
+
log(
|
|
10424
|
+
`released ${Math.round(freed / 1e6)} MB of screencast frames (the recording holds them now; --keep-frames keeps them)`
|
|
10425
|
+
);
|
|
10426
|
+
}
|
|
10312
10427
|
async function cmdRecord(argv) {
|
|
10313
|
-
const { positionals, flags } = parseArgs(
|
|
10428
|
+
const { positionals, flags, multi } = parseArgs(
|
|
10429
|
+
argv,
|
|
10430
|
+
BOOLEAN_FLAGS5,
|
|
10431
|
+
MULTI_FLAGS2
|
|
10432
|
+
);
|
|
10314
10433
|
const actionsPath = strFlag(flags, "actions") ?? positionals[0];
|
|
10315
10434
|
if (!actionsPath)
|
|
10316
10435
|
throw new UsageError(
|
|
@@ -10324,6 +10443,8 @@ async function cmdRecord(argv) {
|
|
|
10324
10443
|
const outDir = resolve9(strFlag(flags, "out") ?? "take");
|
|
10325
10444
|
const backdrop = await takeBackdrop(flags, r);
|
|
10326
10445
|
const maxDurationSeconds = await maxDuration(flags, r);
|
|
10446
|
+
const storageState = takeStorageState(flags);
|
|
10447
|
+
const browserArgs = takeBrowserArgs(multi);
|
|
10327
10448
|
if (existsSync15(join18(outDir, "meta.json"))) {
|
|
10328
10449
|
const { prevDoc, kept } = await prepareReRecord(outDir);
|
|
10329
10450
|
r.log(
|
|
@@ -10332,12 +10453,13 @@ async function cmdRecord(argv) {
|
|
|
10332
10453
|
}
|
|
10333
10454
|
await mkdir10(outDir, { recursive: true });
|
|
10334
10455
|
const paths = await ensureTakeDir(outDir);
|
|
10335
|
-
const browser = await launchBrowser();
|
|
10456
|
+
const browser = await launchBrowser(browserArgs);
|
|
10336
10457
|
try {
|
|
10337
10458
|
r.log("recording\u2026");
|
|
10338
10459
|
r.event({ event: "phase", phase: "record" });
|
|
10339
10460
|
const rec = await recordTake(browser, url, actions, paths, r.log, {
|
|
10340
|
-
maxDurationSeconds
|
|
10461
|
+
maxDurationSeconds,
|
|
10462
|
+
storageState
|
|
10341
10463
|
});
|
|
10342
10464
|
r.event({ event: "phase", phase: "encode" });
|
|
10343
10465
|
r.log("encoding\u2026");
|
|
@@ -10346,6 +10468,7 @@ async function cmdRecord(argv) {
|
|
|
10346
10468
|
outDir,
|
|
10347
10469
|
(p) => r.event({ event: "progress", phase: "encode", fraction: p })
|
|
10348
10470
|
);
|
|
10471
|
+
await releaseFrames(paths, flags, r.log);
|
|
10349
10472
|
r.event({ event: "phase", phase: "plan" });
|
|
10350
10473
|
const plan = await planTake(outDir, { backdrop });
|
|
10351
10474
|
const clicks = rec.events.filter((e) => e.type === "down").length;
|
|
@@ -10408,6 +10531,8 @@ async function cmdCreate2(argv) {
|
|
|
10408
10531
|
}
|
|
10409
10532
|
const backdrop = await takeBackdrop(flags, r);
|
|
10410
10533
|
const maxDurationSeconds = await maxDuration(flags, r);
|
|
10534
|
+
const storageState = takeStorageState(flags);
|
|
10535
|
+
const browserArgs = takeBrowserArgs(multi);
|
|
10411
10536
|
if (existsSync15(join18(outDir, "meta.json"))) {
|
|
10412
10537
|
const { prevDoc, kept } = await prepareReRecord(outDir);
|
|
10413
10538
|
r.log(
|
|
@@ -10416,12 +10541,13 @@ async function cmdCreate2(argv) {
|
|
|
10416
10541
|
}
|
|
10417
10542
|
await mkdir10(outDir, { recursive: true });
|
|
10418
10543
|
const paths = await ensureTakeDir(outDir);
|
|
10419
|
-
const browser = await launchBrowser();
|
|
10544
|
+
const browser = await launchBrowser(browserArgs);
|
|
10420
10545
|
try {
|
|
10421
10546
|
r.log("recording\u2026");
|
|
10422
10547
|
r.event({ event: "phase", phase: "record" });
|
|
10423
10548
|
const rec = await recordTake(browser, url, actions, paths, r.log, {
|
|
10424
|
-
maxDurationSeconds
|
|
10549
|
+
maxDurationSeconds,
|
|
10550
|
+
storageState
|
|
10425
10551
|
});
|
|
10426
10552
|
r.event({ event: "phase", phase: "encode" });
|
|
10427
10553
|
r.log("encoding\u2026");
|
|
@@ -10430,6 +10556,7 @@ async function cmdCreate2(argv) {
|
|
|
10430
10556
|
outDir,
|
|
10431
10557
|
(p) => r.event({ event: "progress", phase: "encode", fraction: p })
|
|
10432
10558
|
);
|
|
10559
|
+
await releaseFrames(paths, flags, r.log);
|
|
10433
10560
|
r.event({ event: "phase", phase: "plan" });
|
|
10434
10561
|
await planTake(outDir, { backdrop });
|
|
10435
10562
|
if (flags.strict === true && (rec.skipped.length > 0 || rec.navTimeout || rec.capped)) {
|
|
@@ -11129,7 +11256,7 @@ async function cmdCallout(argv) {
|
|
|
11129
11256
|
const shape = positionals[1];
|
|
11130
11257
|
if (!dir || !shape || !isCalloutShape(shape))
|
|
11131
11258
|
throw new UsageError(
|
|
11132
|
-
'vos callout <take> <note|tag|code> --step <id> [--title "\u2026"] [--body "\u2026"] [--kicker "\u2026"] [--code "\u2026"|--code-file f] [--seconds 3] [--side \u2026] [--mark ring|underline|none] [--leader] [--color #hex] [--brand BRAND.md] [--ground #hex --accent #hex] [--font "\u2026"] [--body-px
|
|
11259
|
+
'vos callout <take> <note|tag|code> --step <id> [--title "\u2026"] [--body "\u2026"] [--kicker "\u2026"] [--code "\u2026"|--code-file f] [--seconds 3] [--side \u2026] [--mark ring|underline|none] [--leader] [--color #hex (the mark and leader; the kicker is --accent)] [--brand BRAND.md] [--ground #hex --accent #hex] [--font "\u2026"] [--body-px <n> (the body size on the delivered frame)] [--id x] [--print] [--json]'
|
|
11133
11260
|
);
|
|
11134
11261
|
const r = createReporter(flags.json === true);
|
|
11135
11262
|
const take = await loadTake(dir);
|
|
@@ -11180,15 +11307,16 @@ async function cmdCallout(argv) {
|
|
|
11180
11307
|
side,
|
|
11181
11308
|
mark,
|
|
11182
11309
|
leader: flags.leader === true,
|
|
11183
|
-
color: strFlag(flags, "color")
|
|
11310
|
+
color: strFlag(flags, "color"),
|
|
11311
|
+
bodyPxGiven: bodyPx !== void 0
|
|
11184
11312
|
});
|
|
11185
11313
|
} catch (e) {
|
|
11186
11314
|
throw new UsageError(e instanceof Error ? e.message : String(e));
|
|
11187
11315
|
}
|
|
11188
|
-
const { clip, window: window2 } = composed;
|
|
11316
|
+
const { clip, window: window2, sizes } = composed;
|
|
11189
11317
|
if (flags.print === true) {
|
|
11190
11318
|
r.done(
|
|
11191
|
-
{ clip, window: window2, register, brand: brand?.file ?? null },
|
|
11319
|
+
{ clip, window: window2, sizes, register, brand: brand?.file ?? null },
|
|
11192
11320
|
JSON.stringify(clip, null, 2)
|
|
11193
11321
|
);
|
|
11194
11322
|
return EXIT_OK;
|
|
@@ -11210,11 +11338,12 @@ async function cmdCallout(argv) {
|
|
|
11210
11338
|
{
|
|
11211
11339
|
clip,
|
|
11212
11340
|
window: window2,
|
|
11341
|
+
sizes,
|
|
11213
11342
|
register,
|
|
11214
11343
|
brand: brand?.file ?? null,
|
|
11215
11344
|
warnings: lint.warnings
|
|
11216
11345
|
},
|
|
11217
|
-
`${shape} "${clip.id}" at ${window2.start.toFixed(2)}s for ${window2.duration.toFixed(2)}s${clip.pin ? `, pinned to ${clip.pin.step !== void 0 ? `step ${String(clip.pin.step)}` : `the press at ${String(clip.pin.press)}s`}` : ""}, ground ${register.ground} \u2192 card in the product's hue, written to ${take.paths.doc}${lint.warnings.length ? `
|
|
11346
|
+
`${shape} "${clip.id}" at ${window2.start.toFixed(2)}s for ${window2.duration.toFixed(2)}s${clip.pin ? `, pinned to ${clip.pin.step !== void 0 ? `step ${String(clip.pin.step)}` : `the press at ${String(clip.pin.press)}s`}` : ""}, ground ${register.ground} \u2192 card in the product's hue, type ${sizes.kickerPx} / ${sizes.titlePx} / ${sizes.bodyPx} px (kicker / title / body; ${bodyPx !== void 0 ? `--body-px ${bodyPx} as delivered` : `the app's body as seen, footage scale ${sizes.scale}; --body-px <n> sets the delivered size`}), written to ${take.paths.doc}${lint.warnings.length ? `
|
|
11218
11347
|
warnings:
|
|
11219
11348
|
${lint.warnings.join("\n ")}` : ""}`
|
|
11220
11349
|
);
|
|
@@ -11377,8 +11506,16 @@ async function cmdPush3(argv) {
|
|
|
11377
11506
|
const dir = positionals[0];
|
|
11378
11507
|
if (!dir)
|
|
11379
11508
|
throw new UsageError(
|
|
11380
|
-
"vos push <take> [--title|--label|--note|--folder|--override|--yes|--key|--api]"
|
|
11509
|
+
"vos push <take> [--vos|--title|--label|--note|--folder|--override|--yes|--key|--api]"
|
|
11381
11510
|
);
|
|
11511
|
+
const refusal = takePushRefusal({
|
|
11512
|
+
vos: strFlag(flags, "vos"),
|
|
11513
|
+
trackedVosId: readSyncState(resolve9(dir))?.vosId ?? null,
|
|
11514
|
+
programOnly: ["slug", "desc", "tags", "base", "remix-of"].filter(
|
|
11515
|
+
(name) => hasFlag(flags, name)
|
|
11516
|
+
)
|
|
11517
|
+
});
|
|
11518
|
+
if (refusal) throw new UsageError(refusal);
|
|
11382
11519
|
const r = createReporter(flags.json === true);
|
|
11383
11520
|
const overrides = multi.override;
|
|
11384
11521
|
const result = await pushTake(
|
|
@@ -11388,6 +11525,7 @@ async function cmdPush3(argv) {
|
|
|
11388
11525
|
api: strFlag(flags, "api"),
|
|
11389
11526
|
origin: strFlag(flags, "origin"),
|
|
11390
11527
|
yes: flags.yes === true,
|
|
11528
|
+
vos: strFlag(flags, "vos"),
|
|
11391
11529
|
title: strFlag(flags, "title"),
|
|
11392
11530
|
label: strFlag(flags, "label"),
|
|
11393
11531
|
note: strFlag(flags, "note"),
|
|
@@ -11548,6 +11686,9 @@ export {
|
|
|
11548
11686
|
parseAgentBrowserLog,
|
|
11549
11687
|
splitCommand,
|
|
11550
11688
|
convertAgentBrowser,
|
|
11689
|
+
MULTI_FLAGS2 as MULTI_FLAGS,
|
|
11690
|
+
HELP,
|
|
11691
|
+
takeBrowserArgs,
|
|
11551
11692
|
run
|
|
11552
11693
|
};
|
|
11553
|
-
//# sourceMappingURL=chunk-
|
|
11694
|
+
//# sourceMappingURL=chunk-LGRNHJ2U.js.map
|