@scenar/core 0.9.0 → 0.9.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/index.d.ts CHANGED
@@ -11,7 +11,7 @@ export { computeStepTimeline } from "./timeline/compute-step-timeline.js";
11
11
  export { deriveStepFromTime } from "./timeline/derive-step.js";
12
12
  export { getStepDurationMs } from "./timeline/step-duration.js";
13
13
  export type { ScenarioShot } from "./timeline/collect-shots.js";
14
- export { SHOT_NAME_PATTERN, collectScenarioShots } from "./timeline/collect-shots.js";
14
+ export { SHOT_NAME_PATTERN, collectScenarioShots, collectShotNames, } from "./timeline/collect-shots.js";
15
15
  export { CLICK_DELAY_MS, TYPE_CHAR_DELAY_MS, HOVER_HOLD_MS, DRAG_SETTLE_MS, CAMERA_TRANSITION_MS, VIEWPORT_SETTLE_MS, } from "./timing/constants.js";
16
16
  export { findScrollParent, scrollTargetIntoView, scrollTargetIntoViewInstant, } from "./dom/scroll.js";
17
17
  export { CURSOR_TARGET_ATTRIBUTE, SCROLL_TARGET_ATTRIBUTE, HOVER_STATE_ATTRIBUTE, DRAG_STATE_ATTRIBUTE, cursorTargetSelector, scrollTargetSelector, } from "./targeting/data-attributes.js";
package/index.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,YAAY,EACV,UAAU,EACV,UAAU,EACV,0BAA0B,GAC3B,MAAM,2BAA2B,CAAC;AAGnC,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAG9E,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AACrF,OAAO,EACL,2BAA2B,EAC3B,uBAAuB,EACvB,UAAU,EACV,4BAA4B,GAC7B,MAAM,yBAAyB,CAAC;AAGjC,YAAY,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAGrE,YAAY,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,YAAY,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAGtF,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,2BAA2B,GAC5B,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,gCAAgC,CAAC;AAGxC,OAAO,EACL,mBAAmB,EACnB,6BAA6B,EAC7B,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,gBAAgB,EAChB,kBAAkB,EAClB,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACvE,YAAY,EACV,yBAAyB,EACzB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,YAAY,EACV,UAAU,EACV,UAAU,EACV,0BAA0B,GAC3B,MAAM,2BAA2B,CAAC;AAGnC,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAG9E,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AACrF,OAAO,EACL,2BAA2B,EAC3B,uBAAuB,EACvB,UAAU,EACV,4BAA4B,GAC7B,MAAM,yBAAyB,CAAC;AAGjC,YAAY,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAGrE,YAAY,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,YAAY,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,6BAA6B,CAAC;AAGrC,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,2BAA2B,GAC5B,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,gCAAgC,CAAC;AAGxC,OAAO,EACL,mBAAmB,EACnB,6BAA6B,EAC7B,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,gBAAgB,EAChB,kBAAkB,EAClB,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACvE,YAAY,EACV,yBAAyB,EACzB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,4BAA4B,CAAC"}
package/index.js CHANGED
@@ -5,7 +5,7 @@ export { computeCursorPosition } from "./cursor/compute-position.js";
5
5
  export { computeStepTimeline } from "./timeline/compute-step-timeline.js";
6
6
  export { deriveStepFromTime } from "./timeline/derive-step.js";
7
7
  export { getStepDurationMs } from "./timeline/step-duration.js";
8
- export { SHOT_NAME_PATTERN, collectScenarioShots } from "./timeline/collect-shots.js";
8
+ export { SHOT_NAME_PATTERN, collectScenarioShots, collectShotNames, } from "./timeline/collect-shots.js";
9
9
  // Timing constants
10
10
  export { CLICK_DELAY_MS, TYPE_CHAR_DELAY_MS, HOVER_HOLD_MS, DRAG_SETTLE_MS, CAMERA_TRANSITION_MS, VIEWPORT_SETTLE_MS, } from "./timing/constants.js";
