@patterkit/model 0.19.0 → 0.21.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/dist/index.cjs +6 -11
- package/dist/index.d.cts +56 -57
- package/dist/index.d.ts +56 -57
- package/dist/index.js +2 -7
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -54,11 +54,11 @@ __export(index_exports, {
|
|
|
54
54
|
deriveRecordingFolders: () => deriveRecordingFolders,
|
|
55
55
|
effectiveGameId: () => effectiveGameId,
|
|
56
56
|
formatSpeakerLabel: () => formatSpeakerLabel,
|
|
57
|
-
gameIdify: () => gameIdify,
|
|
57
|
+
gameIdify: () => import_toolkit.gameIdify,
|
|
58
58
|
isCaseOnlyPropertyName: () => import_expr.isCaseOnlyPropertyName,
|
|
59
59
|
isContentlessBeat: () => isContentlessBeat,
|
|
60
60
|
isDialogueScene: () => isDialogueScene,
|
|
61
|
-
isValidGameId: () => isValidGameId,
|
|
61
|
+
isValidGameId: () => import_toolkit.isValidGameId,
|
|
62
62
|
isValidPropertyName: () => import_expr.isValidPropertyName,
|
|
63
63
|
projectLayout: () => projectLayout,
|
|
64
64
|
projectQualifiers: () => projectQualifiers,
|
|
@@ -73,6 +73,7 @@ __export(index_exports, {
|
|
|
73
73
|
walkNodes: () => walkNodes
|
|
74
74
|
});
|
|
75
75
|
module.exports = __toCommonJS(index_exports);
|
|
76
|
+
var import_toolkit = require("@wildwinter/toolkit");
|
|
76
77
|
var import_expr = require("@wildwinter/expr");
|
|
77
78
|
function walkNodes(nodes, visit) {
|
|
78
79
|
for (const node of nodes) {
|
|
@@ -88,15 +89,9 @@ function isContentlessBeat(beat, hasText) {
|
|
|
88
89
|
if (beat.tags && beat.tags.length > 0) return false;
|
|
89
90
|
return beat.kind === "text" || !beat.character && !beat.direction;
|
|
90
91
|
}
|
|
91
|
-
function gameIdify(text) {
|
|
92
|
-
return text.toLowerCase().replace(/['’]/g, "").replace(/[^a-z0-9-]+/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
|
|
93
|
-
}
|
|
94
|
-
function isValidGameId(gameId) {
|
|
95
|
-
return /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(gameId);
|
|
96
|
-
}
|
|
97
92
|
function effectiveGameId(entity) {
|
|
98
93
|
const g = entity.gameId?.trim();
|
|
99
|
-
return g ? g : gameIdify(entity.name);
|
|
94
|
+
return g ? g : (0, import_toolkit.gameIdify)(entity.name);
|
|
100
95
|
}
|
|
101
96
|
function sceneAddressIndex(scenes) {
|
|
102
97
|
const byAddress = /* @__PURE__ */ new Map();
|
|
@@ -205,7 +200,7 @@ function deriveRecordingFolders(audioRoot, statuses) {
|
|
|
205
200
|
const root = audioRoot?.trim();
|
|
206
201
|
return statuses.map((s, i) => {
|
|
207
202
|
if (i === 0 || !root) return { name: s.name };
|
|
208
|
-
return { name: s.name, folder: `${root}/${gameIdify(s.name)}` };
|
|
203
|
+
return { name: s.name, folder: `${root}/${(0, import_toolkit.gameIdify)(s.name)}` };
|
|
209
204
|
});
|
|
210
205
|
}
|
|
211
206
|
var DEFAULT_DOCUMENTATION_CLASSES = [
|
|
@@ -237,7 +232,7 @@ var HANDOFF_SCHEMA = "patter/handoff@0";
|
|
|
237
232
|
var DEFAULT_CAPTION_DELIMITERS = { open: "[", close: "]" };
|
|
238
233
|
var DEFAULT_CAPTION_CHARACTER = "SFX";
|
|
239
234
|
var SAVE_SCHEMA = "patter/save@0";
|
|
240
|
-
var SAVE_VERSION =
|
|
235
|
+
var SAVE_VERSION = 4;
|
|
241
236
|
var DEFAULT_LAYOUT = { flow: "scenes/", strings: "loc/", authoring: "authoring/", extensions: "extensions/" };
|
|
242
237
|
function projectLayout(project) {
|
|
243
238
|
return { ...DEFAULT_LAYOUT, ...project.layout };
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AstNode } from '@wildwinter/expr';
|
|
2
2
|
export { RESERVED_PROPERTY_NAMES, isCaseOnlyPropertyName, isValidPropertyName, propertyNameify } from '@wildwinter/expr';
|
|
3
|
+
export { gameIdify, isValidGameId } from '@wildwinter/toolkit';
|
|
3
4
|
|
|
4
5
|
type ScalarValue = boolean | number | string | string[];
|
|
5
6
|
/** Developer-defined host metadata (spec §17). Opaque to Patter. */
|
|
@@ -246,11 +247,6 @@ declare function walkNodes<N extends {
|
|
|
246
247
|
* just `{ jump }` with zero beats - which is valid.
|
|
247
248
|
*/
|
|
248
249
|
declare function isContentlessBeat(beat: Beat, hasText: boolean): boolean;
|
|
249
|
-
/** Slugify a name into a hyphen-form game id: lowercase, drop apostrophes, runs of
|
|
250
|
-
* other punctuation -> a single hyphen, collapse repeats, no leading / trailing hyphen. */
|
|
251
|
-
declare function gameIdify(text: string): string;
|
|
252
|
-
/** A valid authored game id: lowercase alphanumerics + hyphens, no leading / trailing hyphen. */
|
|
253
|
-
declare function isValidGameId(gameId: string): boolean;
|
|
254
250
|
|
|
255
251
|
/** The effective address: the explicit `gameId` if pinned, else derived from `name`. */
|
|
256
252
|
declare function effectiveGameId(entity: {
|
|
@@ -392,6 +388,11 @@ interface CastMember {
|
|
|
392
388
|
* (`{ vo: "Your thoughts" }`), where the project's speaker pattern shouldn't apply. Localised as the
|
|
393
389
|
* `speaker:<name>:<gameId>` string (`speakerLabelKey`). Absent for every pair that follows the pattern. */
|
|
394
390
|
qualifierLabels?: Record<string, string>;
|
|
391
|
+
/** The character's colour in the editors (their cue, the play window, the readable script): a slot of the
|
|
392
|
+
* family's curated palette, 0 to 11. Absent, the colour comes from a hash of the name, so a cast needs no
|
|
393
|
+
* setup; renaming a character stamps the old name's slot here, so they keep their colour. Authoring only
|
|
394
|
+
* (not shipped in the runtime bundle). */
|
|
395
|
+
colour?: number;
|
|
395
396
|
gameData?: GameData;
|
|
396
397
|
}
|
|
397
398
|
/** A speaker qualifier (a screenplay's character extension): `V.O.`, `O.S.`, `RADIO`, or the project's own.
|
|
@@ -435,12 +436,12 @@ interface BundleQualifier {
|
|
|
435
436
|
gameId: string;
|
|
436
437
|
name: string;
|
|
437
438
|
}
|
|
438
|
-
/** The cast as it reaches a compiled bundle: the player-facing fields only. `notes`, `actor
|
|
439
|
-
* `gender` are authoring / production / translation context, and the compiler drops them, so a shipped
|
|
439
|
+
/** The cast as it reaches a compiled bundle: the player-facing fields only. `notes`, `actor`,
|
|
440
|
+
* `gender` and `colour` are authoring / production / translation context, and the compiler drops them, so a shipped
|
|
440
441
|
* game never carries a real person's name or a writer's private notes. The compiler copies the shipping
|
|
441
442
|
* fields across explicitly (an allow-list), which is what actually keeps a new authoring field out of
|
|
442
443
|
* the bundle; this type states the resulting contract for anyone reading a bundle. */
|
|
443
|
-
type BundleCastMember = Omit<CastMember, "notes" | "actor" | "gender">;
|
|
444
|
+
type BundleCastMember = Omit<CastMember, "notes" | "actor" | "gender" | "colour">;
|
|
444
445
|
/** A node TYPE that can carry author-defined gameData fields (the gameData schema, project-level).
|
|
445
446
|
* Beat kinds map straight through: dialogue = `line`, text = `text`, game event = `gameEvent`.
|
|
446
447
|
* `option` is a choice's option: a group that is a direct child of a `choice` group, whose gameData the
|
|
@@ -700,11 +701,10 @@ interface ProjectFile {
|
|
|
700
701
|
gameDataFields?: GameDataFields;
|
|
701
702
|
/**
|
|
702
703
|
* The Patter extensions this project takes, by id (ruled 2026-10-18: the project opts in), each pinned to a
|
|
703
|
-
* version
|
|
704
|
-
*
|
|
705
|
-
*
|
|
706
|
-
*
|
|
707
|
-
* is a warning, and its data is left untouched.
|
|
704
|
+
* version. The manifest itself sits in `extensions/<id>.extension.json`, and the data in `.patterextension`
|
|
705
|
+
* shards. Authoring config: the bundle carries each one's compiled declarations and values, never this
|
|
706
|
+
* block itself. An extension named here whose manifest is missing is a warning, and its data is left
|
|
707
|
+
* untouched.
|
|
708
708
|
*/
|
|
709
709
|
extensions?: Record<string, ProjectExtension>;
|
|
710
710
|
/** Ordered writing-status ladder (not-done -> done); default `DEFAULT_WRITING_STATUSES`. */
|
|
@@ -1092,6 +1092,13 @@ interface Bundle {
|
|
|
1092
1092
|
default: string;
|
|
1093
1093
|
included: string[];
|
|
1094
1094
|
};
|
|
1095
|
+
/** Where a flow opened without a scene starts: the project's authored start (scene id, and block id when
|
|
1096
|
+
* it names one). Absent when the project sets none, or names one that has gone: every runtime then starts
|
|
1097
|
+
* at the first scene. */
|
|
1098
|
+
start?: {
|
|
1099
|
+
scene: string;
|
|
1100
|
+
block?: string;
|
|
1101
|
+
};
|
|
1095
1102
|
/** Player-facing cast only: the compiler strips notes / actor / gender (see `BundleCastMember`). */
|
|
1096
1103
|
cast?: BundleCastMember[];
|
|
1097
1104
|
/** The speaker qualifiers the content uses, in the project's order. Absent when no line has one, so a
|
|
@@ -1113,9 +1120,9 @@ interface Bundle {
|
|
|
1113
1120
|
gameDataFields?: GameDataFields;
|
|
1114
1121
|
/**
|
|
1115
1122
|
* The extensions the project takes, by id: each one's version and its compiled declarations by node kind,
|
|
1116
|
-
* every default resolved (what `extensionDecls` reads), the project node's own values
|
|
1117
|
-
*
|
|
1118
|
-
*
|
|
1123
|
+
* every default resolved (what `extensionDecls` reads), and the project node's own values. A node's values
|
|
1124
|
+
* sit on the node, under `extensions`. Absent when the project takes none, so a bundle without them is byte
|
|
1125
|
+
* for byte what it was.
|
|
1119
1126
|
*/
|
|
1120
1127
|
extensions?: Record<string, BundleExtension>;
|
|
1121
1128
|
scenes: Record<string, CompiledScene>;
|
|
@@ -1155,7 +1162,7 @@ declare const DEFAULT_CAPTION_DELIMITERS: CaptionDelimiters;
|
|
|
1155
1162
|
declare const DEFAULT_CAPTION_CHARACTER = "SFX";
|
|
1156
1163
|
declare const SAVE_SCHEMA = "patter/save@0";
|
|
1157
1164
|
/** The `save.version` inside the envelope. Bumped only when a reader would MISREAD an older save. */
|
|
1158
|
-
declare const SAVE_VERSION =
|
|
1165
|
+
declare const SAVE_VERSION = 4;
|
|
1159
1166
|
/** The tagged envelope a host stores: `serializeState` writes it, `deserializeState` refuses anything else. */
|
|
1160
1167
|
interface SaveEnvelope {
|
|
1161
1168
|
schema: typeof SAVE_SCHEMA;
|
|
@@ -1182,8 +1189,11 @@ interface StackFrame {
|
|
|
1182
1189
|
* restore against an EDITED bundle re-finds the position by id. Absent when the frame sat at its
|
|
1183
1190
|
* container's end (no next child), or in an older save. */
|
|
1184
1191
|
nextId?: string;
|
|
1192
|
+
/** SNAPSHOT-ONLY: on a frame whose container is an option of a choice, that choice group's id, so a load
|
|
1193
|
+
* whose option has gone offers the choice again. Absent on every other frame, and in a version 3 save. */
|
|
1194
|
+
choiceId?: string;
|
|
1185
1195
|
}
|
|
1186
|
-
/**
|
|
1196
|
+
/** A prompt as the choice showed it: a replayed prompt still to be spoken (`FlowCursor.pendingPrompt`). */
|
|
1187
1197
|
interface SavedChoicePrompt {
|
|
1188
1198
|
kind: "line" | "text";
|
|
1189
1199
|
text: string;
|
|
@@ -1197,10 +1207,12 @@ interface SavedChoicePrompt {
|
|
|
1197
1207
|
/** The prompt's resolved pause (line padding). Absent in a save written before it existed. */
|
|
1198
1208
|
padAfter?: number;
|
|
1199
1209
|
}
|
|
1200
|
-
/** One option of a pending choice,
|
|
1210
|
+
/** One option of a pending choice: which option, and whether it could be taken, saved VERBATIM, since
|
|
1211
|
+
* re-deriving on load would re-evaluate conditions. Its prompt is not saved: it is built again in the
|
|
1212
|
+
* language in use each time the choice is delivered. (A version 3 save's option also has a `prompt`,
|
|
1213
|
+
* which a load discards.) */
|
|
1201
1214
|
interface SavedChoiceOption {
|
|
1202
1215
|
id: string;
|
|
1203
|
-
prompt?: SavedChoicePrompt;
|
|
1204
1216
|
eligible: boolean;
|
|
1205
1217
|
gameData?: GameData;
|
|
1206
1218
|
}
|
|
@@ -1216,17 +1228,21 @@ interface FlowCursor {
|
|
|
1216
1228
|
/** The continuation stack (call frames + the active block run), root first. */
|
|
1217
1229
|
stack: StackFrame[];
|
|
1218
1230
|
activeSnippetId: string | null;
|
|
1219
|
-
|
|
1231
|
+
/** The id of the next beat the active snippet delivers, so a load against an edited bundle finds its
|
|
1232
|
+
* place by id. Absent when no snippet is active or the active one has delivered every beat. */
|
|
1233
|
+
beatId?: string;
|
|
1234
|
+
/** Version 3 only, read and never written: the index of the next beat in the active snippet. */
|
|
1235
|
+
beatIndex?: number;
|
|
1220
1236
|
/** Present (non-null) iff the flow is stopped at a choice. */
|
|
1221
1237
|
pendingChoice: SavedChoice | null;
|
|
1222
1238
|
/** The chosen option owning a prompt still to be replayed (a save taken between choose + advance).
|
|
1223
1239
|
* Optional / null in older saves -> no pending prompt. */
|
|
1224
1240
|
pendingPromptOwnerId?: string | null;
|
|
1225
|
-
/** The prompt still to be replayed, exactly as the choice SHOWED it (text and speaker fields, the
|
|
1226
|
-
*
|
|
1227
|
-
* alongside a `pendingPromptOwnerId` (the choose -> advance window, with
|
|
1228
|
-
* absent otherwise. A save without it (written before Patterplay 0.18.0)
|
|
1229
|
-
* when it is delivered, as before. */
|
|
1241
|
+
/** The prompt still to be replayed, exactly as the choice SHOWED it (text and speaker fields), so the
|
|
1242
|
+
* replay after a load says what the player saw, in the language they saw it in: the one prompt a save
|
|
1243
|
+
* keeps as text. Written only alongside a `pendingPromptOwnerId` (the choose -> advance window, with
|
|
1244
|
+
* `replayPromptOnChoose`), and absent otherwise. A save without it (written before Patterplay 0.18.0)
|
|
1245
|
+
* resolves the owner's prompt beat when it is delivered, as before. */
|
|
1230
1246
|
pendingPrompt?: SavedChoicePrompt;
|
|
1231
1247
|
/** This flow's (non-shared) selector cursors, keyed by group id. */
|
|
1232
1248
|
selectors: Record<string, SelectorSnapshot>;
|
|
@@ -1239,10 +1255,10 @@ interface FlowSnapshot {
|
|
|
1239
1255
|
visits: Record<string, number>;
|
|
1240
1256
|
cursor: FlowCursor;
|
|
1241
1257
|
}
|
|
1242
|
-
/** A full resumable save-game (version
|
|
1258
|
+
/** A full resumable save-game (version 4): everything that is not a property, plus the registry's
|
|
1243
1259
|
* values when the engine made its own registry. */
|
|
1244
1260
|
interface SaveGame {
|
|
1245
|
-
version:
|
|
1261
|
+
version: typeof SAVE_VERSION;
|
|
1246
1262
|
/** The engine's own registry's values, keyed by registry key: present only when the engine made the
|
|
1247
1263
|
* registry itself (a standalone game). A game that passed a registry saves it once, beside this. */
|
|
1248
1264
|
registry?: EngineSave;
|
|
@@ -1253,17 +1269,18 @@ interface SaveGame {
|
|
|
1253
1269
|
/** Each live flow's snapshot, keyed by flow id. */
|
|
1254
1270
|
flows: Record<string, FlowSnapshot>;
|
|
1255
1271
|
}
|
|
1256
|
-
/**
|
|
1257
|
-
* `
|
|
1272
|
+
/** A version 3 save, still read: the same shape apart from the cursor (`beatIndex` for `beatId`, no
|
|
1273
|
+
* `choiceId` on its frames) and a pending choice's options (each with its prompt text, discarded). */
|
|
1274
|
+
interface SaveGameV3 extends Omit<SaveGame, "version"> {
|
|
1275
|
+
version: 3;
|
|
1276
|
+
}
|
|
1277
|
+
/** One flow's own property values, without its id: what a `FlowState` carries beside its snapshot. */
|
|
1258
1278
|
interface FlowValues {
|
|
1259
1279
|
/** The NOT-shared `@patter` globals, under token "patter". */
|
|
1260
1280
|
scopes: EngineSave;
|
|
1261
1281
|
/** Per-scene NOT-shared `@scene` bags (scene id -> name -> value). */
|
|
1262
1282
|
sceneBags: Record<string, Record<string, ScalarValue>>;
|
|
1263
1283
|
}
|
|
1264
|
-
/** A version 2 flow snapshot, which carried the flow's property values itself. Still read. */
|
|
1265
|
-
interface FlowSnapshotV2 extends FlowSnapshot, FlowValues {
|
|
1266
|
-
}
|
|
1267
1284
|
/**
|
|
1268
1285
|
* One flow taken out of an engine (`engine.captureFlow`) to be put back later (`engine.restoreFlow`), under the
|
|
1269
1286
|
* same id or another: its snapshot as a save writes it, and its own property values without its id. Plain data
|
|
@@ -1271,19 +1288,8 @@ interface FlowSnapshotV2 extends FlowSnapshot, FlowValues {
|
|
|
1271
1288
|
* visit counts, shared selectors) is never in it, so restoring one rewinds nothing else.
|
|
1272
1289
|
*/
|
|
1273
1290
|
interface FlowState extends FlowSnapshot, FlowValues {
|
|
1274
|
-
version
|
|
1275
|
-
|
|
1276
|
-
/** A version 2 save, from before the registry held the properties. Every runtime still reads it: its
|
|
1277
|
-
* property sections move into the registry (under the keys in the header above) as it loads. */
|
|
1278
|
-
interface SaveGameV2 {
|
|
1279
|
-
version: 2;
|
|
1280
|
-
/** Shared `@patter` globals (owned scope "patter"). */
|
|
1281
|
-
shared: EngineSave;
|
|
1282
|
-
sharedVisits: Record<string, number>;
|
|
1283
|
-
sharedSelectors: Record<string, SelectorSnapshot>;
|
|
1284
|
-
/** Shared, scene-namespaced `@scene` bags (scene id -> name -> value). */
|
|
1285
|
-
stageBags: Record<string, Record<string, ScalarValue>>;
|
|
1286
|
-
flows: Record<string, FlowSnapshotV2>;
|
|
1291
|
+
/** `SAVE_VERSION` when written; a version 3 state still restores. */
|
|
1292
|
+
version: typeof SAVE_VERSION | 3;
|
|
1287
1293
|
}
|
|
1288
1294
|
/** Where a project keeps its shards unless its `layout` says otherwise, relative to the project root. */
|
|
1289
1295
|
declare const DEFAULT_LAYOUT: {
|
|
@@ -1329,12 +1335,12 @@ declare const MANIFEST_EXTENSION = ".extension.json";
|
|
|
1329
1335
|
* folder, so a merge driver handed one shard's path can always find the manifest. */
|
|
1330
1336
|
declare const EXTENSIONS_DIR = "extensions";
|
|
1331
1337
|
/**
|
|
1332
|
-
* The extensions a project takes (`ProjectFile.extensions`), one each: the version it is pinned to
|
|
1333
|
-
* settings
|
|
1338
|
+
* The extensions a project takes (`ProjectFile.extensions`), one each: the version it is pinned to. An older
|
|
1339
|
+
* pin may still carry `settings`, which named the host fields claims presented; claims and settings are gone
|
|
1340
|
+
* from the extensions spec (2026-10-20), so they're ignored, and `patter validate` says so.
|
|
1334
1341
|
*/
|
|
1335
1342
|
interface ProjectExtension {
|
|
1336
1343
|
version: string;
|
|
1337
|
-
settings?: Record<string, string>;
|
|
1338
1344
|
}
|
|
1339
1345
|
/**
|
|
1340
1346
|
* One extension's data for one scene, or for the project (`scene: "@project"`).
|
|
@@ -1366,13 +1372,6 @@ interface BundleExtension {
|
|
|
1366
1372
|
fields: Record<string, ExtensionFieldDecl[]>;
|
|
1367
1373
|
/** The project node's values, raw, when it has any. */
|
|
1368
1374
|
project?: Record<string, unknown>;
|
|
1369
|
-
/**
|
|
1370
|
-
* Every setting the manifest declares, by setting name, keys sorted: the project's value (`ProjectExtension.
|
|
1371
|
-
* settings`), or else the setting's default (`@wildwinter/toolkit/extensions`' `settingValues`). A setting
|
|
1372
|
-
* names a host field, so a game reads here which gameData field holds what the extension claims. Present
|
|
1373
|
-
* only when the manifest declares settings.
|
|
1374
|
-
*/
|
|
1375
|
-
settings?: Record<string, string>;
|
|
1376
1375
|
}
|
|
1377
1376
|
/**
|
|
1378
1377
|
* A compiled extension field declaration (`@wildwinter/toolkit/extensions`' FieldDecl, less the editor's
|
|
@@ -1402,4 +1401,4 @@ interface ExtensionFieldDecl {
|
|
|
1402
1401
|
/** A node's extension values in a bundle: extension id -> field -> value, raw. */
|
|
1403
1402
|
type NodeExtensions = Record<string, Record<string, unknown>>;
|
|
1404
1403
|
|
|
1405
|
-
export { AUTHORING_SCHEMA, type AuthoringFile, type Beat, type Block, type Bundle, type BundleCastMember, type BundleExtension, type BundleQualifier, COMMON_GENDERS, type CaptionDelimiters, type CastMember, type Comment, type CommentMessage, type CommentRange, type CompiledBlock, type CompiledEffect, type CompiledGroup, type CompiledScene, type CompiledSnippet, type CoverageDriver, DEFAULT_CAPTION_CHARACTER, DEFAULT_CAPTION_DELIMITERS, DEFAULT_DOCUMENTATION_CLASSES, DEFAULT_LAYOUT, DEFAULT_PAD_AFTER, DEFAULT_QUALIFIERS, DEFAULT_RECORDING_STATUSES, DEFAULT_SPEAKER_PATTERN, DEFAULT_WRITING_STATUSES, type DocLine, type DocumentationClass, EXTENSIONS_DIR, EXTENSION_SCHEMA, EXTENSION_SHARD, type EditRecord, type Effect, type EngineSave, type EstimatingConfig, type Expression, type ExtensionFieldDecl, type ExtensionShard, FLOW_SCHEMA, type FlowCursor, type FlowFile, type FlowNode, type FlowSnapshot, type
|
|
1404
|
+
export { AUTHORING_SCHEMA, type AuthoringFile, type Beat, type Block, type Bundle, type BundleCastMember, type BundleExtension, type BundleQualifier, COMMON_GENDERS, type CaptionDelimiters, type CastMember, type Comment, type CommentMessage, type CommentRange, type CompiledBlock, type CompiledEffect, type CompiledGroup, type CompiledScene, type CompiledSnippet, type CoverageDriver, DEFAULT_CAPTION_CHARACTER, DEFAULT_CAPTION_DELIMITERS, DEFAULT_DOCUMENTATION_CLASSES, DEFAULT_LAYOUT, DEFAULT_PAD_AFTER, DEFAULT_QUALIFIERS, DEFAULT_RECORDING_STATUSES, DEFAULT_SPEAKER_PATTERN, DEFAULT_WRITING_STATUSES, type DocLine, type DocumentationClass, EXTENSIONS_DIR, EXTENSION_SCHEMA, EXTENSION_SHARD, type EditRecord, type Effect, type EngineSave, type EstimatingConfig, type Expression, type ExtensionFieldDecl, type ExtensionShard, FLOW_SCHEMA, type FlowCursor, type FlowFile, type FlowNode, type FlowSnapshot, type FlowState, type FlowValues, type GameData, type GameDataField, type GameDataFieldType, type GameDataFields, type GameDataNodeKind, type GameEventBeat, type GrammaticalGender, type Group, HANDOFF_SCHEMA, type HandoffFile, type HandoffImport, type HandoffLine, type HandoffRow, type HostScopeDecl, type HostScopeRegistry, type HostScopeSpec, type Jump, type JumpTarget, type LineBeat, type LocaleFile, MANIFEST_EXTENSION, type NodeExtensions, PAD_AFTER_MAX, PAD_AFTER_MIN, PROJECT_EXTENSION_STEM, PROJECT_LOCALE_SCENE, PROJECT_SCHEMA, type ProjectDictionary, type ProjectExtension, type ProjectFile, type ProjectLayout, type PromptBeat, type PropertyDecl, type PropertyType, RERECORD_STATUS, RERECORD_STATUS_DECL, type RecordingFolder, type RecordingStatusDecl, SAVE_SCHEMA, SAVE_VERSION, SPEAKER_PATTERN_KEY, STRINGS_SCHEMA, type SaveEnvelope, type SaveGame, type SaveGameV3, type SavedChoice, type SavedChoiceOption, type SavedChoicePrompt, type ScalarValue, type Scene, type Selector, type SelectorExhaust, type SelectorOrder, type SelectorSnapshot, type SequenceOptions, type Snippet, type SpeakerQualifier, type StackFrame, type Suggestion, type SuggestionSource, type TextBeat, UNRESOLVED_KEY, type VcsKind, type WritingStatusDecl, castStringKey, deriveRecordingFolders, effectiveGameId, formatSpeakerLabel, isContentlessBeat, isDialogueScene, projectLayout, projectQualifiers, qualifierStringKey, resolveSceneRef, sceneAddressIndex, speakerLabelKey, textIsAction, usedQualifiers, usedSpeakerPairs, walkNodes };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AstNode } from '@wildwinter/expr';
|
|
2
2
|
export { RESERVED_PROPERTY_NAMES, isCaseOnlyPropertyName, isValidPropertyName, propertyNameify } from '@wildwinter/expr';
|
|
3
|
+
export { gameIdify, isValidGameId } from '@wildwinter/toolkit';
|
|
3
4
|
|
|
4
5
|
type ScalarValue = boolean | number | string | string[];
|
|
5
6
|
/** Developer-defined host metadata (spec §17). Opaque to Patter. */
|
|
@@ -246,11 +247,6 @@ declare function walkNodes<N extends {
|
|
|
246
247
|
* just `{ jump }` with zero beats - which is valid.
|
|
247
248
|
*/
|
|
248
249
|
declare function isContentlessBeat(beat: Beat, hasText: boolean): boolean;
|
|
249
|
-
/** Slugify a name into a hyphen-form game id: lowercase, drop apostrophes, runs of
|
|
250
|
-
* other punctuation -> a single hyphen, collapse repeats, no leading / trailing hyphen. */
|
|
251
|
-
declare function gameIdify(text: string): string;
|
|
252
|
-
/** A valid authored game id: lowercase alphanumerics + hyphens, no leading / trailing hyphen. */
|
|
253
|
-
declare function isValidGameId(gameId: string): boolean;
|
|
254
250
|
|
|
255
251
|
/** The effective address: the explicit `gameId` if pinned, else derived from `name`. */
|
|
256
252
|
declare function effectiveGameId(entity: {
|
|
@@ -392,6 +388,11 @@ interface CastMember {
|
|
|
392
388
|
* (`{ vo: "Your thoughts" }`), where the project's speaker pattern shouldn't apply. Localised as the
|
|
393
389
|
* `speaker:<name>:<gameId>` string (`speakerLabelKey`). Absent for every pair that follows the pattern. */
|
|
394
390
|
qualifierLabels?: Record<string, string>;
|
|
391
|
+
/** The character's colour in the editors (their cue, the play window, the readable script): a slot of the
|
|
392
|
+
* family's curated palette, 0 to 11. Absent, the colour comes from a hash of the name, so a cast needs no
|
|
393
|
+
* setup; renaming a character stamps the old name's slot here, so they keep their colour. Authoring only
|
|
394
|
+
* (not shipped in the runtime bundle). */
|
|
395
|
+
colour?: number;
|
|
395
396
|
gameData?: GameData;
|
|
396
397
|
}
|
|
397
398
|
/** A speaker qualifier (a screenplay's character extension): `V.O.`, `O.S.`, `RADIO`, or the project's own.
|
|
@@ -435,12 +436,12 @@ interface BundleQualifier {
|
|
|
435
436
|
gameId: string;
|
|
436
437
|
name: string;
|
|
437
438
|
}
|
|
438
|
-
/** The cast as it reaches a compiled bundle: the player-facing fields only. `notes`, `actor
|
|
439
|
-
* `gender` are authoring / production / translation context, and the compiler drops them, so a shipped
|
|
439
|
+
/** The cast as it reaches a compiled bundle: the player-facing fields only. `notes`, `actor`,
|
|
440
|
+
* `gender` and `colour` are authoring / production / translation context, and the compiler drops them, so a shipped
|
|
440
441
|
* game never carries a real person's name or a writer's private notes. The compiler copies the shipping
|
|
441
442
|
* fields across explicitly (an allow-list), which is what actually keeps a new authoring field out of
|
|
442
443
|
* the bundle; this type states the resulting contract for anyone reading a bundle. */
|
|
443
|
-
type BundleCastMember = Omit<CastMember, "notes" | "actor" | "gender">;
|
|
444
|
+
type BundleCastMember = Omit<CastMember, "notes" | "actor" | "gender" | "colour">;
|
|
444
445
|
/** A node TYPE that can carry author-defined gameData fields (the gameData schema, project-level).
|
|
445
446
|
* Beat kinds map straight through: dialogue = `line`, text = `text`, game event = `gameEvent`.
|
|
446
447
|
* `option` is a choice's option: a group that is a direct child of a `choice` group, whose gameData the
|
|
@@ -700,11 +701,10 @@ interface ProjectFile {
|
|
|
700
701
|
gameDataFields?: GameDataFields;
|
|
701
702
|
/**
|
|
702
703
|
* The Patter extensions this project takes, by id (ruled 2026-10-18: the project opts in), each pinned to a
|
|
703
|
-
* version
|
|
704
|
-
*
|
|
705
|
-
*
|
|
706
|
-
*
|
|
707
|
-
* is a warning, and its data is left untouched.
|
|
704
|
+
* version. The manifest itself sits in `extensions/<id>.extension.json`, and the data in `.patterextension`
|
|
705
|
+
* shards. Authoring config: the bundle carries each one's compiled declarations and values, never this
|
|
706
|
+
* block itself. An extension named here whose manifest is missing is a warning, and its data is left
|
|
707
|
+
* untouched.
|
|
708
708
|
*/
|
|
709
709
|
extensions?: Record<string, ProjectExtension>;
|
|
710
710
|
/** Ordered writing-status ladder (not-done -> done); default `DEFAULT_WRITING_STATUSES`. */
|
|
@@ -1092,6 +1092,13 @@ interface Bundle {
|
|
|
1092
1092
|
default: string;
|
|
1093
1093
|
included: string[];
|
|
1094
1094
|
};
|
|
1095
|
+
/** Where a flow opened without a scene starts: the project's authored start (scene id, and block id when
|
|
1096
|
+
* it names one). Absent when the project sets none, or names one that has gone: every runtime then starts
|
|
1097
|
+
* at the first scene. */
|
|
1098
|
+
start?: {
|
|
1099
|
+
scene: string;
|
|
1100
|
+
block?: string;
|
|
1101
|
+
};
|
|
1095
1102
|
/** Player-facing cast only: the compiler strips notes / actor / gender (see `BundleCastMember`). */
|
|
1096
1103
|
cast?: BundleCastMember[];
|
|
1097
1104
|
/** The speaker qualifiers the content uses, in the project's order. Absent when no line has one, so a
|
|
@@ -1113,9 +1120,9 @@ interface Bundle {
|
|
|
1113
1120
|
gameDataFields?: GameDataFields;
|
|
1114
1121
|
/**
|
|
1115
1122
|
* The extensions the project takes, by id: each one's version and its compiled declarations by node kind,
|
|
1116
|
-
* every default resolved (what `extensionDecls` reads), the project node's own values
|
|
1117
|
-
*
|
|
1118
|
-
*
|
|
1123
|
+
* every default resolved (what `extensionDecls` reads), and the project node's own values. A node's values
|
|
1124
|
+
* sit on the node, under `extensions`. Absent when the project takes none, so a bundle without them is byte
|
|
1125
|
+
* for byte what it was.
|
|
1119
1126
|
*/
|
|
1120
1127
|
extensions?: Record<string, BundleExtension>;
|
|
1121
1128
|
scenes: Record<string, CompiledScene>;
|
|
@@ -1155,7 +1162,7 @@ declare const DEFAULT_CAPTION_DELIMITERS: CaptionDelimiters;
|
|
|
1155
1162
|
declare const DEFAULT_CAPTION_CHARACTER = "SFX";
|
|
1156
1163
|
declare const SAVE_SCHEMA = "patter/save@0";
|
|
1157
1164
|
/** The `save.version` inside the envelope. Bumped only when a reader would MISREAD an older save. */
|
|
1158
|
-
declare const SAVE_VERSION =
|
|
1165
|
+
declare const SAVE_VERSION = 4;
|
|
1159
1166
|
/** The tagged envelope a host stores: `serializeState` writes it, `deserializeState` refuses anything else. */
|
|
1160
1167
|
interface SaveEnvelope {
|
|
1161
1168
|
schema: typeof SAVE_SCHEMA;
|
|
@@ -1182,8 +1189,11 @@ interface StackFrame {
|
|
|
1182
1189
|
* restore against an EDITED bundle re-finds the position by id. Absent when the frame sat at its
|
|
1183
1190
|
* container's end (no next child), or in an older save. */
|
|
1184
1191
|
nextId?: string;
|
|
1192
|
+
/** SNAPSHOT-ONLY: on a frame whose container is an option of a choice, that choice group's id, so a load
|
|
1193
|
+
* whose option has gone offers the choice again. Absent on every other frame, and in a version 3 save. */
|
|
1194
|
+
choiceId?: string;
|
|
1185
1195
|
}
|
|
1186
|
-
/**
|
|
1196
|
+
/** A prompt as the choice showed it: a replayed prompt still to be spoken (`FlowCursor.pendingPrompt`). */
|
|
1187
1197
|
interface SavedChoicePrompt {
|
|
1188
1198
|
kind: "line" | "text";
|
|
1189
1199
|
text: string;
|
|
@@ -1197,10 +1207,12 @@ interface SavedChoicePrompt {
|
|
|
1197
1207
|
/** The prompt's resolved pause (line padding). Absent in a save written before it existed. */
|
|
1198
1208
|
padAfter?: number;
|
|
1199
1209
|
}
|
|
1200
|
-
/** One option of a pending choice,
|
|
1210
|
+
/** One option of a pending choice: which option, and whether it could be taken, saved VERBATIM, since
|
|
1211
|
+
* re-deriving on load would re-evaluate conditions. Its prompt is not saved: it is built again in the
|
|
1212
|
+
* language in use each time the choice is delivered. (A version 3 save's option also has a `prompt`,
|
|
1213
|
+
* which a load discards.) */
|
|
1201
1214
|
interface SavedChoiceOption {
|
|
1202
1215
|
id: string;
|
|
1203
|
-
prompt?: SavedChoicePrompt;
|
|
1204
1216
|
eligible: boolean;
|
|
1205
1217
|
gameData?: GameData;
|
|
1206
1218
|
}
|
|
@@ -1216,17 +1228,21 @@ interface FlowCursor {
|
|
|
1216
1228
|
/** The continuation stack (call frames + the active block run), root first. */
|
|
1217
1229
|
stack: StackFrame[];
|
|
1218
1230
|
activeSnippetId: string | null;
|
|
1219
|
-
|
|
1231
|
+
/** The id of the next beat the active snippet delivers, so a load against an edited bundle finds its
|
|
1232
|
+
* place by id. Absent when no snippet is active or the active one has delivered every beat. */
|
|
1233
|
+
beatId?: string;
|
|
1234
|
+
/** Version 3 only, read and never written: the index of the next beat in the active snippet. */
|
|
1235
|
+
beatIndex?: number;
|
|
1220
1236
|
/** Present (non-null) iff the flow is stopped at a choice. */
|
|
1221
1237
|
pendingChoice: SavedChoice | null;
|
|
1222
1238
|
/** The chosen option owning a prompt still to be replayed (a save taken between choose + advance).
|
|
1223
1239
|
* Optional / null in older saves -> no pending prompt. */
|
|
1224
1240
|
pendingPromptOwnerId?: string | null;
|
|
1225
|
-
/** The prompt still to be replayed, exactly as the choice SHOWED it (text and speaker fields, the
|
|
1226
|
-
*
|
|
1227
|
-
* alongside a `pendingPromptOwnerId` (the choose -> advance window, with
|
|
1228
|
-
* absent otherwise. A save without it (written before Patterplay 0.18.0)
|
|
1229
|
-
* when it is delivered, as before. */
|
|
1241
|
+
/** The prompt still to be replayed, exactly as the choice SHOWED it (text and speaker fields), so the
|
|
1242
|
+
* replay after a load says what the player saw, in the language they saw it in: the one prompt a save
|
|
1243
|
+
* keeps as text. Written only alongside a `pendingPromptOwnerId` (the choose -> advance window, with
|
|
1244
|
+
* `replayPromptOnChoose`), and absent otherwise. A save without it (written before Patterplay 0.18.0)
|
|
1245
|
+
* resolves the owner's prompt beat when it is delivered, as before. */
|
|
1230
1246
|
pendingPrompt?: SavedChoicePrompt;
|
|
1231
1247
|
/** This flow's (non-shared) selector cursors, keyed by group id. */
|
|
1232
1248
|
selectors: Record<string, SelectorSnapshot>;
|
|
@@ -1239,10 +1255,10 @@ interface FlowSnapshot {
|
|
|
1239
1255
|
visits: Record<string, number>;
|
|
1240
1256
|
cursor: FlowCursor;
|
|
1241
1257
|
}
|
|
1242
|
-
/** A full resumable save-game (version
|
|
1258
|
+
/** A full resumable save-game (version 4): everything that is not a property, plus the registry's
|
|
1243
1259
|
* values when the engine made its own registry. */
|
|
1244
1260
|
interface SaveGame {
|
|
1245
|
-
version:
|
|
1261
|
+
version: typeof SAVE_VERSION;
|
|
1246
1262
|
/** The engine's own registry's values, keyed by registry key: present only when the engine made the
|
|
1247
1263
|
* registry itself (a standalone game). A game that passed a registry saves it once, beside this. */
|
|
1248
1264
|
registry?: EngineSave;
|
|
@@ -1253,17 +1269,18 @@ interface SaveGame {
|
|
|
1253
1269
|
/** Each live flow's snapshot, keyed by flow id. */
|
|
1254
1270
|
flows: Record<string, FlowSnapshot>;
|
|
1255
1271
|
}
|
|
1256
|
-
/**
|
|
1257
|
-
* `
|
|
1272
|
+
/** A version 3 save, still read: the same shape apart from the cursor (`beatIndex` for `beatId`, no
|
|
1273
|
+
* `choiceId` on its frames) and a pending choice's options (each with its prompt text, discarded). */
|
|
1274
|
+
interface SaveGameV3 extends Omit<SaveGame, "version"> {
|
|
1275
|
+
version: 3;
|
|
1276
|
+
}
|
|
1277
|
+
/** One flow's own property values, without its id: what a `FlowState` carries beside its snapshot. */
|
|
1258
1278
|
interface FlowValues {
|
|
1259
1279
|
/** The NOT-shared `@patter` globals, under token "patter". */
|
|
1260
1280
|
scopes: EngineSave;
|
|
1261
1281
|
/** Per-scene NOT-shared `@scene` bags (scene id -> name -> value). */
|
|
1262
1282
|
sceneBags: Record<string, Record<string, ScalarValue>>;
|
|
1263
1283
|
}
|
|
1264
|
-
/** A version 2 flow snapshot, which carried the flow's property values itself. Still read. */
|
|
1265
|
-
interface FlowSnapshotV2 extends FlowSnapshot, FlowValues {
|
|
1266
|
-
}
|
|
1267
1284
|
/**
|
|
1268
1285
|
* One flow taken out of an engine (`engine.captureFlow`) to be put back later (`engine.restoreFlow`), under the
|
|
1269
1286
|
* same id or another: its snapshot as a save writes it, and its own property values without its id. Plain data
|
|
@@ -1271,19 +1288,8 @@ interface FlowSnapshotV2 extends FlowSnapshot, FlowValues {
|
|
|
1271
1288
|
* visit counts, shared selectors) is never in it, so restoring one rewinds nothing else.
|
|
1272
1289
|
*/
|
|
1273
1290
|
interface FlowState extends FlowSnapshot, FlowValues {
|
|
1274
|
-
version
|
|
1275
|
-
|
|
1276
|
-
/** A version 2 save, from before the registry held the properties. Every runtime still reads it: its
|
|
1277
|
-
* property sections move into the registry (under the keys in the header above) as it loads. */
|
|
1278
|
-
interface SaveGameV2 {
|
|
1279
|
-
version: 2;
|
|
1280
|
-
/** Shared `@patter` globals (owned scope "patter"). */
|
|
1281
|
-
shared: EngineSave;
|
|
1282
|
-
sharedVisits: Record<string, number>;
|
|
1283
|
-
sharedSelectors: Record<string, SelectorSnapshot>;
|
|
1284
|
-
/** Shared, scene-namespaced `@scene` bags (scene id -> name -> value). */
|
|
1285
|
-
stageBags: Record<string, Record<string, ScalarValue>>;
|
|
1286
|
-
flows: Record<string, FlowSnapshotV2>;
|
|
1291
|
+
/** `SAVE_VERSION` when written; a version 3 state still restores. */
|
|
1292
|
+
version: typeof SAVE_VERSION | 3;
|
|
1287
1293
|
}
|
|
1288
1294
|
/** Where a project keeps its shards unless its `layout` says otherwise, relative to the project root. */
|
|
1289
1295
|
declare const DEFAULT_LAYOUT: {
|
|
@@ -1329,12 +1335,12 @@ declare const MANIFEST_EXTENSION = ".extension.json";
|
|
|
1329
1335
|
* folder, so a merge driver handed one shard's path can always find the manifest. */
|
|
1330
1336
|
declare const EXTENSIONS_DIR = "extensions";
|
|
1331
1337
|
/**
|
|
1332
|
-
* The extensions a project takes (`ProjectFile.extensions`), one each: the version it is pinned to
|
|
1333
|
-
* settings
|
|
1338
|
+
* The extensions a project takes (`ProjectFile.extensions`), one each: the version it is pinned to. An older
|
|
1339
|
+
* pin may still carry `settings`, which named the host fields claims presented; claims and settings are gone
|
|
1340
|
+
* from the extensions spec (2026-10-20), so they're ignored, and `patter validate` says so.
|
|
1334
1341
|
*/
|
|
1335
1342
|
interface ProjectExtension {
|
|
1336
1343
|
version: string;
|
|
1337
|
-
settings?: Record<string, string>;
|
|
1338
1344
|
}
|
|
1339
1345
|
/**
|
|
1340
1346
|
* One extension's data for one scene, or for the project (`scene: "@project"`).
|
|
@@ -1366,13 +1372,6 @@ interface BundleExtension {
|
|
|
1366
1372
|
fields: Record<string, ExtensionFieldDecl[]>;
|
|
1367
1373
|
/** The project node's values, raw, when it has any. */
|
|
1368
1374
|
project?: Record<string, unknown>;
|
|
1369
|
-
/**
|
|
1370
|
-
* Every setting the manifest declares, by setting name, keys sorted: the project's value (`ProjectExtension.
|
|
1371
|
-
* settings`), or else the setting's default (`@wildwinter/toolkit/extensions`' `settingValues`). A setting
|
|
1372
|
-
* names a host field, so a game reads here which gameData field holds what the extension claims. Present
|
|
1373
|
-
* only when the manifest declares settings.
|
|
1374
|
-
*/
|
|
1375
|
-
settings?: Record<string, string>;
|
|
1376
1375
|
}
|
|
1377
1376
|
/**
|
|
1378
1377
|
* A compiled extension field declaration (`@wildwinter/toolkit/extensions`' FieldDecl, less the editor's
|
|
@@ -1402,4 +1401,4 @@ interface ExtensionFieldDecl {
|
|
|
1402
1401
|
/** A node's extension values in a bundle: extension id -> field -> value, raw. */
|
|
1403
1402
|
type NodeExtensions = Record<string, Record<string, unknown>>;
|
|
1404
1403
|
|
|
1405
|
-
export { AUTHORING_SCHEMA, type AuthoringFile, type Beat, type Block, type Bundle, type BundleCastMember, type BundleExtension, type BundleQualifier, COMMON_GENDERS, type CaptionDelimiters, type CastMember, type Comment, type CommentMessage, type CommentRange, type CompiledBlock, type CompiledEffect, type CompiledGroup, type CompiledScene, type CompiledSnippet, type CoverageDriver, DEFAULT_CAPTION_CHARACTER, DEFAULT_CAPTION_DELIMITERS, DEFAULT_DOCUMENTATION_CLASSES, DEFAULT_LAYOUT, DEFAULT_PAD_AFTER, DEFAULT_QUALIFIERS, DEFAULT_RECORDING_STATUSES, DEFAULT_SPEAKER_PATTERN, DEFAULT_WRITING_STATUSES, type DocLine, type DocumentationClass, EXTENSIONS_DIR, EXTENSION_SCHEMA, EXTENSION_SHARD, type EditRecord, type Effect, type EngineSave, type EstimatingConfig, type Expression, type ExtensionFieldDecl, type ExtensionShard, FLOW_SCHEMA, type FlowCursor, type FlowFile, type FlowNode, type FlowSnapshot, type
|
|
1404
|
+
export { AUTHORING_SCHEMA, type AuthoringFile, type Beat, type Block, type Bundle, type BundleCastMember, type BundleExtension, type BundleQualifier, COMMON_GENDERS, type CaptionDelimiters, type CastMember, type Comment, type CommentMessage, type CommentRange, type CompiledBlock, type CompiledEffect, type CompiledGroup, type CompiledScene, type CompiledSnippet, type CoverageDriver, DEFAULT_CAPTION_CHARACTER, DEFAULT_CAPTION_DELIMITERS, DEFAULT_DOCUMENTATION_CLASSES, DEFAULT_LAYOUT, DEFAULT_PAD_AFTER, DEFAULT_QUALIFIERS, DEFAULT_RECORDING_STATUSES, DEFAULT_SPEAKER_PATTERN, DEFAULT_WRITING_STATUSES, type DocLine, type DocumentationClass, EXTENSIONS_DIR, EXTENSION_SCHEMA, EXTENSION_SHARD, type EditRecord, type Effect, type EngineSave, type EstimatingConfig, type Expression, type ExtensionFieldDecl, type ExtensionShard, FLOW_SCHEMA, type FlowCursor, type FlowFile, type FlowNode, type FlowSnapshot, type FlowState, type FlowValues, type GameData, type GameDataField, type GameDataFieldType, type GameDataFields, type GameDataNodeKind, type GameEventBeat, type GrammaticalGender, type Group, HANDOFF_SCHEMA, type HandoffFile, type HandoffImport, type HandoffLine, type HandoffRow, type HostScopeDecl, type HostScopeRegistry, type HostScopeSpec, type Jump, type JumpTarget, type LineBeat, type LocaleFile, MANIFEST_EXTENSION, type NodeExtensions, PAD_AFTER_MAX, PAD_AFTER_MIN, PROJECT_EXTENSION_STEM, PROJECT_LOCALE_SCENE, PROJECT_SCHEMA, type ProjectDictionary, type ProjectExtension, type ProjectFile, type ProjectLayout, type PromptBeat, type PropertyDecl, type PropertyType, RERECORD_STATUS, RERECORD_STATUS_DECL, type RecordingFolder, type RecordingStatusDecl, SAVE_SCHEMA, SAVE_VERSION, SPEAKER_PATTERN_KEY, STRINGS_SCHEMA, type SaveEnvelope, type SaveGame, type SaveGameV3, type SavedChoice, type SavedChoiceOption, type SavedChoicePrompt, type ScalarValue, type Scene, type Selector, type SelectorExhaust, type SelectorOrder, type SelectorSnapshot, type SequenceOptions, type Snippet, type SpeakerQualifier, type StackFrame, type Suggestion, type SuggestionSource, type TextBeat, UNRESOLVED_KEY, type VcsKind, type WritingStatusDecl, castStringKey, deriveRecordingFolders, effectiveGameId, formatSpeakerLabel, isContentlessBeat, isDialogueScene, projectLayout, projectQualifiers, qualifierStringKey, resolveSceneRef, sceneAddressIndex, speakerLabelKey, textIsAction, usedQualifiers, usedSpeakerPairs, walkNodes };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
+
import { gameIdify, isValidGameId } from "@wildwinter/toolkit";
|
|
2
3
|
import {
|
|
3
4
|
propertyNameify,
|
|
4
5
|
isValidPropertyName,
|
|
@@ -19,12 +20,6 @@ function isContentlessBeat(beat, hasText) {
|
|
|
19
20
|
if (beat.tags && beat.tags.length > 0) return false;
|
|
20
21
|
return beat.kind === "text" || !beat.character && !beat.direction;
|
|
21
22
|
}
|
|
22
|
-
function gameIdify(text) {
|
|
23
|
-
return text.toLowerCase().replace(/['’]/g, "").replace(/[^a-z0-9-]+/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
|
|
24
|
-
}
|
|
25
|
-
function isValidGameId(gameId) {
|
|
26
|
-
return /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(gameId);
|
|
27
|
-
}
|
|
28
23
|
function effectiveGameId(entity) {
|
|
29
24
|
const g = entity.gameId?.trim();
|
|
30
25
|
return g ? g : gameIdify(entity.name);
|
|
@@ -168,7 +163,7 @@ var HANDOFF_SCHEMA = "patter/handoff@0";
|
|
|
168
163
|
var DEFAULT_CAPTION_DELIMITERS = { open: "[", close: "]" };
|
|
169
164
|
var DEFAULT_CAPTION_CHARACTER = "SFX";
|
|
170
165
|
var SAVE_SCHEMA = "patter/save@0";
|
|
171
|
-
var SAVE_VERSION =
|
|
166
|
+
var SAVE_VERSION = 4;
|
|
172
167
|
var DEFAULT_LAYOUT = { flow: "scenes/", strings: "loc/", authoring: "authoring/", extensions: "extensions/" };
|
|
173
168
|
function projectLayout(project) {
|
|
174
169
|
return { ...DEFAULT_LAYOUT, ...project.layout };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@patterkit/model",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "Patter data-model types: source (scene/block/group/snippet/beat/jump), project, locale, authoring. The shape source-of-truth.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"build": "tsup src/index.ts --format esm,cjs --dts --clean"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@wildwinter/expr": "^0.6.0"
|
|
37
|
+
"@wildwinter/expr": "^0.6.0",
|
|
38
|
+
"@wildwinter/toolkit": "^0.4.0"
|
|
38
39
|
}
|
|
39
40
|
}
|