@plaintake/scenario 1.24.0 → 1.30.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 +10 -0
- package/dist/index.js +346 -38
- package/dist/schema/manifest.d.ts +1 -0
- package/dist/schema/narration-index.d.ts +1 -1
- package/dist/schema/render-plan.d.ts +171 -14
- package/dist/schema/results.d.ts +53 -6
- package/dist/schema/scenario.d.ts +62 -0
- package/dist/types.d.ts +94 -36
- package/package.json +1 -1
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ScenarioMeta } from './schema/index.js';
|
|
1
|
+
import type { ScenarioMeta, TerminalMetaInput } from './schema/index.js';
|
|
2
2
|
import type { BrowserContextOptions, Locator, Page } from 'playwright-core';
|
|
3
3
|
/**
|
|
4
4
|
* What kind of interaction `run()` performs, declared rather than observed. Like
|
|
@@ -217,10 +217,10 @@ export type ExplainConnection = {
|
|
|
217
217
|
to: string;
|
|
218
218
|
label?: string;
|
|
219
219
|
};
|
|
220
|
-
/** One side of a `comparison` explain scene: what this alternative is called, and
|
|
220
|
+
/** One side of a `comparison` explain scene: what this alternative is called, and two to six short items. */
|
|
221
221
|
export type ExplainColumn = {
|
|
222
222
|
heading: string;
|
|
223
|
-
|
|
223
|
+
items: string[];
|
|
224
224
|
};
|
|
225
225
|
/** A named group of imported svg parts a `diagram` scene's cue can target as one thing. */
|
|
226
226
|
export type ExplainRegion = {
|
|
@@ -228,16 +228,16 @@ export type ExplainRegion = {
|
|
|
228
228
|
of: string[];
|
|
229
229
|
};
|
|
230
230
|
/**
|
|
231
|
-
* The five motion-graphics scenes an explain cut-away can be, mirroring
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
*
|
|
231
|
+
* The five motion-graphics scenes an explain cut-away can be, mirroring the scene registry in
|
|
232
|
+
* `@plaintake/motion` prop-for-prop (`title`/`process`/`comparison`/`diagram`/`recap`). This
|
|
233
|
+
* package is types only — each scene is compiled and drawn after capture and spliced into the
|
|
234
|
+
* recording as a frozen segment — so this union is a structural mirror of those scene schemas,
|
|
235
|
+
* and the deep validation (character caps, list bounds, phrase resolution) belongs to the
|
|
236
|
+
* compile at run time, not to this package's types. What `validate` checks without a
|
|
237
237
|
* browser is the shape around the scene: id, narration, a known `type`.
|
|
238
238
|
*
|
|
239
239
|
* Geometry is deliberately absent. Where a pixel appears is the scene layout's decision,
|
|
240
|
-
* exactly as it is in
|
|
240
|
+
* exactly as it is in any motion-graphics scene; an author says what exists and what the
|
|
241
241
|
* narration points at, and nothing about inches.
|
|
242
242
|
*/
|
|
243
243
|
export type ExplainScene = {
|
|
@@ -273,7 +273,7 @@ export type ExplainScene = {
|
|
|
273
273
|
items: string[];
|
|
274
274
|
};
|
|
275
275
|
/**
|
|
276
|
-
* What a cue does to the viewer's attention. The same vocabulary
|
|
276
|
+
* What a cue does to the viewer's attention. The same vocabulary the explain compile defines —
|
|
277
277
|
* deliberately small, and deliberately not easing curves or tween internals: an author says
|
|
278
278
|
* what should happen; how that is expressed is the renderer's job.
|
|
279
279
|
*/
|
|
@@ -281,7 +281,7 @@ export type ExplainCueAction = 'reveal' | 'hide' | 'emphasize' | 'deemphasize' |
|
|
|
281
281
|
/**
|
|
282
282
|
* When a cue fires: bound to words in the narration, resolved against the timings the speech
|
|
283
283
|
* model measures. Rewriting a sentence moves the animation with it instead of silently
|
|
284
|
-
* desynchronising — which is why there is no numeric `at` offset here the way
|
|
284
|
+
* desynchronising — which is why there is no numeric `at` offset here the way the compile's
|
|
285
285
|
* own cue schema allows one. An explain scene always speaks (its narration is the scene's
|
|
286
286
|
* clock), so a phrase is the only anchor that survives a rewording, and an offset that could
|
|
287
287
|
* not is not offered.
|
|
@@ -296,22 +296,23 @@ export type ExplainCue = {
|
|
|
296
296
|
};
|
|
297
297
|
/**
|
|
298
298
|
* A full-frame motion-graphics cut-away in the middle of a browser demo — "explain while
|
|
299
|
-
* demoing". `demo.explain()` stops the screencast, splices in a
|
|
299
|
+
* demoing". `demo.explain()` stops the screencast, splices in a rendered motion-graphics scene
|
|
300
300
|
* (`title`/`process`/`comparison`/`diagram`/`recap`), and resumes the recording on the same
|
|
301
301
|
* page: the cut-away is a boundary on the timeline, the same mechanism a multi-actor `turn`
|
|
302
302
|
* uses, so nothing about the recording's determinism or re-renderability changes. The scene
|
|
303
303
|
* is compiled and rendered after capture finishes, from a generated one-scene project — the
|
|
304
304
|
* only inputs that matter are the ones right here.
|
|
305
305
|
*
|
|
306
|
-
* Free on every tier, like every authoring verb.
|
|
307
|
-
*
|
|
308
|
-
*
|
|
306
|
+
* Free on every tier, like every authoring verb. Always narrated — the narration is the
|
|
307
|
+
* scene's clock — so it needs the voice model installed at record time even when speech is
|
|
308
|
+
* off (`plaintake doctor` reports whether it is there); a bundle that carries an explain
|
|
309
|
+
* segment re-renders without it, the same way it re-renders without a browser.
|
|
309
310
|
*/
|
|
310
311
|
export type DemoExplain = {
|
|
311
312
|
/**
|
|
312
313
|
* Stable, authored — the same rule every other id here follows. It becomes the directory
|
|
313
|
-
* the frozen artifacts live in (`explain/<id>/segment.mp4` and its
|
|
314
|
-
* the generated scene's own id, so it must read as
|
|
314
|
+
* the frozen artifacts live in (`explain/<id>/segment.mp4` and its frozen plan) and
|
|
315
|
+
* the generated scene's own id, so it must read as scene ids do: lower-case
|
|
315
316
|
* alphanumeric and hyphens, starting alphanumeric. Checked at run time, with the offending
|
|
316
317
|
* id named.
|
|
317
318
|
*/
|
|
@@ -320,7 +321,7 @@ export type DemoExplain = {
|
|
|
320
321
|
title: string;
|
|
321
322
|
/**
|
|
322
323
|
* What the scene says. The source of truth for both the audio and the caption — there is
|
|
323
|
-
* no separate caption field, for the same reason
|
|
324
|
+
* no separate caption field, for the same reason a motion-graphics scene has none: two strings that
|
|
324
325
|
* are supposed to say the same thing will eventually disagree, and the one the viewer
|
|
325
326
|
* hears is the one that matters. The measured speech is also the scene's duration: the
|
|
326
327
|
* cut-away lasts exactly as long as it takes to say this, plus its lead-in and lead-out.
|
|
@@ -387,6 +388,53 @@ export type ActorStepMeta = {
|
|
|
387
388
|
*/
|
|
388
389
|
paddingPx?: number;
|
|
389
390
|
};
|
|
391
|
+
/**
|
|
392
|
+
* `ActorStepMeta` for a `TermHandle` verb, plus the one thing a terminal step can mean that a
|
|
393
|
+
* browser step cannot: `expectExit: true` says the terminal process exiting during this step is
|
|
394
|
+
* the point of it (a `quit`, an `exit`), not a capture failure.
|
|
395
|
+
*/
|
|
396
|
+
export type TermStepMeta = ActorStepMeta & {
|
|
397
|
+
expectExit?: boolean;
|
|
398
|
+
};
|
|
399
|
+
/** A rectangle of terminal cells: zero-based `row`/`col` of its top-left cell, size in cells. */
|
|
400
|
+
export type TermCells = {
|
|
401
|
+
row: number;
|
|
402
|
+
col: number;
|
|
403
|
+
width: number;
|
|
404
|
+
height: number;
|
|
405
|
+
};
|
|
406
|
+
/**
|
|
407
|
+
* The live terminal a scenario declaring `terminal` drives, handed to `run()` as `term`. Each
|
|
408
|
+
* verb records `step.start`/`step.finish` through the same bracket `Actor` verbs use, so
|
|
409
|
+
* captions, narration, cursor, camera, highlight and chapters work unchanged.
|
|
410
|
+
*/
|
|
411
|
+
export type TermHandle = {
|
|
412
|
+
/**
|
|
413
|
+
* The terminal as an actor, to turn back to it with `demo.turn(term.actor)`. Only with
|
|
414
|
+
* `terminal.browser: true`; reading it otherwise throws (exit 2).
|
|
415
|
+
*/
|
|
416
|
+
readonly actor: Actor;
|
|
417
|
+
/** Types `line`, then Enter. Records a step whose target is the prompt line. */
|
|
418
|
+
run(line: string, meta?: TermStepMeta): Promise<void>;
|
|
419
|
+
/** Types at a fixed per-character delay — part of the timeline, never wall-clock driven. */
|
|
420
|
+
type(text: string, meta?: TermStepMeta): Promise<void>;
|
|
421
|
+
/** `'Enter'`, `'Ctrl+C'`, or a space-separated sequence such as `'Ctrl+B c'`. */
|
|
422
|
+
press(keys: string, meta?: TermStepMeta): Promise<void>;
|
|
423
|
+
/** Same bounds and timeout semantics as `demo.waitFor`. */
|
|
424
|
+
waitForText(pattern: RegExp | string, opts?: {
|
|
425
|
+
timeoutMs?: number;
|
|
426
|
+
id?: string;
|
|
427
|
+
title?: string;
|
|
428
|
+
}): Promise<void>;
|
|
429
|
+
/** A locator over the first match on the visible screen. */
|
|
430
|
+
getByText(pattern: RegExp | string): Locator;
|
|
431
|
+
/** A locator over a rectangle of cells, refused when it is outside the grid. */
|
|
432
|
+
cells(r: TermCells): Locator;
|
|
433
|
+
/** The visible screen, one line per row. */
|
|
434
|
+
screenText(): Promise<string>;
|
|
435
|
+
/** Reuses `DemoAssertion` verbatim, recorded against the default actor like `demo.assert`. */
|
|
436
|
+
assert(assertion: DemoAssertion): Promise<void>;
|
|
437
|
+
};
|
|
390
438
|
/**
|
|
391
439
|
* A named participant in a multi-actor demo: its own Playwright `BrowserContext`, its own
|
|
392
440
|
* page, and a handle of verbs that each perform a Playwright action *and* record the
|
|
@@ -539,20 +587,14 @@ export interface DemoContext extends PreflightContext {
|
|
|
539
587
|
* `opts.card`, when given, plays a full-frame transition card between the two actors'
|
|
540
588
|
* segments — the `lines` it names, an optional spoken `narration`, held for `durationMs`.
|
|
541
589
|
*
|
|
542
|
-
*
|
|
543
|
-
*
|
|
544
|
-
* is synthesised at render time as `Now: <label>`, naming the
|
|
545
|
-
* it was given to `demo.actor()`, held for the
|
|
546
|
-
*
|
|
547
|
-
* either way; `opts.card` only ever changes whether that hand-off also gets a full-frame beat
|
|
548
|
-
* of its own, and what it says.
|
|
590
|
+
* `opts.card: false` is a hard cut: no card and no gap. With no `opts.card` the scenario
|
|
591
|
+
* default applies: a cut for a `terminal.browser` scenario unless `terminal.transition` is
|
|
592
|
+
* `'card'`; otherwise the card is synthesised at render time as `Now: <label>`, naming the
|
|
593
|
+
* incoming actor by the `label` it was given to `demo.actor()`, held for the default
|
|
594
|
+
* duration. The persistent corner badge names the active actor throughout either way.
|
|
549
595
|
*/
|
|
550
596
|
turn(actor: Actor, opts?: {
|
|
551
|
-
card?:
|
|
552
|
-
lines: string[];
|
|
553
|
-
narration?: string;
|
|
554
|
-
durationMs?: number;
|
|
555
|
-
};
|
|
597
|
+
card?: TurnCard | false;
|
|
556
598
|
}): Promise<void>;
|
|
557
599
|
/**
|
|
558
600
|
* Cuts away from the browser recording to a full-frame motion-graphics scene — a diagram
|
|
@@ -561,10 +603,10 @@ export interface DemoContext extends PreflightContext {
|
|
|
561
603
|
* a `turn` does minus the actor switch, so the cut-away occupies its own slot on the
|
|
562
604
|
* timeline and nothing it covers is ever captured.
|
|
563
605
|
*
|
|
564
|
-
* The scene is not drawn live: it is compiled and rendered
|
|
565
|
-
*
|
|
566
|
-
*
|
|
567
|
-
*
|
|
606
|
+
* The scene is not drawn live: it is compiled and rendered in process after capture
|
|
607
|
+
* finishes, from the request's own fields, and spliced in at render time as a frozen
|
|
608
|
+
* 1920×1080@30 segment — which is what keeps the bundle re-renderable without a voice
|
|
609
|
+
* model, without a browser, and byte-identically. Its narration is spoken by the
|
|
568
610
|
* same engine as the rest of the recording (`--speech on`), lands in the same caption
|
|
569
611
|
* track, and is the scene's clock: the cut-away lasts exactly as long as it takes to say.
|
|
570
612
|
*
|
|
@@ -574,10 +616,25 @@ export interface DemoContext extends PreflightContext {
|
|
|
574
616
|
*/
|
|
575
617
|
explain(request: DemoExplain): Promise<void>;
|
|
576
618
|
}
|
|
619
|
+
/** An explicit transition card for `demo.turn`. */
|
|
620
|
+
export type TurnCard = {
|
|
621
|
+
lines: string[];
|
|
622
|
+
narration?: string;
|
|
623
|
+
durationMs?: number;
|
|
624
|
+
};
|
|
625
|
+
/**
|
|
626
|
+
* `term` is present only when the scenario declares `terminal`; a scenario without one is
|
|
627
|
+
* handed no `term` key at all.
|
|
628
|
+
*
|
|
629
|
+
* `page` is the terminal page in a terminal scenario. `baseURL` is the web target (`--base-url`
|
|
630
|
+
* or the fixture) when `terminal.browser` is set; without it, in a terminal scenario, it is the
|
|
631
|
+
* terminal page's URL.
|
|
632
|
+
*/
|
|
577
633
|
export type DemoRunArgs = {
|
|
578
634
|
page: Page;
|
|
579
635
|
demo: DemoContext;
|
|
580
636
|
baseURL: string;
|
|
637
|
+
term?: TermHandle;
|
|
581
638
|
};
|
|
582
639
|
/** Same property names as `DemoRunArgs`, so moving code between phases changes nothing else. */
|
|
583
640
|
export type PreflightArgs = {
|
|
@@ -625,7 +682,8 @@ export type DemoDefinition = ScenarioMeta & {
|
|
|
625
682
|
* field is one edit here instead of two that can drift apart.
|
|
626
683
|
*/
|
|
627
684
|
type Defaulted = 'language' | 'allowedConsoleErrors' | 'handoff' | 'handoffTimeoutMs';
|
|
628
|
-
export type DemoDefinitionInput = Omit<ScenarioMeta, Defaulted> & Partial<Pick<ScenarioMeta, Defaulted>> & {
|
|
685
|
+
export type DemoDefinitionInput = Omit<ScenarioMeta, Defaulted | 'terminal'> & Partial<Pick<ScenarioMeta, Defaulted>> & {
|
|
686
|
+
terminal?: TerminalMetaInput;
|
|
629
687
|
run(args: DemoRunArgs): Promise<void>;
|
|
630
688
|
} & PreflightHook & WarmupHook;
|
|
631
689
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plaintake/scenario",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.30.0",
|
|
4
4
|
"description": "Authoring SDK for PlainTake demo scenarios: defineDemo and the scenario DSL types. Install for editor autocomplete; the PlainTake binary ships a runtime fallback.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|