@patterkit/runtime 0.24.0 → 0.25.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/CHANGELOG.md +13 -0
- package/LICENSE +21 -0
- package/dist/index.cjs +26 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +27 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -33,6 +33,19 @@ version number always means the same runtime behaviour. This package is versione
|
|
|
33
33
|
|
|
34
34
|
## [Unreleased]
|
|
35
35
|
|
|
36
|
+
## [0.25.0] - 2026-10-14
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- **Speaker labels**: a line step, a line choice prompt, and a beat's info carry `speakerLabel`, the name to
|
|
41
|
+
show for the speaker, localised. With a qualifier it is the character's own label for that pair when the
|
|
42
|
+
project gives one (`speaker:<NAME>:<qualifier>`), else the project's speaker pattern (`speaker:pattern`,
|
|
43
|
+
`{name} ({qualifier})` by default) filled with the shown name and the qualifier's shown name; with none, the
|
|
44
|
+
shown name (the token when the cast gives none). Each piece follows the active locale, then the default, then
|
|
45
|
+
the authored value. A translated pair label counts only for a pair the project overrides. Absent with no
|
|
46
|
+
speaker, on a silenced line, and in IDs-only mode. Saved choice prompts carry it, and an older save works it
|
|
47
|
+
out again on load.
|
|
48
|
+
|
|
36
49
|
## [0.24.0] - 2026-10-11
|
|
37
50
|
|
|
38
51
|
### Added
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ian Thomas
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.cjs
CHANGED
|
@@ -202,6 +202,9 @@ var Engine = class _Engine {
|
|
|
202
202
|
for (const c of bundle.cast ?? []) if (c.displayName) castDisplay.set(c.name, c.displayName);
|
|
203
203
|
const qualifierDisplay = /* @__PURE__ */ new Map();
|
|
204
204
|
for (const q of bundle.qualifiers ?? []) if (q?.gameId) qualifierDisplay.set(q.gameId, q.name);
|
|
205
|
+
const speakerLabels = /* @__PURE__ */ new Map();
|
|
206
|
+
for (const c of bundle.cast ?? []) for (const [q, label] of Object.entries(c.qualifierLabels ?? {})) if (typeof label === "string") speakerLabels.set(`${c.name}\0${q}`, label);
|
|
207
|
+
const speakerPattern = bundle.speakerPattern ?? import_model2.DEFAULT_SPEAKER_PATTERN;
|
|
205
208
|
this.defaultSeed = (options.seed ?? 2654435769) >>> 0;
|
|
206
209
|
const nodeIndex = /* @__PURE__ */ new Map();
|
|
207
210
|
const blockIndex = /* @__PURE__ */ new Map();
|
|
@@ -263,6 +266,8 @@ var Engine = class _Engine {
|
|
|
263
266
|
defaultStrings,
|
|
264
267
|
castDisplay,
|
|
265
268
|
qualifierDisplay,
|
|
269
|
+
speakerLabels,
|
|
270
|
+
speakerPattern,
|
|
266
271
|
nodeIndex,
|
|
267
272
|
blockIndex,
|
|
268
273
|
blockById,
|
|
@@ -673,6 +678,8 @@ var Engine = class _Engine {
|
|
|
673
678
|
const name = this.host.defaultStrings[(0, import_model2.qualifierStringKey)(beat.qualifier)] ?? this.host.qualifierDisplay.get(beat.qualifier);
|
|
674
679
|
if (name !== void 0) info.qualifierName = name;
|
|
675
680
|
}
|
|
681
|
+
const label = speakerLabelOf(this.host, beat.character, beat.qualifier, true);
|
|
682
|
+
if (label !== void 0) info.speakerLabel = label;
|
|
676
683
|
}
|
|
677
684
|
if (beat.kind === "line" || beat.kind === "text") {
|
|
678
685
|
const pad = this.host.padIndex.get(beat.id);
|
|
@@ -1511,7 +1518,8 @@ var Flow = class {
|
|
|
1511
1518
|
if (!node) continue;
|
|
1512
1519
|
byId.set(o.id, node);
|
|
1513
1520
|
const { prompt: saved, ...rest } = o;
|
|
1514
|
-
|
|
1521
|
+
const label = saved?.kind === "line" && saved.speakerLabel === void 0 ? speakerLabelOf(this.host, saved.character, saved.qualifier) : void 0;
|
|
1522
|
+
options.push({ ...rest, ...saved ? { prompt: { ...saved, padAfter: saved.padAfter ?? this.promptPadOf(node), ...label !== void 0 ? { speakerLabel: label } : {} } } : {} });
|
|
1515
1523
|
}
|
|
1516
1524
|
if (options.length > 0) this.pendingChoice = { groupId: c.pendingChoice.groupId, options, byId };
|
|
1517
1525
|
}
|
|
@@ -1520,7 +1528,9 @@ var Flow = class {
|
|
|
1520
1528
|
if (this.pendingPromptOwnerId) {
|
|
1521
1529
|
const owner = this.host.nodeIndex.get(this.pendingPromptOwnerId);
|
|
1522
1530
|
const beat = owner ? this.authoredPromptOf(owner) : void 0;
|
|
1523
|
-
|
|
1531
|
+
const saved = c.pendingPrompt;
|
|
1532
|
+
const label = saved?.kind === "line" && saved.speakerLabel === void 0 ? speakerLabelOf(this.host, saved.character, saved.qualifier) : void 0;
|
|
1533
|
+
if (beat) this.pendingPrompt = { beat, ...saved ? { shown: { ...saved, padAfter: saved.padAfter ?? this.padOf(beat.id), ...label !== void 0 ? { speakerLabel: label } : {} } } : {} };
|
|
1524
1534
|
else this.pendingPromptOwnerId = null;
|
|
1525
1535
|
}
|
|
1526
1536
|
}
|
|
@@ -1906,6 +1916,7 @@ var Flow = class {
|
|
|
1906
1916
|
direction: silent ? void 0 : beat.direction,
|
|
1907
1917
|
qualifier: silent ? void 0 : beat.qualifier,
|
|
1908
1918
|
qualifierName: silent ? void 0 : this.resolveQualifierName(beat.qualifier),
|
|
1919
|
+
speakerLabel: silent ? void 0 : speakerLabelOf(this.host, beat.character, beat.qualifier),
|
|
1909
1920
|
padAfter: this.padOf(beat.id),
|
|
1910
1921
|
// a silent line still fires, so it still carries its pause
|
|
1911
1922
|
gameData: beat.gameData,
|
|
@@ -1955,6 +1966,7 @@ var Flow = class {
|
|
|
1955
1966
|
direction: beat.direction,
|
|
1956
1967
|
qualifier: beat.qualifier,
|
|
1957
1968
|
qualifierName: this.resolveQualifierName(beat.qualifier),
|
|
1969
|
+
speakerLabel: speakerLabelOf(this.host, beat.character, beat.qualifier),
|
|
1958
1970
|
padAfter
|
|
1959
1971
|
} : { kind: "text", text, padAfter };
|
|
1960
1972
|
}
|
|
@@ -1977,6 +1989,7 @@ var Flow = class {
|
|
|
1977
1989
|
direction: shown.direction,
|
|
1978
1990
|
qualifier: shown.qualifier,
|
|
1979
1991
|
qualifierName: shown.qualifierName,
|
|
1992
|
+
speakerLabel: shown.speakerLabel,
|
|
1980
1993
|
padAfter: this.padOf(beat.id),
|
|
1981
1994
|
gameData: beat.gameData,
|
|
1982
1995
|
...withTags
|
|
@@ -2122,6 +2135,16 @@ function collectCast(nodes, out) {
|
|
|
2122
2135
|
for (const beat of n.beats ?? []) if (beat.kind === "line" && beat.character) out.add(beat.character);
|
|
2123
2136
|
});
|
|
2124
2137
|
}
|
|
2138
|
+
function speakerLabelOf(host, character, qualifier, source = false) {
|
|
2139
|
+
if (!character || host.emitIds) return void 0;
|
|
2140
|
+
const lookup = (key) => (source ? void 0 : host.strings[key]) ?? host.defaultStrings[key];
|
|
2141
|
+
const name = lookup((0, import_model2.castStringKey)(character)) ?? host.castDisplay.get(character) ?? character;
|
|
2142
|
+
if (qualifier === void 0) return name;
|
|
2143
|
+
const own = host.speakerLabels.get(`${character}\0${qualifier}`);
|
|
2144
|
+
if (own !== void 0) return lookup((0, import_model2.speakerLabelKey)(character, qualifier)) ?? own;
|
|
2145
|
+
const shown = lookup((0, import_model2.qualifierStringKey)(qualifier)) ?? host.qualifierDisplay.get(qualifier) ?? qualifier;
|
|
2146
|
+
return (0, import_model2.formatSpeakerLabel)(lookup(import_model2.SPEAKER_PATTERN_KEY) ?? host.speakerPattern, name, shown);
|
|
2147
|
+
}
|
|
2125
2148
|
function gameDataField(gameData) {
|
|
2126
2149
|
return gameData && Object.keys(gameData).length ? { gameData } : {};
|
|
2127
2150
|
}
|
|
@@ -2132,6 +2155,7 @@ function savedPrompt(p) {
|
|
|
2132
2155
|
if (p.direction !== void 0) out.direction = p.direction;
|
|
2133
2156
|
if (p.qualifier !== void 0) out.qualifier = p.qualifier;
|
|
2134
2157
|
if (p.qualifierName !== void 0) out.qualifierName = p.qualifierName;
|
|
2158
|
+
if (p.speakerLabel !== void 0) out.speakerLabel = p.speakerLabel;
|
|
2135
2159
|
if (typeof p.padAfter === "number") out.padAfter = p.padAfter;
|
|
2136
2160
|
return out;
|
|
2137
2161
|
}
|