@patterkit/model 0.13.1 → 0.15.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 +41 -0
- package/dist/index.d.cts +45 -6
- package/dist/index.d.ts +45 -6
- package/dist/index.js +36 -0
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -29,6 +29,7 @@ __export(index_exports, {
|
|
|
29
29
|
DEFAULT_PAD_AFTER: () => DEFAULT_PAD_AFTER,
|
|
30
30
|
DEFAULT_QUALIFIERS: () => DEFAULT_QUALIFIERS,
|
|
31
31
|
DEFAULT_RECORDING_STATUSES: () => DEFAULT_RECORDING_STATUSES,
|
|
32
|
+
DEFAULT_SPEAKER_PATTERN: () => DEFAULT_SPEAKER_PATTERN,
|
|
32
33
|
DEFAULT_WRITING_STATUSES: () => DEFAULT_WRITING_STATUSES,
|
|
33
34
|
FLOW_SCHEMA: () => FLOW_SCHEMA,
|
|
34
35
|
HANDOFF_SCHEMA: () => HANDOFF_SCHEMA,
|
|
@@ -41,10 +42,12 @@ __export(index_exports, {
|
|
|
41
42
|
RESERVED_PROPERTY_NAMES: () => import_expr.RESERVED_PROPERTY_NAMES,
|
|
42
43
|
SAVE_SCHEMA: () => SAVE_SCHEMA,
|
|
43
44
|
SAVE_VERSION: () => SAVE_VERSION,
|
|
45
|
+
SPEAKER_PATTERN_KEY: () => SPEAKER_PATTERN_KEY,
|
|
44
46
|
STRINGS_SCHEMA: () => STRINGS_SCHEMA,
|
|
45
47
|
castStringKey: () => castStringKey,
|
|
46
48
|
deriveRecordingFolders: () => deriveRecordingFolders,
|
|
47
49
|
effectiveGameId: () => effectiveGameId,
|
|
50
|
+
formatSpeakerLabel: () => formatSpeakerLabel,
|
|
48
51
|
gameIdify: () => gameIdify,
|
|
49
52
|
isCaseOnlyPropertyName: () => import_expr.isCaseOnlyPropertyName,
|
|
50
53
|
isContentlessBeat: () => isContentlessBeat,
|
|
@@ -54,7 +57,9 @@ __export(index_exports, {
|
|
|
54
57
|
projectQualifiers: () => projectQualifiers,
|
|
55
58
|
propertyNameify: () => import_expr.propertyNameify,
|
|
56
59
|
qualifierStringKey: () => qualifierStringKey,
|
|
60
|
+
speakerLabelKey: () => speakerLabelKey,
|
|
57
61
|
usedQualifiers: () => usedQualifiers,
|
|
62
|
+
usedSpeakerPairs: () => usedSpeakerPairs,
|
|
58
63
|
walkNodes: () => walkNodes
|
|
59
64
|
});
|
|
60
65
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -107,6 +112,29 @@ function usedQualifiers(project, scenes) {
|
|
|
107
112
|
}
|
|
108
113
|
return projectQualifiers(project).filter((q) => used.has(q.gameId));
|
|
109
114
|
}
|
|
115
|
+
function usedSpeakerPairs(scenes) {
|
|
116
|
+
const seen = /* @__PURE__ */ new Set();
|
|
117
|
+
const out = [];
|
|
118
|
+
const add = (beat) => {
|
|
119
|
+
if (!beat.character || !beat.qualifier) return;
|
|
120
|
+
const key = `${beat.character}\0${beat.qualifier}`;
|
|
121
|
+
if (seen.has(key)) return;
|
|
122
|
+
seen.add(key);
|
|
123
|
+
out.push({ character: beat.character, qualifier: beat.qualifier });
|
|
124
|
+
};
|
|
125
|
+
for (const scene of scenes) {
|
|
126
|
+
for (const block of scene.blocks) {
|
|
127
|
+
walkNodes(block.children, (node) => {
|
|
128
|
+
if (node.type === "group") {
|
|
129
|
+
if (node.prompt?.kind === "line") add(node.prompt);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
for (const beat of node.beats ?? []) if (beat.kind === "line") add(beat);
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return out;
|
|
137
|
+
}
|
|
110
138
|
var DEFAULT_PAD_AFTER = 0.6;
|
|
111
139
|
var PAD_AFTER_MIN = -10;
|
|
112
140
|
var PAD_AFTER_MAX = 60;
|
|
@@ -158,6 +186,14 @@ function castStringKey(name) {
|
|
|
158
186
|
function qualifierStringKey(gameId) {
|
|
159
187
|
return `qualifier:${gameId}`;
|
|
160
188
|
}
|
|
189
|
+
function speakerLabelKey(name, gameId) {
|
|
190
|
+
return `speaker:${name}:${gameId}`;
|
|
191
|
+
}
|
|
192
|
+
var SPEAKER_PATTERN_KEY = "speaker:pattern";
|
|
193
|
+
var DEFAULT_SPEAKER_PATTERN = "{name} ({qualifier})";
|
|
194
|
+
function formatSpeakerLabel(pattern, name, qualifier) {
|
|
195
|
+
return pattern.split("{name}").map((part) => part.split("{qualifier}").join(qualifier)).join(name);
|
|
196
|
+
}
|
|
161
197
|
var HANDOFF_SCHEMA = "patter/handoff@0";
|
|
162
198
|
var DEFAULT_CAPTION_DELIMITERS = { open: "[", close: "]" };
|
|
163
199
|
var DEFAULT_CAPTION_CHARACTER = "SFX";
|
|
@@ -182,6 +218,7 @@ var AUTHORING_SCHEMA = "patter/authoring@0";
|
|
|
182
218
|
DEFAULT_PAD_AFTER,
|
|
183
219
|
DEFAULT_QUALIFIERS,
|
|
184
220
|
DEFAULT_RECORDING_STATUSES,
|
|
221
|
+
DEFAULT_SPEAKER_PATTERN,
|
|
185
222
|
DEFAULT_WRITING_STATUSES,
|
|
186
223
|
FLOW_SCHEMA,
|
|
187
224
|
HANDOFF_SCHEMA,
|
|
@@ -194,10 +231,12 @@ var AUTHORING_SCHEMA = "patter/authoring@0";
|
|
|
194
231
|
RESERVED_PROPERTY_NAMES,
|
|
195
232
|
SAVE_SCHEMA,
|
|
196
233
|
SAVE_VERSION,
|
|
234
|
+
SPEAKER_PATTERN_KEY,
|
|
197
235
|
STRINGS_SCHEMA,
|
|
198
236
|
castStringKey,
|
|
199
237
|
deriveRecordingFolders,
|
|
200
238
|
effectiveGameId,
|
|
239
|
+
formatSpeakerLabel,
|
|
201
240
|
gameIdify,
|
|
202
241
|
isCaseOnlyPropertyName,
|
|
203
242
|
isContentlessBeat,
|
|
@@ -207,6 +246,8 @@ var AUTHORING_SCHEMA = "patter/authoring@0";
|
|
|
207
246
|
projectQualifiers,
|
|
208
247
|
propertyNameify,
|
|
209
248
|
qualifierStringKey,
|
|
249
|
+
speakerLabelKey,
|
|
210
250
|
usedQualifiers,
|
|
251
|
+
usedSpeakerPairs,
|
|
211
252
|
walkNodes
|
|
212
253
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -352,6 +352,10 @@ interface CastMember {
|
|
|
352
352
|
/** The voice actor cast for this character, if known - surfaced in the VO script export (spec §16).
|
|
353
353
|
* Authoring-only (not shipped in the runtime bundle). */
|
|
354
354
|
actor?: string;
|
|
355
|
+
/** This character's own label with a qualifier, by the qualifier's `gameId`, in the source language
|
|
356
|
+
* (`{ vo: "Your thoughts" }`), where the project's speaker pattern shouldn't apply. Localised as the
|
|
357
|
+
* `speaker:<name>:<gameId>` string (`speakerLabelKey`). Absent for every pair that follows the pattern. */
|
|
358
|
+
qualifierLabels?: Record<string, string>;
|
|
355
359
|
gameData?: GameData;
|
|
356
360
|
}
|
|
357
361
|
/** A speaker qualifier (a screenplay's character extension): `V.O.`, `O.S.`, `RADIO`, or the project's own.
|
|
@@ -372,6 +376,12 @@ declare const DEFAULT_QUALIFIERS: SpeakerQualifier[];
|
|
|
372
376
|
declare function projectQualifiers(project: Pick<ProjectFile, "qualifiers">): SpeakerQualifier[];
|
|
373
377
|
/** The project's qualifiers that some line (or line prompt) in these scenes uses, in the project's order. */
|
|
374
378
|
declare function usedQualifiers(project: Pick<ProjectFile, "qualifiers">, scenes: Scene[]): SpeakerQualifier[];
|
|
379
|
+
/** Every character and qualifier pair the lines use (a line's speaker with its qualifier, option prompts
|
|
380
|
+
* included), once each, in the order first met. A pair's label is shown only for these. */
|
|
381
|
+
declare function usedSpeakerPairs(scenes: Scene[]): {
|
|
382
|
+
character: string;
|
|
383
|
+
qualifier: string;
|
|
384
|
+
}[];
|
|
375
385
|
/** The built-in `padAfter`, in seconds, for a project that sets no default of its own: the same on every runtime
|
|
376
386
|
* and in Patterpad's Play window (design/proposals/line-padding.md section 4). */
|
|
377
387
|
declare const DEFAULT_PAD_AFTER = 0.6;
|
|
@@ -392,19 +402,27 @@ type BundleCastMember = Omit<CastMember, "notes" | "actor" | "gender">;
|
|
|
392
402
|
/** A node TYPE that can carry author-defined gameData fields (the gameData schema, project-level).
|
|
393
403
|
* Beat kinds map straight through: dialogue = `line`, narration = `text`, game event = `gameEvent`. */
|
|
394
404
|
type GameDataNodeKind = "scene" | "block" | "snippet" | "line" | "text" | "gameEvent";
|
|
395
|
-
/** The value type of a gameData field
|
|
396
|
-
*
|
|
397
|
-
|
|
405
|
+
/** The value type of a gameData field: the family's one field-type list, shared with Storylets' card and
|
|
406
|
+
* outcome fields (patterkit design/family-parity-2026-10.md item 9, patter-qualities.md section 1). Drives
|
|
407
|
+
* the inspector's editor widget (text / textarea / number / toggle / enum dropdown / flags checklist /
|
|
408
|
+
* quality ladder). A `quality` value is a stage of the field's own ladder (`stages`), compared by position by
|
|
409
|
+
* a host, never by the engine. */
|
|
410
|
+
type GameDataFieldType = "text" | "multiline" | "number" | "boolean" | "enum" | "flags" | "quality";
|
|
398
411
|
/** One author-defined custom field on a node type (host-integration metadata, NOT expression state). */
|
|
399
412
|
interface GameDataField {
|
|
400
413
|
/** Field key - also the key a node stores its value under in `gameData` (values are name-keyed). */
|
|
401
414
|
name: string;
|
|
402
415
|
type: GameDataFieldType;
|
|
403
416
|
/** The value used when a node sets nothing. Storage is SPARSE - nodes hold only their overrides, and
|
|
404
|
-
* a reader falls back to this default (so changing it here propagates to every node that didn't set it).
|
|
417
|
+
* a reader falls back to this default (so changing it here propagates to every node that didn't set it).
|
|
418
|
+
* Optional in source: left out, the type's default holds (by the kernel's `defaultFor`), and the compiler
|
|
419
|
+
* writes it into the bundle, so a bundle's field always has one. An enum's may be `""`, none chosen. */
|
|
405
420
|
default?: ScalarValue;
|
|
406
|
-
/** Allowed values when `type` is "enum". */
|
|
421
|
+
/** Allowed values when `type` is "enum", or the flags a "flags" value may hold. */
|
|
407
422
|
values?: string[];
|
|
423
|
+
/** A "quality" field's ordered ladder, by the family's one rule (at least two stages, none empty, none
|
|
424
|
+
* twice; `@wildwinter/expr`'s `qualityDeclarationProblems`). */
|
|
425
|
+
stages?: string[];
|
|
408
426
|
/** Free-text description of what the field is for - shown as a rollover hint in the inspector. */
|
|
409
427
|
purpose?: string;
|
|
410
428
|
}
|
|
@@ -623,6 +641,9 @@ interface ProjectFile {
|
|
|
623
641
|
/** The speaker qualifiers a line can pick from, in display order; default `DEFAULT_QUALIFIERS`. An empty
|
|
624
642
|
* list means the project uses none. */
|
|
625
643
|
qualifiers?: SpeakerQualifier[];
|
|
644
|
+
/** How a character's label reads with a qualifier, in the source language: `{name}` and `{qualifier}` filled
|
|
645
|
+
* in. Absent = `DEFAULT_SPEAKER_PATTERN`. Localised as the `speaker:pattern` string. */
|
|
646
|
+
speakerPattern?: string;
|
|
626
647
|
/** The project's default `padAfter` for every line and text beat that sets none and has no default above it.
|
|
627
648
|
* Absent = `DEFAULT_PAD_AFTER`. */
|
|
628
649
|
padAfterDefault?: number;
|
|
@@ -676,6 +697,19 @@ declare function castStringKey(name: string): string;
|
|
|
676
697
|
/** The project-level loc-string key for a speaker qualifier's shown name, e.g. `qualifier:vo`. Resolved as a
|
|
677
698
|
* cast display name is: the active locale, then the default locale, then the authored `name`. */
|
|
678
699
|
declare function qualifierStringKey(gameId: string): string;
|
|
700
|
+
/** The project-level loc-string key for one character's own label with one qualifier, e.g. `speaker:PLAYER:vo`:
|
|
701
|
+
* only for a pair someone has overridden (`CastMember.qualifierLabels`). Every other pair's label is built from
|
|
702
|
+
* the speaker pattern. */
|
|
703
|
+
declare function speakerLabelKey(name: string, gameId: string): string;
|
|
704
|
+
/** The project-level loc-string key for the speaker pattern, the label a character shows with a qualifier. */
|
|
705
|
+
declare const SPEAKER_PATTERN_KEY = "speaker:pattern";
|
|
706
|
+
/** The speaker pattern a project starts with: `You (V.O.)`. `{name}` and `{qualifier}` are plain placeholders,
|
|
707
|
+
* never run through line interpolation. */
|
|
708
|
+
declare const DEFAULT_SPEAKER_PATTERN = "{name} ({qualifier})";
|
|
709
|
+
/** A qualified speaker's label: the pattern with its placeholders filled. Each placeholder is replaced
|
|
710
|
+
* wherever it appears; nothing else in the pattern is read. The one composition rule, on every runtime and
|
|
711
|
+
* in Patterpad. */
|
|
712
|
+
declare function formatSpeakerLabel(pattern: string, name: string, qualifier: string): string;
|
|
679
713
|
/** Typed documentation annotation line (spec §18). */
|
|
680
714
|
interface DocLine {
|
|
681
715
|
/** The documentation CLASS (a `DocumentationClass.name`) - routes export
|
|
@@ -991,6 +1025,9 @@ interface Bundle {
|
|
|
991
1025
|
/** The speaker qualifiers the content uses, in the project's order. Absent when no line has one, so a
|
|
992
1026
|
* bundle without qualifiers is exactly as before. */
|
|
993
1027
|
qualifiers?: BundleQualifier[];
|
|
1028
|
+
/** The project's speaker pattern, the unlocalised fallback for a qualified speaker's label. Absent when the
|
|
1029
|
+
* project keeps `DEFAULT_SPEAKER_PATTERN` or uses no qualifiers. */
|
|
1030
|
+
speakerPattern?: string;
|
|
994
1031
|
/** The project's own `padAfterDefault`, when it sets one; absent = `DEFAULT_PAD_AFTER`. */
|
|
995
1032
|
padAfterDefault?: number;
|
|
996
1033
|
properties?: PropertyDecl[];
|
|
@@ -1076,6 +1113,8 @@ interface SavedChoicePrompt {
|
|
|
1076
1113
|
direction?: string;
|
|
1077
1114
|
qualifier?: string;
|
|
1078
1115
|
qualifierName?: string;
|
|
1116
|
+
/** The speaker's label as the choice showed it. Absent in a save written before it existed. */
|
|
1117
|
+
speakerLabel?: string;
|
|
1079
1118
|
/** The prompt's resolved pause (line padding). Absent in a save written before it existed. */
|
|
1080
1119
|
padAfter?: number;
|
|
1081
1120
|
}
|
|
@@ -1192,4 +1231,4 @@ declare const PROJECT_SCHEMA = "patter/project@0";
|
|
|
1192
1231
|
declare const STRINGS_SCHEMA = "patter/strings@0";
|
|
1193
1232
|
declare const AUTHORING_SCHEMA = "patter/authoring@0";
|
|
1194
1233
|
|
|
1195
|
-
export { AUTHORING_SCHEMA, type AuthoringFile, type Beat, type Block, type Bundle, type BundleCastMember, 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_WRITING_STATUSES, type DocLine, type DocumentationClass, type EditRecord, type Effect, type EngineSave, type EstimatingConfig, type Expression, FLOW_SCHEMA, type FlowCursor, type FlowFile, type FlowNode, type FlowSnapshot, type FlowSnapshotV2, 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, PAD_AFTER_MAX, PAD_AFTER_MIN, PROJECT_LOCALE_SCENE, PROJECT_SCHEMA, type ProjectDictionary, type ProjectFile, type PromptBeat, type PropertyDecl, type PropertyType, RERECORD_STATUS, RERECORD_STATUS_DECL, type RecordingFolder, type RecordingStatusDecl, SAVE_SCHEMA, SAVE_VERSION, STRINGS_SCHEMA, type SaveEnvelope, type SaveGame, type SaveGameV2, 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, type VcsKind, type WritingStatusDecl, castStringKey, deriveRecordingFolders, effectiveGameId, gameIdify, isContentlessBeat, isValidGameId, projectLayout, projectQualifiers, qualifierStringKey, usedQualifiers, walkNodes };
|
|
1234
|
+
export { AUTHORING_SCHEMA, type AuthoringFile, type Beat, type Block, type Bundle, type BundleCastMember, 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, type EditRecord, type Effect, type EngineSave, type EstimatingConfig, type Expression, FLOW_SCHEMA, type FlowCursor, type FlowFile, type FlowNode, type FlowSnapshot, type FlowSnapshotV2, 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, PAD_AFTER_MAX, PAD_AFTER_MIN, PROJECT_LOCALE_SCENE, PROJECT_SCHEMA, type ProjectDictionary, type ProjectFile, 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 SaveGameV2, 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, type VcsKind, type WritingStatusDecl, castStringKey, deriveRecordingFolders, effectiveGameId, formatSpeakerLabel, gameIdify, isContentlessBeat, isValidGameId, projectLayout, projectQualifiers, qualifierStringKey, speakerLabelKey, usedQualifiers, usedSpeakerPairs, walkNodes };
|
package/dist/index.d.ts
CHANGED
|
@@ -352,6 +352,10 @@ interface CastMember {
|
|
|
352
352
|
/** The voice actor cast for this character, if known - surfaced in the VO script export (spec §16).
|
|
353
353
|
* Authoring-only (not shipped in the runtime bundle). */
|
|
354
354
|
actor?: string;
|
|
355
|
+
/** This character's own label with a qualifier, by the qualifier's `gameId`, in the source language
|
|
356
|
+
* (`{ vo: "Your thoughts" }`), where the project's speaker pattern shouldn't apply. Localised as the
|
|
357
|
+
* `speaker:<name>:<gameId>` string (`speakerLabelKey`). Absent for every pair that follows the pattern. */
|
|
358
|
+
qualifierLabels?: Record<string, string>;
|
|
355
359
|
gameData?: GameData;
|
|
356
360
|
}
|
|
357
361
|
/** A speaker qualifier (a screenplay's character extension): `V.O.`, `O.S.`, `RADIO`, or the project's own.
|
|
@@ -372,6 +376,12 @@ declare const DEFAULT_QUALIFIERS: SpeakerQualifier[];
|
|
|
372
376
|
declare function projectQualifiers(project: Pick<ProjectFile, "qualifiers">): SpeakerQualifier[];
|
|
373
377
|
/** The project's qualifiers that some line (or line prompt) in these scenes uses, in the project's order. */
|
|
374
378
|
declare function usedQualifiers(project: Pick<ProjectFile, "qualifiers">, scenes: Scene[]): SpeakerQualifier[];
|
|
379
|
+
/** Every character and qualifier pair the lines use (a line's speaker with its qualifier, option prompts
|
|
380
|
+
* included), once each, in the order first met. A pair's label is shown only for these. */
|
|
381
|
+
declare function usedSpeakerPairs(scenes: Scene[]): {
|
|
382
|
+
character: string;
|
|
383
|
+
qualifier: string;
|
|
384
|
+
}[];
|
|
375
385
|
/** The built-in `padAfter`, in seconds, for a project that sets no default of its own: the same on every runtime
|
|
376
386
|
* and in Patterpad's Play window (design/proposals/line-padding.md section 4). */
|
|
377
387
|
declare const DEFAULT_PAD_AFTER = 0.6;
|
|
@@ -392,19 +402,27 @@ type BundleCastMember = Omit<CastMember, "notes" | "actor" | "gender">;
|
|
|
392
402
|
/** A node TYPE that can carry author-defined gameData fields (the gameData schema, project-level).
|
|
393
403
|
* Beat kinds map straight through: dialogue = `line`, narration = `text`, game event = `gameEvent`. */
|
|
394
404
|
type GameDataNodeKind = "scene" | "block" | "snippet" | "line" | "text" | "gameEvent";
|
|
395
|
-
/** The value type of a gameData field
|
|
396
|
-
*
|
|
397
|
-
|
|
405
|
+
/** The value type of a gameData field: the family's one field-type list, shared with Storylets' card and
|
|
406
|
+
* outcome fields (patterkit design/family-parity-2026-10.md item 9, patter-qualities.md section 1). Drives
|
|
407
|
+
* the inspector's editor widget (text / textarea / number / toggle / enum dropdown / flags checklist /
|
|
408
|
+
* quality ladder). A `quality` value is a stage of the field's own ladder (`stages`), compared by position by
|
|
409
|
+
* a host, never by the engine. */
|
|
410
|
+
type GameDataFieldType = "text" | "multiline" | "number" | "boolean" | "enum" | "flags" | "quality";
|
|
398
411
|
/** One author-defined custom field on a node type (host-integration metadata, NOT expression state). */
|
|
399
412
|
interface GameDataField {
|
|
400
413
|
/** Field key - also the key a node stores its value under in `gameData` (values are name-keyed). */
|
|
401
414
|
name: string;
|
|
402
415
|
type: GameDataFieldType;
|
|
403
416
|
/** The value used when a node sets nothing. Storage is SPARSE - nodes hold only their overrides, and
|
|
404
|
-
* a reader falls back to this default (so changing it here propagates to every node that didn't set it).
|
|
417
|
+
* a reader falls back to this default (so changing it here propagates to every node that didn't set it).
|
|
418
|
+
* Optional in source: left out, the type's default holds (by the kernel's `defaultFor`), and the compiler
|
|
419
|
+
* writes it into the bundle, so a bundle's field always has one. An enum's may be `""`, none chosen. */
|
|
405
420
|
default?: ScalarValue;
|
|
406
|
-
/** Allowed values when `type` is "enum". */
|
|
421
|
+
/** Allowed values when `type` is "enum", or the flags a "flags" value may hold. */
|
|
407
422
|
values?: string[];
|
|
423
|
+
/** A "quality" field's ordered ladder, by the family's one rule (at least two stages, none empty, none
|
|
424
|
+
* twice; `@wildwinter/expr`'s `qualityDeclarationProblems`). */
|
|
425
|
+
stages?: string[];
|
|
408
426
|
/** Free-text description of what the field is for - shown as a rollover hint in the inspector. */
|
|
409
427
|
purpose?: string;
|
|
410
428
|
}
|
|
@@ -623,6 +641,9 @@ interface ProjectFile {
|
|
|
623
641
|
/** The speaker qualifiers a line can pick from, in display order; default `DEFAULT_QUALIFIERS`. An empty
|
|
624
642
|
* list means the project uses none. */
|
|
625
643
|
qualifiers?: SpeakerQualifier[];
|
|
644
|
+
/** How a character's label reads with a qualifier, in the source language: `{name}` and `{qualifier}` filled
|
|
645
|
+
* in. Absent = `DEFAULT_SPEAKER_PATTERN`. Localised as the `speaker:pattern` string. */
|
|
646
|
+
speakerPattern?: string;
|
|
626
647
|
/** The project's default `padAfter` for every line and text beat that sets none and has no default above it.
|
|
627
648
|
* Absent = `DEFAULT_PAD_AFTER`. */
|
|
628
649
|
padAfterDefault?: number;
|
|
@@ -676,6 +697,19 @@ declare function castStringKey(name: string): string;
|
|
|
676
697
|
/** The project-level loc-string key for a speaker qualifier's shown name, e.g. `qualifier:vo`. Resolved as a
|
|
677
698
|
* cast display name is: the active locale, then the default locale, then the authored `name`. */
|
|
678
699
|
declare function qualifierStringKey(gameId: string): string;
|
|
700
|
+
/** The project-level loc-string key for one character's own label with one qualifier, e.g. `speaker:PLAYER:vo`:
|
|
701
|
+
* only for a pair someone has overridden (`CastMember.qualifierLabels`). Every other pair's label is built from
|
|
702
|
+
* the speaker pattern. */
|
|
703
|
+
declare function speakerLabelKey(name: string, gameId: string): string;
|
|
704
|
+
/** The project-level loc-string key for the speaker pattern, the label a character shows with a qualifier. */
|
|
705
|
+
declare const SPEAKER_PATTERN_KEY = "speaker:pattern";
|
|
706
|
+
/** The speaker pattern a project starts with: `You (V.O.)`. `{name}` and `{qualifier}` are plain placeholders,
|
|
707
|
+
* never run through line interpolation. */
|
|
708
|
+
declare const DEFAULT_SPEAKER_PATTERN = "{name} ({qualifier})";
|
|
709
|
+
/** A qualified speaker's label: the pattern with its placeholders filled. Each placeholder is replaced
|
|
710
|
+
* wherever it appears; nothing else in the pattern is read. The one composition rule, on every runtime and
|
|
711
|
+
* in Patterpad. */
|
|
712
|
+
declare function formatSpeakerLabel(pattern: string, name: string, qualifier: string): string;
|
|
679
713
|
/** Typed documentation annotation line (spec §18). */
|
|
680
714
|
interface DocLine {
|
|
681
715
|
/** The documentation CLASS (a `DocumentationClass.name`) - routes export
|
|
@@ -991,6 +1025,9 @@ interface Bundle {
|
|
|
991
1025
|
/** The speaker qualifiers the content uses, in the project's order. Absent when no line has one, so a
|
|
992
1026
|
* bundle without qualifiers is exactly as before. */
|
|
993
1027
|
qualifiers?: BundleQualifier[];
|
|
1028
|
+
/** The project's speaker pattern, the unlocalised fallback for a qualified speaker's label. Absent when the
|
|
1029
|
+
* project keeps `DEFAULT_SPEAKER_PATTERN` or uses no qualifiers. */
|
|
1030
|
+
speakerPattern?: string;
|
|
994
1031
|
/** The project's own `padAfterDefault`, when it sets one; absent = `DEFAULT_PAD_AFTER`. */
|
|
995
1032
|
padAfterDefault?: number;
|
|
996
1033
|
properties?: PropertyDecl[];
|
|
@@ -1076,6 +1113,8 @@ interface SavedChoicePrompt {
|
|
|
1076
1113
|
direction?: string;
|
|
1077
1114
|
qualifier?: string;
|
|
1078
1115
|
qualifierName?: string;
|
|
1116
|
+
/** The speaker's label as the choice showed it. Absent in a save written before it existed. */
|
|
1117
|
+
speakerLabel?: string;
|
|
1079
1118
|
/** The prompt's resolved pause (line padding). Absent in a save written before it existed. */
|
|
1080
1119
|
padAfter?: number;
|
|
1081
1120
|
}
|
|
@@ -1192,4 +1231,4 @@ declare const PROJECT_SCHEMA = "patter/project@0";
|
|
|
1192
1231
|
declare const STRINGS_SCHEMA = "patter/strings@0";
|
|
1193
1232
|
declare const AUTHORING_SCHEMA = "patter/authoring@0";
|
|
1194
1233
|
|
|
1195
|
-
export { AUTHORING_SCHEMA, type AuthoringFile, type Beat, type Block, type Bundle, type BundleCastMember, 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_WRITING_STATUSES, type DocLine, type DocumentationClass, type EditRecord, type Effect, type EngineSave, type EstimatingConfig, type Expression, FLOW_SCHEMA, type FlowCursor, type FlowFile, type FlowNode, type FlowSnapshot, type FlowSnapshotV2, 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, PAD_AFTER_MAX, PAD_AFTER_MIN, PROJECT_LOCALE_SCENE, PROJECT_SCHEMA, type ProjectDictionary, type ProjectFile, type PromptBeat, type PropertyDecl, type PropertyType, RERECORD_STATUS, RERECORD_STATUS_DECL, type RecordingFolder, type RecordingStatusDecl, SAVE_SCHEMA, SAVE_VERSION, STRINGS_SCHEMA, type SaveEnvelope, type SaveGame, type SaveGameV2, 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, type VcsKind, type WritingStatusDecl, castStringKey, deriveRecordingFolders, effectiveGameId, gameIdify, isContentlessBeat, isValidGameId, projectLayout, projectQualifiers, qualifierStringKey, usedQualifiers, walkNodes };
|
|
1234
|
+
export { AUTHORING_SCHEMA, type AuthoringFile, type Beat, type Block, type Bundle, type BundleCastMember, 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, type EditRecord, type Effect, type EngineSave, type EstimatingConfig, type Expression, FLOW_SCHEMA, type FlowCursor, type FlowFile, type FlowNode, type FlowSnapshot, type FlowSnapshotV2, 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, PAD_AFTER_MAX, PAD_AFTER_MIN, PROJECT_LOCALE_SCENE, PROJECT_SCHEMA, type ProjectDictionary, type ProjectFile, 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 SaveGameV2, 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, type VcsKind, type WritingStatusDecl, castStringKey, deriveRecordingFolders, effectiveGameId, formatSpeakerLabel, gameIdify, isContentlessBeat, isValidGameId, projectLayout, projectQualifiers, qualifierStringKey, speakerLabelKey, usedQualifiers, usedSpeakerPairs, walkNodes };
|
package/dist/index.js
CHANGED
|
@@ -53,6 +53,29 @@ function usedQualifiers(project, scenes) {
|
|
|
53
53
|
}
|
|
54
54
|
return projectQualifiers(project).filter((q) => used.has(q.gameId));
|
|
55
55
|
}
|
|
56
|
+
function usedSpeakerPairs(scenes) {
|
|
57
|
+
const seen = /* @__PURE__ */ new Set();
|
|
58
|
+
const out = [];
|
|
59
|
+
const add = (beat) => {
|
|
60
|
+
if (!beat.character || !beat.qualifier) return;
|
|
61
|
+
const key = `${beat.character}\0${beat.qualifier}`;
|
|
62
|
+
if (seen.has(key)) return;
|
|
63
|
+
seen.add(key);
|
|
64
|
+
out.push({ character: beat.character, qualifier: beat.qualifier });
|
|
65
|
+
};
|
|
66
|
+
for (const scene of scenes) {
|
|
67
|
+
for (const block of scene.blocks) {
|
|
68
|
+
walkNodes(block.children, (node) => {
|
|
69
|
+
if (node.type === "group") {
|
|
70
|
+
if (node.prompt?.kind === "line") add(node.prompt);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
for (const beat of node.beats ?? []) if (beat.kind === "line") add(beat);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
56
79
|
var DEFAULT_PAD_AFTER = 0.6;
|
|
57
80
|
var PAD_AFTER_MIN = -10;
|
|
58
81
|
var PAD_AFTER_MAX = 60;
|
|
@@ -104,6 +127,14 @@ function castStringKey(name) {
|
|
|
104
127
|
function qualifierStringKey(gameId) {
|
|
105
128
|
return `qualifier:${gameId}`;
|
|
106
129
|
}
|
|
130
|
+
function speakerLabelKey(name, gameId) {
|
|
131
|
+
return `speaker:${name}:${gameId}`;
|
|
132
|
+
}
|
|
133
|
+
var SPEAKER_PATTERN_KEY = "speaker:pattern";
|
|
134
|
+
var DEFAULT_SPEAKER_PATTERN = "{name} ({qualifier})";
|
|
135
|
+
function formatSpeakerLabel(pattern, name, qualifier) {
|
|
136
|
+
return pattern.split("{name}").map((part) => part.split("{qualifier}").join(qualifier)).join(name);
|
|
137
|
+
}
|
|
107
138
|
var HANDOFF_SCHEMA = "patter/handoff@0";
|
|
108
139
|
var DEFAULT_CAPTION_DELIMITERS = { open: "[", close: "]" };
|
|
109
140
|
var DEFAULT_CAPTION_CHARACTER = "SFX";
|
|
@@ -127,6 +158,7 @@ export {
|
|
|
127
158
|
DEFAULT_PAD_AFTER,
|
|
128
159
|
DEFAULT_QUALIFIERS,
|
|
129
160
|
DEFAULT_RECORDING_STATUSES,
|
|
161
|
+
DEFAULT_SPEAKER_PATTERN,
|
|
130
162
|
DEFAULT_WRITING_STATUSES,
|
|
131
163
|
FLOW_SCHEMA,
|
|
132
164
|
HANDOFF_SCHEMA,
|
|
@@ -139,10 +171,12 @@ export {
|
|
|
139
171
|
RESERVED_PROPERTY_NAMES,
|
|
140
172
|
SAVE_SCHEMA,
|
|
141
173
|
SAVE_VERSION,
|
|
174
|
+
SPEAKER_PATTERN_KEY,
|
|
142
175
|
STRINGS_SCHEMA,
|
|
143
176
|
castStringKey,
|
|
144
177
|
deriveRecordingFolders,
|
|
145
178
|
effectiveGameId,
|
|
179
|
+
formatSpeakerLabel,
|
|
146
180
|
gameIdify,
|
|
147
181
|
isCaseOnlyPropertyName,
|
|
148
182
|
isContentlessBeat,
|
|
@@ -152,6 +186,8 @@ export {
|
|
|
152
186
|
projectQualifiers,
|
|
153
187
|
propertyNameify,
|
|
154
188
|
qualifierStringKey,
|
|
189
|
+
speakerLabelKey,
|
|
155
190
|
usedQualifiers,
|
|
191
|
+
usedSpeakerPairs,
|
|
156
192
|
walkNodes
|
|
157
193
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@patterkit/model",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.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,6 @@
|
|
|
34
34
|
"build": "tsup src/index.ts --format esm,cjs --dts --clean"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@wildwinter/expr": "^0.
|
|
37
|
+
"@wildwinter/expr": "^0.6.0"
|
|
38
38
|
}
|
|
39
39
|
}
|