@vosjs/cli 0.28.1 → 0.29.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 +2 -0
- package/dist/{chunk-T35XY4YW.js → chunk-GSRCASV2.js} +55 -4
- package/dist/chunk-GSRCASV2.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{run-QAI3HGTK.js → run-2KGUUW4W.js} +2 -2
- package/package.json +5 -5
- package/schema/doc.schema.json +43 -3
- package/dist/chunk-T35XY4YW.js.map +0 -1
- /package/dist/{run-QAI3HGTK.js.map → run-2KGUUW4W.js.map} +0 -0
package/README.md
CHANGED
|
@@ -161,6 +161,8 @@ Verified the flow in agent-browser already? `vos actions from-agent-browser step
|
|
|
161
161
|
|
|
162
162
|
**Image and video overlays.** Media kinds on the same lane: `{ "id": "m0", "kind": "image" | "video", "start": 2, "duration": 4, "key": "/logo.png", "width": 0.35, "radius": 12, "opacity": 1, "loop": false, "transform": { … } }`. `key` is a file inside the take directory (`"/logo.png"`) or a URL; `width` is a fraction of the frame width, height follows the media's aspect; corners in design px. Video time is clip-local and muted by design; soundtracks belong to `doc.audio`.
|
|
163
163
|
|
|
164
|
+
**HTML layers.** A UI component authored as DOM on the same lane, sharp at any export size because it is rasterized from source, not magnified from the footage: `{ "id": "h0", "kind": "html", "start": 2, "duration": 4, "html": "<div class=\"card\">Open Code</div>", "css": ".card{font-family:'Inter';background:#0b0b0d;border-radius:16px;box-shadow:0 24px 60px rgba(0,0,0,.45)}", "box": { "width": 452, "height": 132 }, "transform": { … } }`. The markup is well-formed XML (`<br />`, `&`, quoted attributes; `vos validate` refuses the rest in words, because a malformed layer decodes to nothing and says nothing). `box` is the design box in 1080p px; `width` defaults to the design size. The CSS is the chrome (shadow, radius, border; `bleed` is derived from the shadows, or stated), a `font-family` it names resolves against the hosted catalog at every `font-weight` it names (a face outside the catalog rides `fonts: [{ family, url }]`), an image inside must be a `data:` URI, and an `animation` runs on the wall clock rather than the timeline, so animate the layer with `anim` and `motion`. It is never re-hosted and never an upload.
|
|
165
|
+
|
|
164
166
|
**3D props.** `doc.objects`: world-space props between the card and the overlays. `{ "id": "p0", "asset": { "kind": "primitive", "shape": "knot", "color": "#ffb03a" }, "span": { "start": 1, "duration": 3 }, "transform3d": { "x": 0.8, "y": 0.28, "z": 0.5, "rx": 0, "ry": 40, "rz": 0, "scale": 0.18 }, "animation": "spin" }`. Shapes `cube`, `sphere`, `torus`, `knot`; `kind: "gltf"` with `key` loads a GLB (bounding-box normalized so `scale` means the same for every model; a bad model fails open). `x`/`y` are frame fractions, `z` world units toward the camera from the card plane, `scale` a fraction of the frame height; `animation` is `spin` or `float`, deterministic.
|
|
165
167
|
|
|
166
168
|
**Audio.** `doc.audio` clips (music, effects, `key` a take-directory file or a URL) are mixed with gain, fade and loop envelopes and muxed into every full render: Opus for webm, AAC (Opus fallback) for mp4. Audio forces single-flight (`--parallel` is ignored with a note); a `--range` render keeps its audio.
|
|
@@ -189,6 +189,7 @@ import {
|
|
|
189
189
|
SEGMENT_EXIT_KINDS,
|
|
190
190
|
enterOf,
|
|
191
191
|
exitOf,
|
|
192
|
+
htmlLayerProblems,
|
|
192
193
|
segmentOutputExtents,
|
|
193
194
|
transitionSeconds,
|
|
194
195
|
CARD_EXIT_KINDS,
|
|
@@ -926,9 +927,9 @@ function lintDoc(docIn) {
|
|
|
926
927
|
problems.push(`${name} must be an object`);
|
|
927
928
|
continue;
|
|
928
929
|
}
|
|
929
|
-
if (o.kind !== "text" && o.kind !== "image" && o.kind !== "video") {
|
|
930
|
+
if (o.kind !== "text" && o.kind !== "image" && o.kind !== "video" && o.kind !== "html") {
|
|
930
931
|
problems.push(
|
|
931
|
-
`${name}.kind must be "text" | "image" | "video" (got ${String(o.kind)})`
|
|
932
|
+
`${name}.kind must be "text" | "image" | "video" | "html" (got ${String(o.kind)})`
|
|
932
933
|
);
|
|
933
934
|
}
|
|
934
935
|
if (!isNum(o.start) || o.start < 0)
|
|
@@ -1105,6 +1106,55 @@ function lintDoc(docIn) {
|
|
|
1105
1106
|
problems.push(`${name}.opacity must be 0..1`);
|
|
1106
1107
|
}
|
|
1107
1108
|
}
|
|
1109
|
+
if (o.kind === "html") {
|
|
1110
|
+
if (typeof o.html !== "string") {
|
|
1111
|
+
problems.push(`${name}.html must be the layer's markup (a string)`);
|
|
1112
|
+
}
|
|
1113
|
+
if (o.css !== void 0 && typeof o.css !== "string") {
|
|
1114
|
+
problems.push(`${name}.css must be a string of CSS`);
|
|
1115
|
+
}
|
|
1116
|
+
const box = isObj(o.box) ? o.box : void 0;
|
|
1117
|
+
if (!box || !isNum(box.width) || !isNum(box.height) || box.width <= 0 || box.height <= 0) {
|
|
1118
|
+
problems.push(
|
|
1119
|
+
`${name}.box must be { width, height } in design px, both > 0 (the 1080p frame is 1920 wide)`
|
|
1120
|
+
);
|
|
1121
|
+
}
|
|
1122
|
+
if (o.bleed !== void 0 && (!isNum(o.bleed) || o.bleed < 0)) {
|
|
1123
|
+
problems.push(
|
|
1124
|
+
`${name}.bleed must be \u2265 0 design px (absent = derived from the CSS's shadows)`
|
|
1125
|
+
);
|
|
1126
|
+
}
|
|
1127
|
+
if (o.fonts !== void 0) {
|
|
1128
|
+
if (!Array.isArray(o.fonts)) {
|
|
1129
|
+
problems.push(
|
|
1130
|
+
`${name}.fonts must be an array of { family, url, weight?, style? }`
|
|
1131
|
+
);
|
|
1132
|
+
} else {
|
|
1133
|
+
o.fonts.forEach((f, fi) => {
|
|
1134
|
+
if (!isObj(f) || typeof f.family !== "string" || typeof f.url !== "string" || !/^https?:\/\//.test(f.url))
|
|
1135
|
+
problems.push(
|
|
1136
|
+
`${name}.fonts[${fi}] must be { family, url (https), weight?, style? }: a face the catalog does not host. A hosted family needs no entry; name it in the CSS`
|
|
1137
|
+
);
|
|
1138
|
+
});
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
if (o.width !== void 0 && (!isNum(o.width) || o.width <= 0 || o.width > 1)) {
|
|
1142
|
+
problems.push(
|
|
1143
|
+
`${name}.width must be a fraction of the frame width in (0..1] (got ${String(o.width)}; absent = the design size)`
|
|
1144
|
+
);
|
|
1145
|
+
}
|
|
1146
|
+
if (o.opacity !== void 0 && (!isNum(o.opacity) || o.opacity < 0 || o.opacity > 1)) {
|
|
1147
|
+
problems.push(`${name}.opacity must be 0..1`);
|
|
1148
|
+
}
|
|
1149
|
+
if (typeof o.html === "string") {
|
|
1150
|
+
for (const p of htmlLayerProblems(o)) {
|
|
1151
|
+
;
|
|
1152
|
+
(p.level === "problem" ? problems : warnings).push(
|
|
1153
|
+
`${name}: ${p.message}`
|
|
1154
|
+
);
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1108
1158
|
const tf = isObj(o.transform) ? o.transform : void 0;
|
|
1109
1159
|
if (!tf) {
|
|
1110
1160
|
problems.push(
|
|
@@ -6515,6 +6565,7 @@ import { basename, join as join15 } from "path";
|
|
|
6515
6565
|
import { lowerToComposition as lowerToComposition3, migrateHostedDoc as migrateHostedDoc3 } from "@vosjs/studio-core";
|
|
6516
6566
|
|
|
6517
6567
|
// src/plugin/media.ts
|
|
6568
|
+
import { isKeyedOverlay } from "@vosjs/studio-core";
|
|
6518
6569
|
import { createWriteStream, existsSync as existsSync11 } from "fs";
|
|
6519
6570
|
import { writeFile as writeFile9 } from "fs/promises";
|
|
6520
6571
|
import { join as join13 } from "path";
|
|
@@ -6562,7 +6613,7 @@ function docMediaRefs(doc, keep = isTakeRelativeKey) {
|
|
|
6562
6613
|
});
|
|
6563
6614
|
}
|
|
6564
6615
|
for (const clip of doc.overlays ?? []) {
|
|
6565
|
-
if (clip
|
|
6616
|
+
if (!isKeyedOverlay(clip) || !keep(clip.key)) continue;
|
|
6566
6617
|
out.push({
|
|
6567
6618
|
where: `overlay ${clip.id}`,
|
|
6568
6619
|
key: clip.key,
|
|
@@ -10536,4 +10587,4 @@ export {
|
|
|
10536
10587
|
convertAgentBrowser,
|
|
10537
10588
|
run
|
|
10538
10589
|
};
|
|
10539
|
-
//# sourceMappingURL=chunk-
|
|
10590
|
+
//# sourceMappingURL=chunk-GSRCASV2.js.map
|