@vosjs/cli 0.65.4 → 0.67.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.
@@ -9,7 +9,7 @@ import {
9
9
  reencodeStill,
10
10
  renderStill,
11
11
  videoFormat
12
- } from "./chunk-TYGDQEEI.js";
12
+ } from "./chunk-MDRYSHOF.js";
13
13
  import {
14
14
  PREV_DOC_NAME,
15
15
  RECORDING_NAME,
@@ -33,7 +33,7 @@ import {
33
33
  uploadDocRefs,
34
34
  uploadManifest,
35
35
  writeJson
36
- } from "./chunk-63KINQOJ.js";
36
+ } from "./chunk-OFTRK3Y3.js";
37
37
  import {
38
38
  CREDENTIALS_PATH,
39
39
  MEDIA_HEAD_BYTES,
@@ -56,6 +56,7 @@ import {
56
56
  parseVosId,
57
57
  platformOrigin,
58
58
  programAssets,
59
+ promptHint,
59
60
  readSyncState,
60
61
  requireCredential,
61
62
  resolveCredential,
@@ -65,7 +66,7 @@ import {
65
66
  strFlag,
66
67
  writeCredential,
67
68
  writeSyncState
68
- } from "./chunk-UQLC4BEZ.js";
69
+ } from "./chunk-C5VKACGQ.js";
69
70
  import {
70
71
  deadLine,
71
72
  deadWarns
@@ -214,7 +215,12 @@ import {
214
215
  pinCandidates,
215
216
  pinRectOnScreen,
216
217
  pinReferent,
217
- parseEmphasis,
218
+ marksEmphasis,
219
+ migrateTextClip,
220
+ plainText,
221
+ resolveOverlayStyle,
222
+ snapRunWeight,
223
+ RUN_STYLE_KEYS,
218
224
  ratedSegments,
219
225
  recommendedExportResolution,
220
226
  resolvePins,
@@ -244,7 +250,7 @@ function wordsOf(text) {
244
250
  return text.toLowerCase().split(/[^a-z0-9]+/).filter((x) => x.length >= 3 && !LABEL_STOPWORDS.has(x));
245
251
  }
246
252
  function layerWords(o) {
247
- const src = typeof o.html === "string" ? o.html.replace(/<[^>]*>/g, " ") : typeof o.text === "string" ? o.text : "";
253
+ const src = typeof o.html === "string" ? o.html.replace(/<[^>]*>/g, " ") : typeof o.text === "string" || Array.isArray(o.text) ? plainText(o.text) : "";
248
254
  return new Set(wordsOf(src));
249
255
  }
250
256
  function selectorLabelWords(selector) {
@@ -1063,28 +1069,75 @@ function lintDoc(docIn) {
1063
1069
  }
1064
1070
  checkPin(o, name, docIn, recording, problems, warnings);
1065
1071
  if (o.kind === "text") {
1066
- if (typeof o.text !== "string")
1067
- problems.push(`${name}.text must be a string`);
1072
+ if (Array.isArray(o.text)) {
1073
+ const HINTS = {
1074
+ bold: "weight: 700",
1075
+ fontWeight: "weight",
1076
+ strikethrough: "strike: true",
1077
+ background: "highlight",
1078
+ colour: "color"
1079
+ };
1080
+ o.text.forEach((run2, ri) => {
1081
+ const at2 = `${name}.text[${ri}]`;
1082
+ if (!run2 || typeof run2 !== "object" || Array.isArray(run2)) {
1083
+ problems.push(
1084
+ `${at2} must be a run: { text, weight?, italic?, color?, underline?, strike?, highlight? }`
1085
+ );
1086
+ return;
1087
+ }
1088
+ const r = run2;
1089
+ if (typeof r.text !== "string")
1090
+ problems.push(`${at2}.text must be a string`);
1091
+ else if (!r.text)
1092
+ warnings.push(`${at2} has no text and paints nothing; drop it`);
1093
+ for (const k of Object.keys(r)) {
1094
+ if (k === "text" || RUN_STYLE_KEYS.includes(k))
1095
+ continue;
1096
+ problems.push(
1097
+ `${at2}.${k} is not a run field (${RUN_STYLE_KEYS.join(", ")})${HINTS[k] ? `: write ${HINTS[k]}` : ""}`
1098
+ );
1099
+ }
1100
+ if (r.weight !== void 0 && (!isNum(r.weight) || r.weight < 100 || r.weight > 900))
1101
+ problems.push(`${at2}.weight must be 100..900`);
1102
+ for (const k of ["italic", "underline", "strike"]) {
1103
+ if (r[k] !== void 0 && typeof r[k] !== "boolean")
1104
+ problems.push(`${at2}.${k} must be true or false`);
1105
+ }
1106
+ for (const k of ["color", "highlight"]) {
1107
+ if (r[k] !== void 0 && typeof r[k] !== "string")
1108
+ problems.push(`${at2}.${k} must be a CSS colour`);
1109
+ }
1110
+ if (isNum(r.weight) && r.weight >= 100 && r.weight <= 900) {
1111
+ const layer = o;
1112
+ const own = resolveOverlayStyle({ ...layer, text: "" }).weight;
1113
+ if (r.weight !== own && snapRunWeight(layer, r.weight) === own)
1114
+ warnings.push(
1115
+ `${at2}.weight ${r.weight} paints no differently: the layer's family hosts no weight nearer to it than the layer's own ${own}`
1116
+ );
1117
+ }
1118
+ });
1119
+ } else if (typeof o.text !== "string") {
1120
+ problems.push(
1121
+ `${name}.text must be a string, or a list of runs ([{ text, weight?, italic?, color?, underline?, strike?, highlight? }])`
1122
+ );
1123
+ }
1068
1124
  if (typeof o.preset === "string" && !PRESETS.includes(o.preset)) {
1069
1125
  warnings.push(
1070
1126
  `${name}.preset "${String(o.preset)}" is not a known preset (${PRESETS.join("|")}) \u2014 falls back to "title"`
1071
1127
  );
1072
1128
  }
1073
- if (o.emphasis !== void 0) {
1074
- const em = o.emphasis;
1075
- if (!em || typeof em !== "object" || Array.isArray(em)) {
1076
- problems.push(
1077
- `${name}.emphasis must be { weight?, color? } ({} turns *markers* on)`
1078
- );
1079
- } else {
1080
- if (em.weight !== void 0 && (!isNum(em.weight) || em.weight < 100 || em.weight > 900))
1081
- problems.push(`${name}.emphasis.weight must be 100..900`);
1082
- if (em.color !== void 0 && typeof em.color !== "string")
1083
- problems.push(`${name}.emphasis.color must be a CSS colour`);
1084
- }
1085
- } else if (typeof o.text === "string" && parseEmphasis(o.text) !== null) {
1129
+ if (o.emphasis !== void 0 && typeof o.text === "string") {
1130
+ const runs = migrateTextClip(o).text;
1131
+ warnings.push(
1132
+ `${name}.emphasis is retired (styled words are runs now, with no markers in the text). It is still read, but write it as: "text": ${JSON.stringify(runs)} and drop "emphasis"`
1133
+ );
1134
+ } else if (typeof o.text === "string" && marksEmphasis(o.text)) {
1135
+ const runs = migrateTextClip({
1136
+ ...o,
1137
+ emphasis: {}
1138
+ }).text;
1086
1139
  warnings.push(
1087
- `${name}.text has *marked* words but no emphasis, so the asterisks show as typed; add emphasis: {} to set them bold (\\* keeps one literal)`
1140
+ `${name}.text has words between asterisks, which show as typed. To set them bold write runs: "text": ${JSON.stringify(runs)}`
1088
1141
  );
1089
1142
  }
1090
1143
  if (o.size !== void 0 && (!isNum(o.size) || o.size < 12 || o.size > 200)) {
@@ -4333,8 +4386,9 @@ import {
4333
4386
  computeCardLayout,
4334
4387
  docStillTime as docStillTime2,
4335
4388
  migrateHostedDoc,
4389
+ overlayPlainText,
4336
4390
  overlayRect,
4337
- resolveOverlayStyle
4391
+ resolveOverlayStyle as resolveOverlayStyle2
4338
4392
  } from "@vosjs/studio-core";
4339
4393
  var POSTER_CLASSES = [
4340
4394
  "landscape",
@@ -4453,7 +4507,7 @@ function posterTextBoxes(doc, px, time) {
4453
4507
  if (clip.kind !== "text") continue;
4454
4508
  if (time < clip.start || time > clip.start + clip.duration) continue;
4455
4509
  const rect = overlayRect(clip, estimateWidth, W, H);
4456
- const style = resolveOverlayStyle(clip);
4510
+ const style = resolveOverlayStyle2(clip);
4457
4511
  const r3 = (v) => Math.round(v * 1e3) / 1e3;
4458
4512
  out.push({
4459
4513
  x: r3((rect.cx - rect.w / 2) / W),
@@ -4461,7 +4515,7 @@ function posterTextBoxes(doc, px, time) {
4461
4515
  w: r3(rect.w / W),
4462
4516
  h: r3(rect.h / H),
4463
4517
  role: clip.preset === "title" ? "headline" : "body",
4464
- label: clip.text.split("\n")[0].slice(0, 40),
4518
+ label: overlayPlainText(clip).split("\n")[0].slice(0, 40),
4465
4519
  .../^#[0-9a-f]{6}$/i.test(style.color) ? { color: style.color } : {}
4466
4520
  });
4467
4521
  }
@@ -7308,7 +7362,8 @@ async function pushTake(dir, flags, r) {
7308
7362
  client: clientId(),
7309
7363
  ...folderId ? { folderId } : {},
7310
7364
  ...flags.label ? { label: flags.label } : {},
7311
- ...flags.note ? { note: flags.note } : {}
7365
+ ...flags.note ? { note: flags.note } : {},
7366
+ ...flags.prompt ? { prompt: flags.prompt } : {}
7312
7367
  }
7313
7368
  });
7314
7369
  if (created.status !== 201) {
@@ -7359,6 +7414,16 @@ async function pushTake(dir, flags, r) {
7359
7414
  );
7360
7415
  }
7361
7416
  serverWarnings(pushed.json, (l) => r.log(l));
7417
+ if (flags.prompt) {
7418
+ const set = await api(ctx, `/vos/${state.vosId}`, {
7419
+ method: "PATCH",
7420
+ body: { prompt: flags.prompt }
7421
+ });
7422
+ if (set.status !== 200)
7423
+ r.warn(
7424
+ `could not set the prompt (${set.status}): ${String(set.json.error ?? "")}${detailLine(set.json)}`
7425
+ );
7426
+ }
7362
7427
  const version = pushed.json.version;
7363
7428
  writeSyncState(dir, {
7364
7429
  vosId: state.vosId,
@@ -8261,6 +8326,8 @@ ${landedLines(landed2)}` : "")
8261
8326
  currentVersionId: created.currentVersionId,
8262
8327
  watchUrl,
8263
8328
  studioUrl,
8329
+ prompt: prompt ?? null,
8330
+ ...prompt ? {} : { promptHint: promptHint(source, created.id) },
8264
8331
  ...landed ? {
8265
8332
  still: landed.still,
8266
8333
  thumbnailUrl: landed.thumbnailUrl,
@@ -8273,7 +8340,9 @@ ${landedLines(landed2)}` : "")
8273
8340
  ` + (landed ? `${landedLines(landed)}
8274
8341
  ` : "") + ` shelf: ${folderRef ? `in ${folderRef}` : `unfiled, at the root of your shelf (file it: vos folder move ${created.id} --to <slug>)`}
8275
8342
  cover: ${typeof programDoc?.still === "number" ? `${String(programDoc.still)}s` : "the platform picks an early frame; choose one with --still <seconds>"}
8276
- Iterate with: vos push ${source} --vos ${created.id}`
8343
+ ` + (prompt ? ` prompt: shown on the watch page
8344
+ ` : ` prompt: none shown; show the one that made it: ${promptHint(source, created.id)}
8345
+ `) + `Iterate with: vos push ${source} --vos ${created.id}`
8277
8346
  );
8278
8347
  return EXIT_OK;
8279
8348
  }
@@ -14729,7 +14798,7 @@ async function cmdPush3(argv) {
14729
14798
  const dir = positionals[0];
14730
14799
  if (!dir)
14731
14800
  throw new UsageError(
14732
- "vos push <take> [--vos|--title|--label|--note|--folder|--override|--yes|--key|--api]"
14801
+ "vos push <take> [--vos|--title|--label|--note|--prompt|--folder|--override|--yes|--key|--api]"
14733
14802
  );
14734
14803
  const refusal = takePushRefusal({
14735
14804
  vos: strFlag(flags, "vos"),
@@ -14753,7 +14822,8 @@ async function cmdPush3(argv) {
14753
14822
  label: strFlag(flags, "label"),
14754
14823
  note: strFlag(flags, "note"),
14755
14824
  folder: strFlag(flags, "folder"),
14756
- overrides
14825
+ overrides,
14826
+ prompt: strFlag(flags, "prompt")
14757
14827
  },
14758
14828
  r
14759
14829
  );
@@ -14770,9 +14840,12 @@ async function cmdPush3(argv) {
14770
14840
  }) : null;
14771
14841
  const filed = result.versionNumber === 1 ? `
14772
14842
  shelf: ${strFlag(flags, "folder") ? `in ${strFlag(flags, "folder")}` : `unfiled, at the root of your shelf (file it: vos folder move ${result.vosId} --to <slug>)`}` : "";
14843
+ const prompt = strFlag(flags, "prompt");
14844
+ const hint = result.versionNumber === 1 && !prompt ? promptHint(dir, result.vosId) : null;
14773
14845
  r.done(
14774
14846
  {
14775
14847
  ...result,
14848
+ ...hint ? { promptHint: hint } : {},
14776
14849
  ...landed ? {
14777
14850
  still: landed.still,
14778
14851
  thumbnailUrl: landed.thumbnailUrl,
@@ -14781,7 +14854,8 @@ async function cmdPush3(argv) {
14781
14854
  },
14782
14855
  `pushed v${result.versionNumber} \u2192 vos ${result.vosId}
14783
14856
  review: ${pushedTo}/vos/${result.vosId}
14784
- studio: ${pushedTo}/studio?vos=${result.vosId}` + filed + (landed ? `
14857
+ studio: ${pushedTo}/studio?vos=${result.vosId}` + filed + (hint ? `
14858
+ prompt: none shown; show the one that made it: ${hint}` : "") + (landed ? `
14785
14859
  ${landedLines(landed)}` : "")
14786
14860
  );
14787
14861
  return EXIT_OK;
@@ -15093,4 +15167,4 @@ export {
15093
15167
  verbHelp,
15094
15168
  run
15095
15169
  };
15096
- //# sourceMappingURL=chunk-IDPTF5PP.js.map
15170
+ //# sourceMappingURL=chunk-XCWC7SUS.js.map