@onmark/cli 0.3.0 → 0.4.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.
Files changed (34) hide show
  1. package/onmark-release.json +83 -53
  2. package/package.json +4 -4
  3. package/packages/authoring/dist/src/frame-motion.d.ts +10 -2
  4. package/packages/authoring/dist/src/frame-motion.js +29 -6
  5. package/packages/authoring/dist/src/index.d.ts +2 -2
  6. package/packages/authoring/dist/src/motion.d.ts +16 -4
  7. package/packages/authoring/dist/src/presentation.js +34 -1
  8. package/packages/authoring/dist/src/types.d.ts +1 -1
  9. package/packages/bundler/dist/src/authored_html.d.ts +17 -7
  10. package/packages/bundler/dist/src/authored_html.js +79 -21
  11. package/packages/bundler/dist/src/bundle_projection.d.ts +9 -0
  12. package/packages/bundler/dist/src/bundle_projection.js +66 -0
  13. package/packages/bundler/dist/src/command.js +28 -8
  14. package/packages/bundler/dist/src/generated/bundle-projection-validator.d.ts +7 -0
  15. package/packages/bundler/dist/src/generated/bundle-projection-validator.js +432 -0
  16. package/packages/bundler/dist/src/generated/bundle-projection.d.ts +25 -0
  17. package/packages/bundler/dist/src/generated/bundle-projection.js +2 -0
  18. package/packages/bundler/dist/src/index.d.ts +1 -1
  19. package/packages/bundler/dist/src/presentation.d.ts +13 -6
  20. package/packages/bundler/dist/src/presentation.js +58 -28
  21. package/packages/motion-gsap/dist/src/index.d.ts +10 -2
  22. package/packages/motion-gsap/dist/src/index.js +27 -5
  23. package/packages/runtime/dist/src/generated/browser-request.d.ts +15 -2
  24. package/packages/runtime/dist/src/generated/browser-response.d.ts +1 -1
  25. package/packages/runtime/dist/src/generated/runtime-contract.d.ts +2 -0
  26. package/packages/runtime/dist/src/generated/runtime-contract.js +2 -0
  27. package/packages/runtime/dist/src/generated/validators.d.ts +2 -2
  28. package/packages/runtime/dist/src/generated/validators.js +331 -128
  29. package/packages/runtime/dist/src/index.d.ts +2 -2
  30. package/packages/runtime/dist/src/index.js +1 -1
  31. package/packages/runtime/dist/src/presentation.d.ts +10 -0
  32. package/packages/runtime/dist/src/presentation.js +18 -3
  33. package/packages/runtime/dist/src/session.js +61 -12
  34. package/packages/runtime/dist/src/types.d.ts +1 -1
@@ -5,9 +5,9 @@ export type { BrowserPlan, BrowserVideo } from "./generated/browser-request.js";
5
5
  export { runtimeFrameAt, type RuntimeFrame } from "./clock.js";
6
6
  export { videoFrameSelection, type RuntimeVideo, type VideoFrameSelection, } from "./media.js";
7
7
  export { DecodedVideo, materializedVideoSource, type BrowserVideoElement, type DecodedVideoOptions, } from "./video.js";
8
- export { MAX_PRESENTATION_EFFECTS, PresentationRuntimeAdapter, type ContainerPresentation, type FrameEffect, type OverlayPresentation, type PresentationBindings, type PresentationExtensions, type RuntimeOverlay, type RuntimeNode, type RuntimeScene, type RuntimeShot, type VideoPresentation, } from "./presentation.js";
8
+ export { MAX_PRESENTATION_EFFECTS, PresentationRuntimeAdapter, type ContainerPresentation, type FrameEffect, type OverlayPresentation, type PresentationBindings, type PresentationExtensions, type RuntimeOverlay, type RuntimeNode, type RuntimeScene, type RuntimeShot, type RuntimeTransition, type TransitionPresentation, type VideoPresentation, } from "./presentation.js";
9
9
  export { MAX_PRESENTATION_RESOURCES, PRESENTATION_RESOURCE_KINDS, type PresentationResource, type PresentationResourceKind, } from "./resource.js";
10
10
  export { BUNDLE_ASSET_DIRECTORY, PRESENTATION_TEMPORAL_CAPABILITIES, type PresentationTemporalCapability, } from "./generated/bundle-layout.js";
