@vosjs/cli 0.58.0 → 0.58.1
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/dist/{chunk-K6PE735V.js → chunk-RZZUR2IF.js} +119 -10
- package/dist/{chunk-K6PE735V.js.map → chunk-RZZUR2IF.js.map} +1 -1
- package/dist/cli.js +3 -3
- package/dist/index.js +1 -1
- package/dist/{run-O747IZNO.js → run-BOJVRM3P.js} +2 -2
- package/package.json +6 -6
- package/schema/doc.schema.json +6 -0
- /package/dist/{run-O747IZNO.js.map → run-BOJVRM3P.js.map} +0 -0
|
@@ -185,6 +185,37 @@ import {
|
|
|
185
185
|
unionFitLevel
|
|
186
186
|
} from "@vosjs/studio-core";
|
|
187
187
|
import { TYPEFACE_CATALOG, findFontFamily, findTypeface } from "@vosjs/shared";
|
|
188
|
+
var PIN_NEAR_FRACTION = 0.08;
|
|
189
|
+
var PIN_SURFACE_AREA = 0.25;
|
|
190
|
+
var LABEL_STOPWORDS = /* @__PURE__ */ new Set([
|
|
191
|
+
"the",
|
|
192
|
+
"and",
|
|
193
|
+
"for",
|
|
194
|
+
"with",
|
|
195
|
+
"your",
|
|
196
|
+
"you",
|
|
197
|
+
"this",
|
|
198
|
+
"that",
|
|
199
|
+
"from",
|
|
200
|
+
"into",
|
|
201
|
+
"button",
|
|
202
|
+
"link"
|
|
203
|
+
]);
|
|
204
|
+
function wordsOf(text) {
|
|
205
|
+
return text.toLowerCase().split(/[^a-z0-9]+/).filter((x) => x.length >= 3 && !LABEL_STOPWORDS.has(x));
|
|
206
|
+
}
|
|
207
|
+
function layerWords(o) {
|
|
208
|
+
const src = typeof o.html === "string" ? o.html.replace(/<[^>]*>/g, " ") : typeof o.text === "string" ? o.text : "";
|
|
209
|
+
return new Set(wordsOf(src));
|
|
210
|
+
}
|
|
211
|
+
function selectorLabelWords(selector) {
|
|
212
|
+
const out = [];
|
|
213
|
+
const re = /(?:has-text\(|text=|(?:aria-label|title|alt|placeholder|name)\s*[*^$~|]?=\s*)['"]([^'"]+)['"]/g;
|
|
214
|
+
for (let m = re.exec(selector); m; m = re.exec(selector)) {
|
|
215
|
+
out.push(...wordsOf(m[1]));
|
|
216
|
+
}
|
|
217
|
+
return [...new Set(out)];
|
|
218
|
+
}
|
|
188
219
|
var STEP_KINDS_ALL = [
|
|
189
220
|
"none",
|
|
190
221
|
"fade",
|
|
@@ -248,6 +279,20 @@ function lintAnim(name, anim, kinds, problems) {
|
|
|
248
279
|
if (key === "stagger" && (typeof obj.stagger !== "number" || obj.stagger < 0 || obj.stagger > 2))
|
|
249
280
|
problems.push(`${name}.anim.${side}.stagger must be seconds in 0..2`);
|
|
250
281
|
}
|
|
282
|
+
if (obj.at !== void 0) {
|
|
283
|
+
if (!kinds.card || side !== "enter")
|
|
284
|
+
problems.push(
|
|
285
|
+
`${name}.anim.${side}.at is the card's own: frame.anim.enter.at delays the card's entrance; a clip already starts at its own start`
|
|
286
|
+
);
|
|
287
|
+
else if (typeof obj.at !== "number" || !Number.isFinite(obj.at) || obj.at < 0 || obj.at > 30)
|
|
288
|
+
problems.push(
|
|
289
|
+
`${name}.anim.enter.at must be OUTPUT seconds in 0..30 (when the card arrives; the ground plays alone until then)`
|
|
290
|
+
);
|
|
291
|
+
else if (kind === "none")
|
|
292
|
+
problems.push(
|
|
293
|
+
`${name}.anim.enter.at has nothing to delay: the enter is "none", so the card is on screen from the first frame`
|
|
294
|
+
);
|
|
295
|
+
}
|
|
251
296
|
if (obj.side !== void 0) {
|
|
252
297
|
if (kind !== "slide")
|
|
253
298
|
problems.push(`${name}.anim.${side}.side is for a slide`);
|
|
@@ -599,6 +644,7 @@ function lintDoc(docIn) {
|
|
|
599
644
|
}
|
|
600
645
|
const tilt = entries(doc.tilt);
|
|
601
646
|
checkByMedia(tilt, "tilt");
|
|
647
|
+
const dramatic = [];
|
|
602
648
|
for (const t of tilt) {
|
|
603
649
|
const name = spanName("tilt", t);
|
|
604
650
|
for (const ax of ["rx", "ry"]) {
|
|
@@ -611,8 +657,8 @@ function lintDoc(docIn) {
|
|
|
611
657
|
}
|
|
612
658
|
checkTransition(t, name, problems);
|
|
613
659
|
if (isNum(t.rx) && isNum(t.ry) && Math.abs(t.rx) + Math.abs(t.ry) > 25) {
|
|
614
|
-
|
|
615
|
-
`${name}
|
|
660
|
+
dramatic.push(
|
|
661
|
+
`${name} ${(Math.abs(t.rx) + Math.abs(t.ry)).toFixed(0)}\xB0`
|
|
616
662
|
);
|
|
617
663
|
}
|
|
618
664
|
if (t.source !== void 0 && t.source !== "manual" && t.source !== "auto") {
|
|
@@ -624,6 +670,11 @@ function lintDoc(docIn) {
|
|
|
624
670
|
);
|
|
625
671
|
}
|
|
626
672
|
}
|
|
673
|
+
if (dramatic.length) {
|
|
674
|
+
warnings.push(
|
|
675
|
+
`tilt: ${dramatic.length === 1 ? "a span leans" : `${dramatic.length} spans lean`} past 25\xB0 combined (${dramatic.join(", ")}) and read${dramatic.length === 1 ? "s" : ""} dramatic \u2014 the premium band is \xB15..18\xB0 per axis; keep it if the piece means it`
|
|
676
|
+
);
|
|
677
|
+
}
|
|
627
678
|
if (typeof doc.zoomStyle === "string" && doc.zoomStyle in RETIRED_ZOOM_STYLES) {
|
|
628
679
|
const r = RETIRED_ZOOM_STYLES[doc.zoomStyle];
|
|
629
680
|
warnings.push(
|
|
@@ -836,7 +887,8 @@ function lintDoc(docIn) {
|
|
|
836
887
|
enter: CARD_ENTER_KINDS,
|
|
837
888
|
exit: CARD_EXIT_KINDS,
|
|
838
889
|
idle: null,
|
|
839
|
-
words: false
|
|
890
|
+
words: false,
|
|
891
|
+
card: true
|
|
840
892
|
},
|
|
841
893
|
problems
|
|
842
894
|
);
|
|
@@ -930,9 +982,12 @@ function lintDoc(docIn) {
|
|
|
930
982
|
}
|
|
931
983
|
if (footageEnd !== null && footageEnd > 0 && isNum(o.start) && isNum(o.duration)) {
|
|
932
984
|
const over = o.start + o.duration - footageEnd;
|
|
933
|
-
|
|
985
|
+
const frameAnim = isObj(docIn) && isObj(docIn.frame) && isObj(docIn.frame.anim) ? docIn.frame.anim : null;
|
|
986
|
+
const exit = frameAnim ? isObj(frameAnim.exit) ? frameAnim.exit.kind : frameAnim.exit : void 0;
|
|
987
|
+
const cardLeaves = exit !== void 0 && exit !== "none";
|
|
988
|
+
if (over > 0.05 && !cardLeaves) {
|
|
934
989
|
warnings.push(
|
|
935
|
-
o.start >= footageEnd ? `${name} starts at ${o.start.toFixed(2)}s, after the footage ends (${footageEnd.toFixed(2)}s): it plays
|
|
990
|
+
o.start >= footageEnd ? `${name} starts at ${o.start.toFixed(2)}s, after the footage ends (${footageEnd.toFixed(2)}s): it plays over the card's held last frame 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), put a freeze under it, or, for a closing card on the ground, let the card leave (frame.anim.exit: 'fade')` : `${name} ends ${over.toFixed(2)}s after the footage (${footageEnd.toFixed(2)}s): the card holds its last frame under it. Shorten it, put a freeze under it, or, for a closing card on the ground, let the card leave (frame.anim.exit: 'fade')`
|
|
936
991
|
);
|
|
937
992
|
}
|
|
938
993
|
}
|
|
@@ -1604,13 +1659,67 @@ function framingWarnings(docIn, doc, zoom, overlays, warnings) {
|
|
|
1604
1659
|
if (!tf || !isNum(tf.x) || !isNum(tf.y)) return;
|
|
1605
1660
|
const pinned = pins.get(String(o.id));
|
|
1606
1661
|
if (!pinned && o.pin === void 0 && (o.kind === "html" || o.kind === "image" || o.kind === "video")) {
|
|
1607
|
-
const
|
|
1662
|
+
const words = layerWords(o);
|
|
1663
|
+
let layerBox = null;
|
|
1664
|
+
try {
|
|
1665
|
+
const b = pinBox(o, layout);
|
|
1666
|
+
layerBox = {
|
|
1667
|
+
x: tf.x * layout.W - b.w / 2,
|
|
1668
|
+
y: tf.y * layout.H - b.h / 2,
|
|
1669
|
+
w: b.w,
|
|
1670
|
+
h: b.h
|
|
1671
|
+
};
|
|
1672
|
+
} catch {
|
|
1673
|
+
layerBox = null;
|
|
1674
|
+
}
|
|
1675
|
+
const about = [];
|
|
1676
|
+
for (const c of pinCandidates(docIn, {
|
|
1608
1677
|
start: o.start,
|
|
1609
1678
|
duration: o.duration
|
|
1610
|
-
})
|
|
1611
|
-
|
|
1679
|
+
})) {
|
|
1680
|
+
const named = c.selector ? selectorLabelWords(c.selector).filter((x) => words.has(x)) : [];
|
|
1681
|
+
if (named.length) {
|
|
1682
|
+
about.push({
|
|
1683
|
+
step: String(c.step),
|
|
1684
|
+
why: `its words name ${c.step}'s element ("${named.join(" ")}")`
|
|
1685
|
+
});
|
|
1686
|
+
continue;
|
|
1687
|
+
}
|
|
1688
|
+
if (!layerBox) continue;
|
|
1689
|
+
let ref;
|
|
1690
|
+
try {
|
|
1691
|
+
ref = pinReferent(docIn, { step: c.step });
|
|
1692
|
+
} catch {
|
|
1693
|
+
ref = null;
|
|
1694
|
+
}
|
|
1695
|
+
if (!ref || ref.rect.w * ref.rect.h > PIN_SURFACE_AREA) continue;
|
|
1696
|
+
const target = pinRectOnScreen(
|
|
1697
|
+
ref.rect,
|
|
1698
|
+
c.output.start,
|
|
1699
|
+
layout,
|
|
1700
|
+
camera,
|
|
1701
|
+
zoomTrack
|
|
1702
|
+
);
|
|
1703
|
+
const dx = Math.max(
|
|
1704
|
+
0,
|
|
1705
|
+
target.x - (layerBox.x + layerBox.w),
|
|
1706
|
+
layerBox.x - (target.x + target.w)
|
|
1707
|
+
);
|
|
1708
|
+
const dy = Math.max(
|
|
1709
|
+
0,
|
|
1710
|
+
target.y - (layerBox.y + layerBox.h),
|
|
1711
|
+
layerBox.y - (target.y + target.h)
|
|
1712
|
+
);
|
|
1713
|
+
if (Math.hypot(dx, dy) <= PIN_NEAR_FRACTION * layout.H) {
|
|
1714
|
+
about.push({
|
|
1715
|
+
step: String(c.step),
|
|
1716
|
+
why: `it sits beside ${c.step}'s element`
|
|
1717
|
+
});
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1720
|
+
if (about.length) {
|
|
1612
1721
|
warnings.push(
|
|
1613
|
-
`overlays[${i}] is not pinned,
|
|
1722
|
+
`overlays[${i}] is not pinned, but ${about[0].why} \u2014 a callout about it says so, and follows it through the camera: pin: { step: "${about[0].step}" }`
|
|
1614
1723
|
);
|
|
1615
1724
|
}
|
|
1616
1725
|
}
|
|
@@ -14700,4 +14809,4 @@ export {
|
|
|
14700
14809
|
verbHelp,
|
|
14701
14810
|
run
|
|
14702
14811
|
};
|
|
14703
|
-
//# sourceMappingURL=chunk-
|
|
14812
|
+
//# sourceMappingURL=chunk-RZZUR2IF.js.map
|