@patterkit/runtime 0.4.5 → 0.5.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/CHANGELOG.md +28 -0
- package/dist/index.cjs +74 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +74 -3
- package/dist/index.js.map +1 -1
- package/dist/patterplay.min.js +2 -2
- package/dist/patterplay.min.js.map +1 -1
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [f97f6eb]
|
|
8
|
+
- @patterkit/model@0.4.0
|
|
9
|
+
- @patterkit/dialect@0.1.6
|
|
10
|
+
|
|
3
11
|
## 0.4.1
|
|
4
12
|
|
|
5
13
|
### Patch Changes
|
|
@@ -25,6 +33,26 @@ version number always means the same runtime behaviour. This package is versione
|
|
|
25
33
|
|
|
26
34
|
## [Unreleased]
|
|
27
35
|
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
- **The `quality` property type: a story stage as an ordered ladder of named stages.** The value is a
|
|
39
|
+
stage name; ordering operators compare by ladder POSITION, `advance(@q)` steps to the next stage
|
|
40
|
+
saturating at the last, and a save carries the stage by name - so a stage inserted mid-production
|
|
41
|
+
shifts nothing. Declared with `stages` on the property; seeds at the first stage. Corpus-locked
|
|
42
|
+
across all four runtimes (gating, stepping, and the insertion story through a live hot swap).
|
|
43
|
+
|
|
44
|
+
## [0.5.0] - 2026-08-21
|
|
45
|
+
|
|
46
|
+
### Added
|
|
47
|
+
|
|
48
|
+
- **Cast lists you can query at runtime.** Three static reads answer "who is in this?": the cast the
|
|
49
|
+
project declares, the speakers of a scene, and the speakers of one block. Scene and block refs take
|
|
50
|
+
an internal id or a gameId address. The result is the character token a line beat carries, deduped
|
|
51
|
+
and ordered by first appearance, and it is derived from the AUTHORED structure, so a speaker behind a
|
|
52
|
+
condition, inside a group, or voicing a choice prompt is included: it answers who _can_ speak, not
|
|
53
|
+
who a given playthrough heard. Held across all four runtimes by the conformance corpus.
|
|
54
|
+
`engine.getCast()`, `engine.castForScene(sceneRef)`, `engine.castForBlock(sceneRef, blockRef)`.
|
|
55
|
+
|
|
28
56
|
## [0.4.5] - 2026-08-20
|
|
29
57
|
|
|
30
58
|
### Changed
|
package/dist/index.cjs
CHANGED
|
@@ -360,6 +360,42 @@ var Engine = class _Engine {
|
|
|
360
360
|
const id = this.resolveBlockRef(sceneId, blockRef);
|
|
361
361
|
return (id != null ? this.host.tagIndex.get(id) : void 0) ?? [];
|
|
362
362
|
}
|
|
363
|
+
/**
|
|
364
|
+
* Every cast member the PROJECT declares, in authored order - the same list `describeBundle` counts.
|
|
365
|
+
* A superset of any scene's cast: the validator holds a beat's `character` to a declared member, so
|
|
366
|
+
* {@link castForScene} and {@link castForBlock} only ever return names that appear here.
|
|
367
|
+
*/
|
|
368
|
+
getCast() {
|
|
369
|
+
const names = [];
|
|
370
|
+
for (const c of this.host.bundle.cast ?? []) if (c?.name) names.push(c.name);
|
|
371
|
+
return names;
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* A scene's cast: the `character` token of every speaker with a line anywhere in it, deduped, in
|
|
375
|
+
* first-appearance order. Static, like {@link getOutline}: it walks the authored structure, so a
|
|
376
|
+
* speaker behind a condition, inside any group, or voicing a choice prompt counts - this is who CAN
|
|
377
|
+
* speak in the scene, not who a given playthrough heard. Empty for an unknown ref, or a scene with no
|
|
378
|
+
* dialogue. Tokens, not display names: resolve those through the delivered step (`characterName`),
|
|
379
|
+
* which is what follows `setLocale`.
|
|
380
|
+
*/
|
|
381
|
+
castForScene(sceneRef) {
|
|
382
|
+
const id = this.resolveSceneRef(sceneRef);
|
|
383
|
+
const scene = id != null ? this.host.bundle.scenes[id] : void 0;
|
|
384
|
+
if (!scene) return [];
|
|
385
|
+
const out = /* @__PURE__ */ new Set();
|
|
386
|
+
for (const block of scene.blocks) collectCast(block.children, out);
|
|
387
|
+
return [...out];
|
|
388
|
+
}
|
|
389
|
+
/** One block's cast, by scene + block ref (id or gameId). {@link castForScene} scoped to a block. */
|
|
390
|
+
castForBlock(sceneRef, blockRef) {
|
|
391
|
+
const sceneId = this.resolveSceneRef(sceneRef);
|
|
392
|
+
const id = this.resolveBlockRef(sceneId, blockRef);
|
|
393
|
+
const block = id != null ? this.host.blockById.get(id) : void 0;
|
|
394
|
+
if (!block) return [];
|
|
395
|
+
const out = /* @__PURE__ */ new Set();
|
|
396
|
+
collectCast(block.children, out);
|
|
397
|
+
return [...out];
|
|
398
|
+
}
|
|
363
399
|
/**
|
|
364
400
|
* The authored structure as a nested tree: scenes -> blocks -> children (groups + snippets, groups
|
|
365
401
|
* preserved) -> a snippet's beats. Static (no flow / play state); per-beat data is read at the source
|
|
@@ -489,6 +525,7 @@ var Engine = class _Engine {
|
|
|
489
525
|
ref: `@${d.name}`,
|
|
490
526
|
type: d.type,
|
|
491
527
|
values: d.values,
|
|
528
|
+
stages: d.stages,
|
|
492
529
|
value: this.getProperty(`@${d.name}`),
|
|
493
530
|
default: declDefault(d)
|
|
494
531
|
}));
|
|
@@ -621,9 +658,28 @@ var Flow = class {
|
|
|
621
658
|
nextRandom: this.rng,
|
|
622
659
|
visits: (id2) => this.visitCounts.get(id2) ?? 0,
|
|
623
660
|
patterVisits: (id2) => this.host.sharedVisits.get(id2) ?? 0
|
|
624
|
-
}
|
|
661
|
+
},
|
|
662
|
+
// The quality channel (expr 0.4.0): hands the evaluator a property's stage ladder, which is what
|
|
663
|
+
// makes ordering compare by position and advance() step. Wired by hand because this context takes
|
|
664
|
+
// only the registry's SCOPES (the patter/scene resolvers here are the flow's own merged views),
|
|
665
|
+
// and because @scene declarations belong to whichever scene the flow is in RIGHT NOW.
|
|
666
|
+
qualities: (scope, name) => this.stagesFor(scope, name)
|
|
625
667
|
};
|
|
626
668
|
}
|
|
669
|
+
/** The stage ladder of `@scope.name` when it is a declared quality, else undefined. Names compare
|
|
670
|
+
* lowercase, as the compiler emits references (the selfBackedResolver lesson). */
|
|
671
|
+
stagesFor(scope, name) {
|
|
672
|
+
const key = name.toLowerCase();
|
|
673
|
+
const fromDecls = (decls) => decls?.find((d) => d.name.toLowerCase() === key && d.type === "quality")?.stages;
|
|
674
|
+
if (scope === "patter") {
|
|
675
|
+
return fromDecls(this.host.patterSharedDecls) ?? fromDecls(this.host.patterLocalDecls);
|
|
676
|
+
}
|
|
677
|
+
if (scope === "scene") {
|
|
678
|
+
const scene = this.currentSceneId != null ? this.host.bundle.scenes[this.currentSceneId] : void 0;
|
|
679
|
+
return fromDecls(scene?.sceneProps);
|
|
680
|
+
}
|
|
681
|
+
return fromDecls(this.host.bundle.scopeRegistry?.scopes.find((s) => s.token === scope)?.declarations);
|
|
682
|
+
}
|
|
627
683
|
// -- Host API -------------------------------------------------------------
|
|
628
684
|
/** Begin this flow at a scene (and optionally a specific block within it). */
|
|
629
685
|
start(sceneId, blockId) {
|
|
@@ -1353,6 +1409,15 @@ var Flow = class {
|
|
|
1353
1409
|
}
|
|
1354
1410
|
}
|
|
1355
1411
|
};
|
|
1412
|
+
function collectCast(nodes, out) {
|
|
1413
|
+
(0, import_model.walkNodes)(nodes, (n) => {
|
|
1414
|
+
if (n.type === "group") {
|
|
1415
|
+
if (n.prompt?.kind === "line" && n.prompt.character) out.add(n.prompt.character);
|
|
1416
|
+
return;
|
|
1417
|
+
}
|
|
1418
|
+
for (const beat of n.beats ?? []) if (beat.kind === "line" && beat.character) out.add(beat.character);
|
|
1419
|
+
});
|
|
1420
|
+
}
|
|
1356
1421
|
function serialiseSelectors(map) {
|
|
1357
1422
|
const out = {};
|
|
1358
1423
|
for (const [id, st] of map) {
|
|
@@ -1376,7 +1441,7 @@ function deserialiseSelectors(rec) {
|
|
|
1376
1441
|
return map;
|
|
1377
1442
|
}
|
|
1378
1443
|
function toDecl(decl) {
|
|
1379
|
-
return { name: decl.name, type: decl.type, values: decl.values, default: decl.default };
|
|
1444
|
+
return { name: decl.name, type: decl.type, values: decl.values, stages: decl.stages, default: decl.default };
|
|
1380
1445
|
}
|
|
1381
1446
|
function declDefault(d) {
|
|
1382
1447
|
if (d.default !== void 0) return d.default;
|
|
@@ -1389,12 +1454,14 @@ function declDefault(d) {
|
|
|
1389
1454
|
return [];
|
|
1390
1455
|
case "enum":
|
|
1391
1456
|
return d.values?.[0] ?? "";
|
|
1457
|
+
case "quality":
|
|
1458
|
+
return d.stages?.[0] ?? "";
|
|
1392
1459
|
default:
|
|
1393
1460
|
return false;
|
|
1394
1461
|
}
|
|
1395
1462
|
}
|
|
1396
1463
|
function toForeignDecl(decl) {
|
|
1397
|
-
return { name: decl.name, type: decl.type, values: decl.values, default: decl.default, writable: decl.writable };
|
|
1464
|
+
return { name: decl.name, type: decl.type, values: decl.values, stages: decl.stages, default: decl.default, writable: decl.writable };
|
|
1398
1465
|
}
|
|
1399
1466
|
function hostScopeDefault(decl) {
|
|
1400
1467
|
if (decl.default !== void 0) return decl.default;
|
|
@@ -1409,6 +1476,8 @@ function hostScopeDefault(decl) {
|
|
|
1409
1476
|
return [];
|
|
1410
1477
|
case "enum":
|
|
1411
1478
|
return decl.values?.[0] ?? "";
|
|
1479
|
+
case "quality":
|
|
1480
|
+
return decl.stages?.[0] ?? "";
|
|
1412
1481
|
}
|
|
1413
1482
|
}
|
|
1414
1483
|
function selfBackedResolver(decls) {
|
|
@@ -1435,6 +1504,8 @@ function sceneDefault(decl) {
|
|
|
1435
1504
|
return [];
|
|
1436
1505
|
case "enum":
|
|
1437
1506
|
return decl.values?.[0] ?? "";
|
|
1507
|
+
case "quality":
|
|
1508
|
+
return decl.stages?.[0] ?? "";
|
|
1438
1509
|
}
|
|
1439
1510
|
}
|
|
1440
1511
|
function truthy(v) {
|