11
- export { MAX_BROWSER_OVERLAYS, MAX_BROWSER_OVERLAY_TEXT_CHARACTERS, MAX_BROWSER_VIDEOS, MAX_FAILURE_MESSAGE_CHARACTERS, MAX_PENDING_RESOURCE_CHARACTERS, MAX_PENDING_RESOURCES, } from "./generated/runtime-contract.js";
11
+ export { BROWSER_PROTOCOL_VERSION, MAX_BROWSER_OVERLAYS, MAX_BROWSER_OVERLAY_TEXT_CHARACTERS, MAX_BROWSER_VIDEOS, MAX_BROWSER_TRANSITIONS, MAX_FAILURE_MESSAGE_CHARACTERS, MAX_PENDING_RESOURCE_CHARACTERS, MAX_PENDING_RESOURCES, } from "./generated/runtime-contract.js";
12
12
  export { RUNTIME_HOST_NAME, installRuntimeHost, type RuntimeHost, } from "./host.js";
13
13
  export { RuntimeAdapterError, RuntimeSession, type RuntimeAdapter, type RuntimeAdapterFailureKind, type RuntimePlan, } from "./session.js";
@@ -7,6 +7,6 @@ export { DecodedVideo, materializedVideoSource, } from "./video.js";
7
7
  export { MAX_PRESENTATION_EFFECTS, PresentationRuntimeAdapter, } from "./presentation.js";
8
8
  export { MAX_PRESENTATION_RESOURCES, PRESENTATION_RESOURCE_KINDS, } from "./resource.js";
9
9
  export { BUNDLE_ASSET_DIRECTORY, PRESENTATION_TEMPORAL_CAPABILITIES, } from "./generated/bundle-layout.js";
10
- export { MAX_BROWSER_OVERLAYS, MAX_BROWSER_OVERLAY_TEXT_CHARACTERS, MAX_BROWSER_VIDEOS, MAX_FAILURE_MESSAGE_CHARACTERS, MAX_PENDING_RESOURCE_CHARACTERS, MAX_PENDING_RESOURCES, } from "./generated/runtime-contract.js";
10
+ export { BROWSER_PROTOCOL_VERSION, MAX_BROWSER_OVERLAYS, MAX_BROWSER_OVERLAY_TEXT_CHARACTERS, MAX_BROWSER_VIDEOS, MAX_BROWSER_TRANSITIONS, MAX_FAILURE_MESSAGE_CHARACTERS, MAX_PENDING_RESOURCE_CHARACTERS, MAX_PENDING_RESOURCES, } from "./generated/runtime-contract.js";
11
11
  export { RUNTIME_HOST_NAME, installRuntimeHost, } from "./host.js";
12
12
  export { RuntimeAdapterError, RuntimeSession, } from "./session.js";
@@ -11,6 +11,8 @@ export type RuntimeOverlay = RuntimePlan["overlays"][number];
11
11
  export type RuntimeScene = RuntimePlan["scenes"][number];
12
12
  /** Immutable shot container projected from Timeline IR. */
13
13
  export type RuntimeShot = RuntimePlan["shots"][number];
14
+ /** Immutable transition relationship projected from Timeline IR. */
15
+ export type RuntimeTransition = RuntimePlan["transitions"][number];
14
16
  /** Immutable film identity projected from Timeline IR. */
15
17
  export type RuntimeNode = RuntimePlan["film"];
16
18
  /** Presentation-owned effects for one semantic container. */
@@ -32,6 +34,13 @@ export interface OverlayPresentation {
32
34
  setVisible(visible: boolean): void;
33
35
  dispose(): void;
34
36
  }
37
+ /** Presentation-owned binding between two adjacent shot elements. */
38
+ export interface TransitionPresentation {
39
+ readonly element: HTMLElement;
40
+ readonly incomingElement: HTMLElement;
41
+ readonly outgoingElement: HTMLElement;
42
+ dispose(): void;
43
+ }
35
44
  /** One paused browser effect driven exclusively by the authored frame. */