11
11
  // DOM scroll utilities
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAC5B,sEAAsE;AAgBtE,OAAO,EACL,2BAA2B,EAC3B,uBAAuB,EACvB,UAAU,EACV,4BAA4B,GAC7B,MAAM,yBAAyB,CAAC;AAIjC,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAIrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAEhE,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAEtF,mBAAmB;AACnB,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAE/B,uBAAuB;AACvB,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,2BAA2B,GAC5B,MAAM,iBAAiB,CAAC;AAEzB,oCAAoC;AACpC,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,gCAAgC,CAAC;AAExC,0EAA0E;AAC1E,OAAO,EACL,mBAAmB,EACnB,6BAA6B,EAC7B,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAQ7B,uEAAuE;AACvE,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAC5B,sEAAsE;AAgBtE,OAAO,EACL,2BAA2B,EAC3B,uBAAuB,EACvB,UAAU,EACV,4BAA4B,GAC7B,MAAM,yBAAyB,CAAC;AAIjC,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAIrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAEhE,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,6BAA6B,CAAC;AAErC,mBAAmB;AACnB,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAE/B,uBAAuB;AACvB,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,2BAA2B,GAC5B,MAAM,iBAAiB,CAAC;AAEzB,oCAAoC;AACpC,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,gCAAgC,CAAC;AAExC,0EAA0E;AAC1E,OAAO,EACL,mBAAmB,EACnB,6BAA6B,EAC7B,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAQ7B,uEAAuE;AACvE,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scenar/core",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
4
4
  "description": "Pure TypeScript types, timing, and utilities for the Scenar scenario engine.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
package/src/index.ts CHANGED
@@ -32,7 +32,11 @@ export { computeStepTimeline } from "./timeline/compute-step-timeline.js";
32
32
  export { deriveStepFromTime } from "./timeline/derive-step.js";
33
33
  export { getStepDurationMs } from "./timeline/step-duration.js";
34
34
  export type { ScenarioShot } from "./timeline/collect-shots.js";
35
- export { SHOT_NAME_PATTERN, collectScenarioShots } from "./timeline/collect-shots.js";
35
+ export {
36
+ SHOT_NAME_PATTERN,
37
+ collectScenarioShots,
38
+ collectShotNames,
39
+ } from "./timeline/collect-shots.js";
36
40
 
37
41
  // Timing constants
38
42
  export {
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, it } from "vitest";
2
2
  import { computeStepTimeline } from "./compute-step-timeline.js";
3
- import { SHOT_NAME_PATTERN, collectScenarioShots } from "./collect-shots.js";
3
+ import { SHOT_NAME_PATTERN, collectScenarioShots, collectShotNames } from "./collect-shots.js";
4
4
 