36
45
  export interface FrameEffect {
37
46
  /** Applies the exact frame before the runtime reports it as staged. */
@@ -50,6 +59,7 @@ export interface PresentationBindings {
50
59
  bindFilm(plan: RuntimePlan): ContainerPresentation;
51
60
  bindScene(scene: RuntimeScene): ContainerPresentation;
52
61
  bindShot(shot: RuntimeShot): ContainerPresentation;
62
+ bindTransition(transition: RuntimeTransition): TransitionPresentation;
53
63
  bindVideo(placement: RuntimeVideo): VideoPresentation;
54
64
  bindOverlay(placement: RuntimeOverlay): OverlayPresentation;
55
65
  bindExtensions(plan: RuntimePlan): Promise<PresentationExtensions>;
@@ -35,8 +35,10 @@ export class PresentationRuntimeAdapter {
35
35
  let boundStructure;
36
36
  const videos = [];
37
37
  const overlays = [];
38
+ const transitions = [];
38
39
  try {
39
40
  boundStructure = this.#bindStructure(plan, structure);
41
+ this.#bindTransitions(plan, transitions);
40
42
  this.#bindVideos(plan, videos);
41
43
  this.#bindOverlays(plan, overlays);
42
44
  const extensions = await this.#bindings.bindExtensions(plan);
@@ -51,7 +53,7 @@ export class PresentationRuntimeAdapter {
51
53
  await loadVideos(videos);
52
54
  }
53
55
  catch (error) {
54
- const cleanupFailure = await releasePresentation(effects, resources, structure, videos, overlays);
56
+ const cleanupFailure = await releasePresentation(effects, resources, structure, transitions, videos, overlays);
55
57
  // A binding attempt may mutate author-owned state that generic cleanup
56
58
  // cannot prove reusable. A fresh page owns the only valid retry.
57
59
  this.#state = { kind: "disposed" };
@@ -63,6 +65,7 @@ export class PresentationRuntimeAdapter {
63
65
  frameRate: plan.frameRate,
64
66
  resources,
65
67
  structure: boundStructure,
68
+ transitions,
66
69
  videos,
67
70
  overlays,
68
71
  };
@@ -122,7 +125,7 @@ export class PresentationRuntimeAdapter {
122
125
  : undefined;
123
126
  this.#state = { kind: "disposed" };
124
127
  this.#staged = undefined;
125
- const failure = await releasePresentation(loaded?.effects ?? [], loaded?.resources ?? [], loaded?.structure, loaded?.videos ?? [], loaded?.overlays ?? []);
128
+ const failure = await releasePresentation(loaded?.effects ?? [], loaded?.resources ?? [], loaded?.structure, loaded?.transitions ?? [], loaded?.videos ?? [], loaded?.overlays ?? []);
126
129
  if (failure !== undefined) {
127
130
  throw RuntimeAdapterError.fromUnknown(failure, "presentation cleanup failed");
128
131
  }
@@ -160,6 +163,11 @@ export class PresentationRuntimeAdapter {
160
163
  presentation.setVisible(false);
161
164
  }
162
165
  }
166
+ #bindTransitions(plan, transitions) {
167
+ for (const placement of plan.transitions) {
168
+ transitions.push(this.#bindings.bindTransition(placement));
169
+ }
170
+ }
163
171
  #bindOverlays(plan, overlays) {
164
172
  for (const placement of plan.overlays) {
165
173
  const presentation = this.#bindings.bindOverlay(placement);
@@ -293,7 +301,7 @@ function presentationLoadFailure(error, cleanupFailure) {
293
301
  }
294
302
  return RuntimeAdapterError.fromUnknown(error, "presentation failed to load");
295
303
  }
296
- async function releasePresentation(effects, resources, structure, videos, overlays) {
304
+ async function releasePresentation(effects, resources, structure, transitions, videos, overlays) {
297
305
  let failure = await releaseFrameEffects(effects);
298
306
  const resourceFailure = await releasePresentationResources(resources);
299
307
  failure ??= resourceFailure;
@@ -305,10 +313,17 @@ async function releasePresentation(effects, resources, structure, videos, overla
305
313
  const releaseFailure = releaseOverlay(overlay);
306
314
  failure ??= releaseFailure;
307
315
  }
316
+ for (const transition of transitions.toReversed()) {
317
+ const releaseFailure = releaseTransition(transition);
318
+ failure ??= releaseFailure;
319
+ }
308
320
  const structureFailure = releaseStructure(structure);
309
321
  failure ??= structureFailure;
310
322
  return failure;
311
323
  }
324
+ function releaseTransition(transition) {
325
+ return releaseAll([() => transition.dispose()]);
326
+ }
312
327
  function releaseStructure(structure) {
313
328
  if (structure === undefined) {
314
329
  return undefined;
@@ -2,7 +2,7 @@
2
2
  // Owns command ordering and state while a narrow adapter owns browser effects;
3
3
  // this split keeps protocol behavior deterministic and directly testable.
4
4
  import { decodeBrowserResponse } from "./generated/codec.js";
5
- import { MAX_FAILURE_MESSAGE_CHARACTERS, MAX_PENDING_RESOURCE_CHARACTERS, MAX_PENDING_RESOURCES, } from "./generated/runtime-contract.js";
5
+ import { BROWSER_PROTOCOL_VERSION, MAX_FAILURE_MESSAGE_CHARACTERS, MAX_PENDING_RESOURCE_CHARACTERS, MAX_PENDING_RESOURCES, } from "./generated/runtime-contract.js";
6
6
  import { runtimeFrameAt } from "./clock.js";
7
7
  import { exactRatioIsCanonical, videoSourceMappingIsValid } from "./media.js";
8
8
  /** Expected failure reported by a browser adapter. */
@@ -157,7 +157,11 @@ export class RuntimeSession {
157
157
  }
158
158
  }
159
159
  function response(requestId, event) {
160
- return decodeBrowserResponse({ version: 3, requestId, event });
160
+ return decodeBrowserResponse({
161
+ version: BROWSER_PROTOCOL_VERSION,
162
+ requestId,
163
+ event,
164
+ });
161
165
  }
162
166
  function invalidRequest(requestId, message) {
163
167
  return response(requestId, {
@@ -217,6 +221,7 @@ function planViolation(plan) {
217
221
  }
218
222
  if (!hasCanonicalNodeOrder(plan.scenes) ||
219
223
  !hasCanonicalNodeOrder(plan.shots) ||
224
+ !hasCanonicalNodeOrder(plan.transitions) ||
220
225
  !hasCanonicalNodeOrder(plan.videos) ||
221
226
  !hasCanonicalNodeOrder(plan.overlays)) {
222
227
  return "plan node collection is not in canonical order";
@@ -238,7 +243,7 @@ function planViolation(plan) {
238
243
  }
239
244
  sceneIntervals.set(scene.node.nodeId, scene.interval);
240
245
  }
241
- const shotIntervals = new Map();
246
+ const shots = new Map();
242
247
  for (const shot of plan.shots) {
243
248
  const nodeViolation = claimNode(shot.node, nodeIds, authoredIds);
244
249
  if (nodeViolation !== undefined) {
@@ -254,21 +259,35 @@ function planViolation(plan) {
254
259
  if (!insideInterval(shot.interval, sceneInterval)) {
255
260
  return "plan shot interval falls outside its scene";
256
261
  }
257
- shotIntervals.set(shot.node.nodeId, shot.interval);
262
+ shots.set(shot.node.nodeId, {
263
+ interval: shot.interval,
264
+ order: shots.size,
265
+ sceneId: shot.sceneId,
266
+ });
267
+ }
268
+ for (const transition of plan.transitions) {
269
+ const nodeViolation = claimNode(transition.node, nodeIds, authoredIds);
270
+ if (nodeViolation !== undefined) {
271
+ return nodeViolation;
272
+ }
273
+ const relationViolation = transitionRelationViolation(transition, shots, plan);
274
+ if (relationViolation !== undefined) {
275
+ return relationViolation;
276
+ }
258
277
  }
259
278
  for (const video of plan.videos) {
260
279
  const nodeViolation = claimNode(video.node, nodeIds, authoredIds);
261
280
  if (nodeViolation !== undefined) {
262
281
  return nodeViolation;
263
282
  }
264
- const shotInterval = shotIntervals.get(video.shotId);
265
- if (shotInterval === undefined) {
283
+ const shot = shots.get(video.shotId);
284
+ if (shot === undefined) {
266
285
  return "plan video names an unknown shot";
267
286
  }
268
287
  if (!insideEvaluation(video.interval, plan.evaluation)) {
269
288
  return "plan video interval falls outside evaluation";
270
289
  }
271
- if (!insideInterval(video.interval, shotInterval)) {
290
+ if (!insideInterval(video.interval, shot.interval)) {
272
291
  return "plan video interval falls outside its shot";
273
292
  }
274
293
  if (!videoSourceMappingIsValid(video, plan.frameRate)) {
@@ -280,7 +299,7 @@ function planViolation(plan) {
280
299
  if (nodeViolation !== undefined) {
281
300
  return nodeViolation;
282
301
  }
283
- const parentViolation = overlayParentViolation(overlay, shotIntervals);
302
+ const parentViolation = overlayParentViolation(overlay, shots);
284
303
  if (parentViolation !== undefined) {
285
304
  return parentViolation;
286
305
  }
@@ -293,6 +312,26 @@ function planViolation(plan) {
293
312
  }
294
313
  return undefined;
295
314
  }
315
+ function transitionRelationViolation(transition, shots, plan) {
316
+ const outgoing = shots.get(transition.outgoingShotId);
317
+ const incoming = shots.get(transition.incomingShotId);
318
+ if (outgoing === undefined ||
319
+ incoming === undefined ||
320
+ incoming.order !== outgoing.order + 1 ||
321
+ outgoing.sceneId !== incoming.sceneId) {
322
+ return "plan transition does not connect adjacent projected shots";
323
+ }
324
+ if (!validPlacement(transition.interval, plan.timeline, plan.evaluation)) {
325
+ return "plan transition interval is invalid for this evaluation";
326
+ }
327
+ if (!insideInterval(transition.interval, outgoing.interval) ||
328
+ !insideInterval(transition.interval, incoming.interval) ||
329
+ transition.interval.start !== incoming.interval.start ||
330
+ transition.interval.end !== outgoing.interval.end) {
331
+ return "plan transition interval does not match its adjacent shot boundary";
332
+ }
333
+ return undefined;
334
+ }
296
335
  function hasDenseNodeIdentity(identities) {
297
336
  for (let expected = 0; expected < identities.size; expected += 1) {
298
337
  if (!identities.has(expected)) {
@@ -311,7 +350,7 @@ function hasCanonicalNodeOrder(entries) {
311
350
  }
312
351
  return true;
313
352
  }
314
- function overlayParentViolation(overlay, shotIntervals) {
353
+ function overlayParentViolation(overlay, shots) {
315
354
  if (overlay.kind === "caption") {
316
355
  return overlay.shotId === undefined || overlay.shotId === null
317
356
  ? undefined
@@ -320,11 +359,11 @@ function overlayParentViolation(overlay, shotIntervals) {
320
359
  if (overlay.shotId === undefined || overlay.shotId === null) {
321
360
  return "plan overlay names an unknown shot";
322
361
  }
323
- const shotInterval = shotIntervals.get(overlay.shotId);
324
- if (shotInterval === undefined) {
362
+ const shot = shots.get(overlay.shotId);
363
+ if (shot === undefined) {
325
364
  return "plan overlay names an unknown shot";
326
365
  }
327
- if (!insideInterval(overlay.interval, shotInterval)) {
366
+ if (!insideInterval(overlay.interval, shot.interval)) {
328
367
  return "plan overlay interval falls outside its shot";
329
368
  }
330
369
  return undefined;
@@ -372,6 +411,7 @@ function snapshotPlan(plan) {
372
411
  const film = snapshotNode(plan.film);
373
412
  const scenes = Object.freeze(plan.scenes.map(snapshotScene));
374
413
  const shots = Object.freeze(plan.shots.map(snapshotShot));
414
+ const transitions = Object.freeze(plan.transitions.map(snapshotTransition));
375
415
  const videos = Object.freeze(plan.videos.map(snapshotVideo));
376
416
  const overlays = Object.freeze(plan.overlays.map(snapshotOverlay));
377
417
  return Object.freeze({
@@ -383,10 +423,19 @@ function snapshotPlan(plan) {
383
423
  film,
384
424
  scenes,
385
425
  shots,
426
+ transitions,
386
427
  videos,
387
428
  overlays,
388
429
  });
389
430
  }
431
+ function snapshotTransition(transition) {
432
+ return Object.freeze({
433
+ incomingShotId: transition.incomingShotId,
434
+ interval: Object.freeze({ ...transition.interval }),
435
+ node: snapshotNode(transition.node),
436
+ outgoingShotId: transition.outgoingShotId,
437
+ });
438
+ }
390
439
  function snapshotScene(scene) {
391
440
  return Object.freeze({
392
441
  node: snapshotNode(scene.node),
@@ -2,5 +2,5 @@ export type { RuntimeFrame } from "./clock.js";
2
2
  export type { RuntimeVideo } from "./media.js";
3
3
  export type { PresentationFrameBehavior, PresentationTemporalCapability, PresentationVisualCapability, } from "./generated/bundle-layout.js";
4
4
  export type { RuntimePlan } from "./session.js";
5
- export type { ContainerPresentation, FrameEffect, OverlayPresentation, PresentationBindings, PresentationExtensions, RuntimeOverlay, RuntimeNode, RuntimeScene, RuntimeShot, VideoPresentation, } from "./presentation.js";
5
+ export type { ContainerPresentation, FrameEffect, OverlayPresentation, PresentationBindings, PresentationExtensions, RuntimeOverlay, RuntimeNode, RuntimeScene, RuntimeShot, RuntimeTransition, TransitionPresentation, VideoPresentation, } from "./presentation.js";
6
6
  export type { PresentationResource, PresentationResourceKind, } from "./resource.js";