5
5
  describe("collectScenarioShots", () => {
6
6
  it("resolves each shot to the settled end of its step", () => {
@@ -76,3 +76,41 @@ describe("collectScenarioShots", () => {
76
76
  ).toThrowError(/steps 0 and 2 both declare shot "opening"/);
77
77
  });
78
78
  });
79
+
80
+ describe("collectShotNames", () => {
81
+ it("returns the declared names in step order, without needing a timeline", () => {
82
+ const steps = [
83
+ { delayMs: 0, shot: "opening" },
84
+ { delayMs: 1000 },
85
+ { delayMs: 2000, shot: "detail-open" },
86
+ ];
87
+ expect(collectShotNames(steps)).toEqual(["opening", "detail-open"]);
88
+ });
89
+
90
+ it("returns an empty list when no step declares a shot", () => {
91
+ expect(collectShotNames([{ delayMs: 0 }, { delayMs: 1000 }])).toEqual([]);
92
+ });
93
+
94
+ it("throws the same validation errors as collectScenarioShots", () => {
95
+ expect(() => collectShotNames([{ delayMs: 0, shot: "Not_Kebab" }])).toThrowError(
96
+ /not kebab-case/,
97
+ );
98
+ expect(() =>
99
+ collectShotNames([
100
+ { delayMs: 0, shot: "opening" },
101
+ { delayMs: 100, shot: "opening" },
102
+ ]),
103
+ ).toThrowError(/steps 0 and 1 both declare shot "opening"/);
104
+ });
105
+
106
+ it("agrees with collectScenarioShots on every valid scenario (shared walk)", () => {
107
+ const steps = [
108
+ { delayMs: 0, shot: "opening" },
109
+ { delayMs: 500 },
110
+ { delayMs: 700, shot: "midway" },
111
+ { delayMs: 300, shot: "finale" },
112
+ ];
113
+ const resolved = collectScenarioShots(steps, computeStepTimeline(steps, null));
114
+ expect(collectShotNames(steps)).toEqual(resolved.map((shot) => shot.name));
115
+ });
116
+ });
@@ -33,24 +33,21 @@ export interface ScenarioShot {
33
33
  export const SHOT_NAME_PATTERN = /^[a-z0-9]+(-[a-z0-9]+)*$/;
34
34
 
35
35
  /**
36
- * Resolve every `shot`-bearing step to its named capture point, in
37
- * timeline order.
36
+ * Walk the steps and validate every declared `shot`, returning name +
37
+ * declaring index in step order — the single validation pass behind both
38
+ * {@link collectShotNames} and {@link collectScenarioShots}, so a name
39
+ * that passes one can never fail the other.
38
40
  *
39
41
  * Throws on the two authoring mistakes that must never reach a deployed
40
42
  * bundle: a name that cannot be a clean filename/URL segment, and a
41
43
  * duplicate name (shots are addressed by name, never by index — a
42
44
  * collision would silently overwrite a still). Error messages name the
43
45
  * offending step index so the fix is local.
44
- *
45
- * The `timeline` must be computed from the same steps (and the same
46
- * narration manifest) the capture will walk — shot times are meaningless
47
- * against any other timeline.
48
46
  */
49
- export function collectScenarioShots(
47
+ function collectDeclaredShots(
50
48
  steps: readonly StepWithShot[],
51
- timeline: StepTimeline,
52
- ): ScenarioShot[] {
53
- const shots: ScenarioShot[] = [];
49
+ ): Array<{ name: string; stepIndex: number }> {
50
+ const declared: Array<{ name: string; stepIndex: number }> = [];
54
51
  const seen = new Map<string, number>();
55
52
 
56
53
  for (let i = 0; i < steps.length; i++) {
@@ -71,14 +68,47 @@ export function collectScenarioShots(
71
68
  );
72
69
  }
73
70
  seen.set(name, i);
71
+ declared.push({ name, stepIndex: i });
72
+ }
73
+
74
+ return declared;
75
+ }
76
+
77
+ /**
78
+ * The validated shot names declared by a scenario, in step order —
79
+ * everything about a scenario's shots that is knowable without a
80
+ * timeline. `scenar pack` records this list in the bundle's
81
+ * scenario.json so tooling can learn a bundle's shots (or that it has
82
+ * none) without booting a browser.
83
+ *
84
+ * Throws on the same authoring mistakes as {@link collectScenarioShots};
85
+ * see {@link collectDeclaredShots}.
86
+ */
87
+ export function collectShotNames(steps: readonly StepWithShot[]): string[] {
88
+ return collectDeclaredShots(steps).map((shot) => shot.name);
89
+ }
74
90
 
75
- const nextStartMs = timeline.stepStartTimesMs[i + 1];
76
- shots.push({
91
+ /**
92
+ * Resolve every `shot`-bearing step to its named capture point, in
93
+ * timeline order.
94
+ *
95
+ * Validation (and the errors it throws) is shared with
96
+ * {@link collectShotNames}; see {@link collectDeclaredShots}.
97
+ *
98
+ * The `timeline` must be computed from the same steps (and the same
99
+ * narration manifest) the capture will walk — shot times are meaningless
100
+ * against any other timeline.
101
+ */
102
+ export function collectScenarioShots(
103
+ steps: readonly StepWithShot[],
104
+ timeline: StepTimeline,
105
+ ): ScenarioShot[] {
106
+ return collectDeclaredShots(steps).map(({ name, stepIndex }) => {
107
+ const nextStartMs = timeline.stepStartTimesMs[stepIndex + 1];
108
+ return {
77
109
  name,
78
110
  timeMs: (nextStartMs ?? timeline.totalDurationMs) - 1,
79
- stepIndex: i,
80
- });
81
- }
82
-
83
- return shots;
111
+ stepIndex,
112
+ };
113
+ });
84
114
  }
@@ -28,15 +28,23 @@ export interface ScenarioShot {
28
28
  * deploy path contract admits.
29
29
  */
30
30
  export declare const SHOT_NAME_PATTERN: RegExp;
31
+ /**
32
+ * The validated shot names declared by a scenario, in step order —
33
+ * everything about a scenario's shots that is knowable without a
34
+ * timeline. `scenar pack` records this list in the bundle's
35
+ * scenario.json so tooling can learn a bundle's shots (or that it has
36
+ * none) without booting a browser.
37
+ *
38
+ * Throws on the same authoring mistakes as {@link collectScenarioShots};
39
+ * see {@link collectDeclaredShots}.
40
+ */
41
+ export declare function collectShotNames(steps: readonly StepWithShot[]): string[];
31
42
  /**
32
43
  * Resolve every `shot`-bearing step to its named capture point, in
33
44
  * timeline order.
34
45
  *
35
- * Throws on the two authoring mistakes that must never reach a deployed
36
- * bundle: a name that cannot be a clean filename/URL segment, and a
37
- * duplicate name (shots are addressed by name, never by index — a
38
- * collision would silently overwrite a still). Error messages name the
39
- * offending step index so the fix is local.
46
+ * Validation (and the errors it throws) is shared with
47
+ * {@link collectShotNames}; see {@link collectDeclaredShots}.
40
48
  *
41
49
  * The `timeline` must be computed from the same steps (and the same
42
50
  * narration manifest) the capture will walk — shot times are meaningless
@@ -1 +1 @@
1
- {"version":3,"file":"collect-shots.d.ts","sourceRoot":"","sources":["../../src/timeline/collect-shots.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE/D;;;GAGG;AACH,UAAU,YAAY;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,4EAA4E;AAC5E,MAAM,WAAW,YAAY;IAC3B,sEAAsE;IACtE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,gDAAgD;IAChD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,QAA6B,CAAC;AAE5D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,SAAS,YAAY,EAAE,EAC9B,QAAQ,EAAE,YAAY,GACrB,YAAY,EAAE,CAgChB"}
1
+ {"version":3,"file":"collect-shots.d.ts","sourceRoot":"","sources":["../../src/timeline/collect-shots.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE/D;;;GAGG;AACH,UAAU,YAAY;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,4EAA4E;AAC5E,MAAM,WAAW,YAAY;IAC3B,sEAAsE;IACtE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,gDAAgD;IAChD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,QAA6B,CAAC;AA4C5D;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,EAAE,CAEzE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,SAAS,YAAY,EAAE,EAC9B,QAAQ,EAAE,YAAY,GACrB,YAAY,EAAE,CAShB"}
@@ -6,21 +6,19 @@
6
6
  */
7
7
  export const SHOT_NAME_PATTERN = /^[a-z0-9]+(-[a-z0-9]+)*$/;
8
8
  /**
9
- * Resolve every `shot`-bearing step to its named capture point, in
10
- * timeline order.
9
+ * Walk the steps and validate every declared `shot`, returning name +
10
+ * declaring index in step order — the single validation pass behind both
11
+ * {@link collectShotNames} and {@link collectScenarioShots}, so a name
12
+ * that passes one can never fail the other.
11
13
  *
12
14
  * Throws on the two authoring mistakes that must never reach a deployed
13
15
  * bundle: a name that cannot be a clean filename/URL segment, and a
14
16
  * duplicate name (shots are addressed by name, never by index — a
15
17
  * collision would silently overwrite a still). Error messages name the
16
18
  * offending step index so the fix is local.
17
- *
18
- * The `timeline` must be computed from the same steps (and the same
19
- * narration manifest) the capture will walk — shot times are meaningless
20
- * against any other timeline.
21
19
  */
22
- export function collectScenarioShots(steps, timeline) {
23
- const shots = [];
20
+ function collectDeclaredShots(steps) {
21
+ const declared = [];
24
22
  const seen = new Map();
25
23
  for (let i = 0; i < steps.length; i++) {
26
24
  const name = steps[i]?.shot;
@@ -36,13 +34,42 @@ export function collectScenarioShots(steps, timeline) {
36
34
  `shot names must be unique within a scenario`);
37
35
  }
38
36
  seen.set(name, i);
39
- const nextStartMs = timeline.stepStartTimesMs[i + 1];
40
- shots.push({
37
+ declared.push({ name, stepIndex: i });
38
+ }
39
+ return declared;
40
+ }
41
+ /**
42
+ * The validated shot names declared by a scenario, in step order —
43
+ * everything about a scenario's shots that is knowable without a
44
+ * timeline. `scenar pack` records this list in the bundle's
45
+ * scenario.json so tooling can learn a bundle's shots (or that it has
46
+ * none) without booting a browser.
47
+ *
48
+ * Throws on the same authoring mistakes as {@link collectScenarioShots};
49
+ * see {@link collectDeclaredShots}.
50
+ */
51
+ export function collectShotNames(steps) {
52
+ return collectDeclaredShots(steps).map((shot) => shot.name);
53
+ }
54
+ /**
55
+ * Resolve every `shot`-bearing step to its named capture point, in
56
+ * timeline order.
57
+ *
58
+ * Validation (and the errors it throws) is shared with
59
+ * {@link collectShotNames}; see {@link collectDeclaredShots}.
60
+ *
61
+ * The `timeline` must be computed from the same steps (and the same
62
+ * narration manifest) the capture will walk — shot times are meaningless
63
+ * against any other timeline.
64
+ */
65
+ export function collectScenarioShots(steps, timeline) {
66
+ return collectDeclaredShots(steps).map(({ name, stepIndex }) => {
67
+ const nextStartMs = timeline.stepStartTimesMs[stepIndex + 1];
68
+ return {
41
69
  name,
42
70
  timeMs: (nextStartMs ?? timeline.totalDurationMs) - 1,
43
- stepIndex: i,
44
- });
45
- }
46
- return shots;
71
+ stepIndex,
72
+ };
73
+ });
47
74
  }
48
75
  //# sourceMappingURL=collect-shots.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"collect-shots.js","sourceRoot":"","sources":["../../src/timeline/collect-shots.ts"],"names":[],"mappings":"AA0BA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,0BAA0B,CAAC;AAE5D;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,oBAAoB,CAClC,KAA8B,EAC9B,QAAsB;IAEtB,MAAM,KAAK,GAAmB,EAAE,CAAC;IACjC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;QAC5B,IAAI,IAAI,KAAK,SAAS;YAAE,SAAS;QAEjC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CACb,QAAQ,CAAC,mBAAmB,IAAI,6BAA6B;gBAC3D,aAAa,iBAAiB,4CAA4C,CAC7E,CAAC;QACJ,CAAC;QACD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CACb,SAAS,UAAU,QAAQ,CAAC,uBAAuB,IAAI,KAAK;gBAC1D,6CAA6C,CAChD,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAElB,MAAM,WAAW,GAAG,QAAQ,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACrD,KAAK,CAAC,IAAI,CAAC;YACT,IAAI;YACJ,MAAM,EAAE,CAAC,WAAW,IAAI,QAAQ,CAAC,eAAe,CAAC,GAAG,CAAC;YACrD,SAAS,EAAE,CAAC;SACb,CAAC,CAAC;IACL,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"collect-shots.js","sourceRoot":"","sources":["../../src/timeline/collect-shots.ts"],"names":[],"mappings":"AA0BA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,0BAA0B,CAAC;AAE5D;;;;;;;;;;;GAWG;AACH,SAAS,oBAAoB,CAC3B,KAA8B;IAE9B,MAAM,QAAQ,GAA+C,EAAE,CAAC;IAChE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;QAC5B,IAAI,IAAI,KAAK,SAAS;YAAE,SAAS;QAEjC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CACb,QAAQ,CAAC,mBAAmB,IAAI,6BAA6B;gBAC3D,aAAa,iBAAiB,4CAA4C,CAC7E,CAAC;QACJ,CAAC;QACD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CACb,SAAS,UAAU,QAAQ,CAAC,uBAAuB,IAAI,KAAK;gBAC1D,6CAA6C,CAChD,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAClB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC;IACxC,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAA8B;IAC7D,OAAO,oBAAoB,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC9D,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,oBAAoB,CAClC,KAA8B,EAC9B,QAAsB;IAEtB,OAAO,oBAAoB,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE;QAC7D,MAAM,WAAW,GAAG,QAAQ,CAAC,gBAAgB,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;QAC7D,OAAO;YACL,IAAI;YACJ,MAAM,EAAE,CAAC,WAAW,IAAI,QAAQ,CAAC,eAAe,CAAC,GAAG,CAAC;YACrD,SAAS;SACV,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}