@patterkit/model 0.16.0 → 0.18.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 CHANGED
@@ -57,6 +57,7 @@ __export(index_exports, {
57
57
  gameIdify: () => gameIdify,
58
58
  isCaseOnlyPropertyName: () => import_expr.isCaseOnlyPropertyName,
59
59
  isContentlessBeat: () => isContentlessBeat,
60
+ isDialogueScene: () => isDialogueScene,
60
61
  isValidGameId: () => isValidGameId,
61
62
  isValidPropertyName: () => import_expr.isValidPropertyName,
62
63
  projectLayout: () => projectLayout,
@@ -64,6 +65,7 @@ __export(index_exports, {
64
65
  propertyNameify: () => import_expr.propertyNameify,
65
66
  qualifierStringKey: () => qualifierStringKey,
66
67
  speakerLabelKey: () => speakerLabelKey,
68
+ textIsAction: () => textIsAction,
67
69
  usedQualifiers: () => usedQualifiers,
68
70
  usedSpeakerPairs: () => usedSpeakerPairs,
69
71
  walkNodes: () => walkNodes
@@ -141,6 +143,27 @@ function usedSpeakerPairs(scenes) {
141
143
  }
142
144
  return out;
143
145
  }
146
+ function isDialogueScene(scene) {
147
+ let found = false;
148
+ for (const block of scene.blocks) {
149
+ walkNodes(block.children, (node) => {
150
+ if (found) return;
151
+ if (node.type === "group") {
152
+ if (node.prompt?.kind === "line" && node.prompt.character) found = true;
153
+ return;
154
+ }
155
+ for (const beat of node.beats ?? []) if (beat.kind === "line" && beat.character) {
156
+ found = true;
157
+ return;
158
+ }
159
+ });
160
+ if (found) return true;
161
+ }
162
+ return false;
163
+ }
164
+ function textIsAction(project, scene) {
165
+ return !project.localiseDialogueText && isDialogueScene(scene);
166
+ }
144
167
  var DEFAULT_PAD_AFTER = 0.6;
145
168
  var PAD_AFTER_MIN = -10;
146
169
  var PAD_AFTER_MAX = 60;
@@ -258,6 +281,7 @@ var UNRESOLVED_KEY = "unresolved";
258
281
  gameIdify,
259
282
  isCaseOnlyPropertyName,
260
283
  isContentlessBeat,
284
+ isDialogueScene,
261
285
  isValidGameId,
262
286
  isValidPropertyName,
263
287
  projectLayout,
@@ -265,6 +289,7 @@ var UNRESOLVED_KEY = "unresolved";
265
289
  propertyNameify,
266
290
  qualifierStringKey,
267
291
  speakerLabelKey,
292
+ textIsAction,
268
293
  usedQualifiers,
269
294
  usedSpeakerPairs,
270
295
  walkNodes
package/dist/index.d.cts CHANGED
@@ -43,7 +43,7 @@ interface LineBeat {
43
43
  tags?: string[];
44
44
  }
45
45
  /**
46
- * Authorial voice / narration - speaker-less prose (spec §2). Never voiced; its
46
+ * Text - speaker-less prose (spec §2). Never voiced; its
47
47
  * localised text always permits inline `{@name}` interpolation (spec §16). This
48
48
  * is the on-screen-text role (e.g. "A door slams!") - distinct from a game-event
49
49
  * beat, which is a pure engine instruction with no localised content.
@@ -63,6 +63,11 @@ interface TextBeat {
63
63
  extensions?: NodeExtensions;
64
64
  /** Author tags (#215). See LineBeat.tags. */
65
65
  tags?: string[];
66
+ /** Bundle only: this text beat is ACTION, a direction to the people staging the scene that the player
67
+ * never sees (design/proposals/action-text.md). Set by the compiler on every text beat of a dialogue scene
68
+ * (`isDialogueScene`) when the project's `localiseDialogueText` is off; its text is then the source in
69
+ * every locale. Absent = shown text. Never in source. */
70
+ action?: true;
66
71
  }
67
72
  /**
68
73
  * A GAME EVENT (spec §2): a pure engine instruction with no player-facing text - just `gameData` the host
@@ -394,6 +399,12 @@ declare function usedSpeakerPairs(scenes: Scene[]): {
394
399
  character: string;
395
400
  qualifier: string;
396
401
  }[];
402
+ /** A DIALOGUE scene (design/proposals/action-text.md): one with at least one line beat that names a
403
+ * character, an option's prompt included. Any other scene is a TEXT scene. */
404
+ declare function isDialogueScene(scene: Scene): boolean;
405
+ /** Whether a scene's text beats are ACTION: a dialogue scene, in a project that doesn't localise dialogue
406
+ * scenes' text (`localiseDialogueText` off, the default). Its option prompts never are. */
407
+ declare function textIsAction(project: Pick<ProjectFile, "localiseDialogueText">, scene: Scene): boolean;
397
408
  /** The built-in `padAfter`, in seconds, for a project that sets no default of its own: the same on every runtime
398
409
  * and in Patterpad's Play window (design/proposals/line-padding.md section 4). */
399
410
  declare const DEFAULT_PAD_AFTER = 0.6;
@@ -412,7 +423,7 @@ interface BundleQualifier {
412
423
  * the bundle; this type states the resulting contract for anyone reading a bundle. */
413
424
  type BundleCastMember = Omit<CastMember, "notes" | "actor" | "gender">;
414
425
  /** A node TYPE that can carry author-defined gameData fields (the gameData schema, project-level).
415
- * Beat kinds map straight through: dialogue = `line`, narration = `text`, game event = `gameEvent`.
426
+ * Beat kinds map straight through: dialogue = `line`, text = `text`, game event = `gameEvent`.
416
427
  * `option` is a choice's option: a group that is a direct child of a `choice` group, whose gameData the
417
428
  * host reads off the option `getChoices` hands it. Any other group's gameData stays undeclared. */
418
429
  type GameDataNodeKind = "scene" | "block" | "snippet" | "line" | "text" | "gameEvent" | "option";
@@ -589,7 +600,7 @@ interface ProjectFile {
589
600
  * opt-in even for a voiced project (a voiced story may want voice scripts without tracking recording status). */
590
601
  trackAudioStatus?: boolean;
591
602
  /**
592
- * Inline text formatting. When true, authors can mark dialogue / narration / direction /
603
+ * Inline text formatting. When true, authors can mark dialogue / text / direction /
593
604
  * choice-prompt text bold, italic, or bold+italic; it is stored INSIDE the localised strings
594
605
  * (and the flow's `direction`) as `<b>…</b>`, `<i>…</i>`, `<bi>…</bi>`, with literal `<`, `>`,
595
606
  * `&` escaped to `&lt;` / `&gt;` / `&amp;`. The runtime treats the string as opaque - it is the
@@ -662,13 +673,19 @@ interface ProjectFile {
662
673
  /** The project's default `padAfter` for every line and text beat that sets none and has no default above it.
663
674
  * Absent = `DEFAULT_PAD_AFTER`. */
664
675
  padAfterDefault?: number;
676
+ /** Localise text lines in dialogue scenes (design/proposals/action-text.md). Off (absent) by default: a
677
+ * dialogue scene's text beats (`isDialogueScene`) are then ACTION, left out of the loc files and the
678
+ * written word counts, and compiled with `action: true`. On: they're localised and shown as a text
679
+ * scene's are. A text scene is localised whatever this says, and an option's prompt always is. */
680
+ localiseDialogueText?: boolean;
665
681
  gameDataFields?: GameDataFields;
666
682
  /**
667
683
  * The Patter extensions this project takes, by id (ruled 2026-10-18: the project opts in), each pinned to a
668
684
  * version, with its settings (the host fields its claims present, by setting name). The manifest itself
669
685
  * sits in `extensions/<id>.extension.json`, and the data in `.patterextension` shards. Authoring config:
670
- * the bundle carries each one's compiled declarations and values, never this block. An extension named
671
- * here whose manifest is missing is a warning, and its data is left untouched.
686
+ * the bundle carries each one's compiled declarations, values, and resolved settings
687
+ * (`BundleExtension.settings`), never this block itself. An extension named here whose manifest is missing
688
+ * is a warning, and its data is left untouched.
672
689
  */
673
690
  extensions?: Record<string, ProjectExtension>;
674
691
  /** Ordered writing-status ladder (not-done -> done); default `DEFAULT_WRITING_STATUSES`. */
@@ -706,6 +723,11 @@ interface LocaleFile {
706
723
  scene: string;
707
724
  locale: string;
708
725
  default?: boolean;
726
+ /** A translated shard only: its scene's text beats were action (`textIsAction`) when loc import last wrote
727
+ * it, so they aren't in it. Loc export and `patter validate` compare this with the scene now, to report
728
+ * text that has dropped out of the loc files or come into them. Absent = shown text, or a shard written
729
+ * before the setting existed. */
730
+ textAction?: true;
709
731
  /** beatId -> text. */
710
732
  strings: Record<string, string>;
711
733
  }
@@ -918,7 +940,7 @@ interface HandoffFile {
918
940
  }
919
941
  /** An editable line as sent. */
920
942
  interface HandoffLine {
921
- /** The beat id (a line, a narration beat, or an option prompt). */
943
+ /** The beat id (a line, a text beat, or an option prompt). */
922
944
  id: string;
923
945
  kind: "line" | "narration" | "option";
924
946
  /** The speaker, speaker qualifier (`gameId`), and direction as sent (spoken lines only). */
@@ -1072,9 +1094,9 @@ interface Bundle {
1072
1094
  gameDataFields?: GameDataFields;
1073
1095
  /**
1074
1096
  * The extensions the project takes, by id: each one's version and its compiled declarations by node kind,
1075
- * every default resolved (what `extensionDecls` reads), and the project node's own values. A node's values
1076
- * sit on the node, under `extensions`. Absent when the project takes none, so a bundle without them is
1077
- * byte for byte what it was.
1097
+ * every default resolved (what `extensionDecls` reads), the project node's own values, and its settings,
1098
+ * resolved (what `extensionSettings` reads). A node's values sit on the node, under `extensions`. Absent
1099
+ * when the project takes none, so a bundle without them is byte for byte what it was.
1078
1100
  */
1079
1101
  extensions?: Record<string, BundleExtension>;
1080
1102
  scenes: Record<string, CompiledScene>;
@@ -1325,6 +1347,13 @@ interface BundleExtension {
1325
1347
  fields: Record<string, ExtensionFieldDecl[]>;
1326
1348
  /** The project node's values, raw, when it has any. */
1327
1349
  project?: Record<string, unknown>;
1350
+ /**
1351
+ * Every setting the manifest declares, by setting name, keys sorted: the project's value (`ProjectExtension.
1352
+ * settings`), or else the setting's default (`@wildwinter/toolkit/extensions`' `settingValues`). A setting
1353
+ * names a host field, so a game reads here which gameData field holds what the extension claims. Present
1354
+ * only when the manifest declares settings.
1355
+ */
1356
+ settings?: Record<string, string>;
1328
1357
  }
1329
1358
  /**
1330
1359
  * A compiled extension field declaration (`@wildwinter/toolkit/extensions`' FieldDecl, less the editor's
@@ -1354,4 +1383,4 @@ interface ExtensionFieldDecl {
1354
1383
  /** A node's extension values in a bundle: extension id -> field -> value, raw. */
1355
1384
  type NodeExtensions = Record<string, Record<string, unknown>>;
1356
1385
 
1357
- 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 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, 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 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, UNRESOLVED_KEY, type VcsKind, type WritingStatusDecl, castStringKey, deriveRecordingFolders, effectiveGameId, formatSpeakerLabel, gameIdify, isContentlessBeat, isValidGameId, projectLayout, projectQualifiers, qualifierStringKey, speakerLabelKey, usedQualifiers, usedSpeakerPairs, walkNodes };
1386
+ 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 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, 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 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, UNRESOLVED_KEY, type VcsKind, type WritingStatusDecl, castStringKey, deriveRecordingFolders, effectiveGameId, formatSpeakerLabel, gameIdify, isContentlessBeat, isDialogueScene, isValidGameId, projectLayout, projectQualifiers, qualifierStringKey, speakerLabelKey, textIsAction, usedQualifiers, usedSpeakerPairs, walkNodes };
package/dist/index.d.ts CHANGED
@@ -43,7 +43,7 @@ interface LineBeat {
43
43
  tags?: string[];
44
44
  }
45
45
  /**
46
- * Authorial voice / narration - speaker-less prose (spec §2). Never voiced; its
46
+ * Text - speaker-less prose (spec §2). Never voiced; its
47
47
  * localised text always permits inline `{@name}` interpolation (spec §16). This
48
48
  * is the on-screen-text role (e.g. "A door slams!") - distinct from a game-event
49
49
  * beat, which is a pure engine instruction with no localised content.
@@ -63,6 +63,11 @@ interface TextBeat {
63
63
  extensions?: NodeExtensions;
64
64
  /** Author tags (#215). See LineBeat.tags. */
65
65
  tags?: string[];
66
+ /** Bundle only: this text beat is ACTION, a direction to the people staging the scene that the player
67
+ * never sees (design/proposals/action-text.md). Set by the compiler on every text beat of a dialogue scene
68
+ * (`isDialogueScene`) when the project's `localiseDialogueText` is off; its text is then the source in
69
+ * every locale. Absent = shown text. Never in source. */
70
+ action?: true;
66
71
  }
67
72
  /**
68
73
  * A GAME EVENT (spec §2): a pure engine instruction with no player-facing text - just `gameData` the host
@@ -394,6 +399,12 @@ declare function usedSpeakerPairs(scenes: Scene[]): {
394
399
  character: string;
395
400
  qualifier: string;
396
401
  }[];
402
+ /** A DIALOGUE scene (design/proposals/action-text.md): one with at least one line beat that names a
403
+ * character, an option's prompt included. Any other scene is a TEXT scene. */
404
+ declare function isDialogueScene(scene: Scene): boolean;
405
+ /** Whether a scene's text beats are ACTION: a dialogue scene, in a project that doesn't localise dialogue
406
+ * scenes' text (`localiseDialogueText` off, the default). Its option prompts never are. */
407
+ declare function textIsAction(project: Pick<ProjectFile, "localiseDialogueText">, scene: Scene): boolean;
397
408
  /** The built-in `padAfter`, in seconds, for a project that sets no default of its own: the same on every runtime
398
409
  * and in Patterpad's Play window (design/proposals/line-padding.md section 4). */
399
410
  declare const DEFAULT_PAD_AFTER = 0.6;
@@ -412,7 +423,7 @@ interface BundleQualifier {
412
423
  * the bundle; this type states the resulting contract for anyone reading a bundle. */
413
424
  type BundleCastMember = Omit<CastMember, "notes" | "actor" | "gender">;
414
425
  /** A node TYPE that can carry author-defined gameData fields (the gameData schema, project-level).
415
- * Beat kinds map straight through: dialogue = `line`, narration = `text`, game event = `gameEvent`.
426
+ * Beat kinds map straight through: dialogue = `line`, text = `text`, game event = `gameEvent`.
416
427
  * `option` is a choice's option: a group that is a direct child of a `choice` group, whose gameData the
417
428
  * host reads off the option `getChoices` hands it. Any other group's gameData stays undeclared. */
418
429
  type GameDataNodeKind = "scene" | "block" | "snippet" | "line" | "text" | "gameEvent" | "option";
@@ -589,7 +600,7 @@ interface ProjectFile {
589
600
  * opt-in even for a voiced project (a voiced story may want voice scripts without tracking recording status). */
590
601
  trackAudioStatus?: boolean;
591
602
  /**
592
- * Inline text formatting. When true, authors can mark dialogue / narration / direction /
603
+ * Inline text formatting. When true, authors can mark dialogue / text / direction /
593
604
  * choice-prompt text bold, italic, or bold+italic; it is stored INSIDE the localised strings
594
605
  * (and the flow's `direction`) as `<b>…</b>`, `<i>…</i>`, `<bi>…</bi>`, with literal `<`, `>`,
595
606
  * `&` escaped to `&lt;` / `&gt;` / `&amp;`. The runtime treats the string as opaque - it is the
@@ -662,13 +673,19 @@ interface ProjectFile {
662
673
  /** The project's default `padAfter` for every line and text beat that sets none and has no default above it.
663
674
  * Absent = `DEFAULT_PAD_AFTER`. */
664
675
  padAfterDefault?: number;
676
+ /** Localise text lines in dialogue scenes (design/proposals/action-text.md). Off (absent) by default: a
677
+ * dialogue scene's text beats (`isDialogueScene`) are then ACTION, left out of the loc files and the
678
+ * written word counts, and compiled with `action: true`. On: they're localised and shown as a text
679
+ * scene's are. A text scene is localised whatever this says, and an option's prompt always is. */
680
+ localiseDialogueText?: boolean;
665
681
  gameDataFields?: GameDataFields;
666
682
  /**
667
683
  * The Patter extensions this project takes, by id (ruled 2026-10-18: the project opts in), each pinned to a
668
684
  * version, with its settings (the host fields its claims present, by setting name). The manifest itself
669
685
  * sits in `extensions/<id>.extension.json`, and the data in `.patterextension` shards. Authoring config:
670
- * the bundle carries each one's compiled declarations and values, never this block. An extension named
671
- * here whose manifest is missing is a warning, and its data is left untouched.
686
+ * the bundle carries each one's compiled declarations, values, and resolved settings
687
+ * (`BundleExtension.settings`), never this block itself. An extension named here whose manifest is missing
688
+ * is a warning, and its data is left untouched.
672
689
  */
673
690
  extensions?: Record<string, ProjectExtension>;
674
691
  /** Ordered writing-status ladder (not-done -> done); default `DEFAULT_WRITING_STATUSES`. */
@@ -706,6 +723,11 @@ interface LocaleFile {
706
723
  scene: string;
707
724
  locale: string;
708
725
  default?: boolean;
726
+ /** A translated shard only: its scene's text beats were action (`textIsAction`) when loc import last wrote
727
+ * it, so they aren't in it. Loc export and `patter validate` compare this with the scene now, to report
728
+ * text that has dropped out of the loc files or come into them. Absent = shown text, or a shard written
729
+ * before the setting existed. */
730
+ textAction?: true;
709
731
  /** beatId -> text. */
710
732
  strings: Record<string, string>;
711
733
  }
@@ -918,7 +940,7 @@ interface HandoffFile {
918
940
  }
919
941
  /** An editable line as sent. */
920
942
  interface HandoffLine {
921
- /** The beat id (a line, a narration beat, or an option prompt). */
943
+ /** The beat id (a line, a text beat, or an option prompt). */
922
944
  id: string;
923
945
  kind: "line" | "narration" | "option";
924
946
  /** The speaker, speaker qualifier (`gameId`), and direction as sent (spoken lines only). */
@@ -1072,9 +1094,9 @@ interface Bundle {
1072
1094
  gameDataFields?: GameDataFields;
1073
1095
  /**
1074
1096
  * The extensions the project takes, by id: each one's version and its compiled declarations by node kind,
1075
- * every default resolved (what `extensionDecls` reads), and the project node's own values. A node's values
1076
- * sit on the node, under `extensions`. Absent when the project takes none, so a bundle without them is
1077
- * byte for byte what it was.
1097
+ * every default resolved (what `extensionDecls` reads), the project node's own values, and its settings,
1098
+ * resolved (what `extensionSettings` reads). A node's values sit on the node, under `extensions`. Absent
1099
+ * when the project takes none, so a bundle without them is byte for byte what it was.
1078
1100
  */
1079
1101
  extensions?: Record<string, BundleExtension>;
1080
1102
  scenes: Record<string, CompiledScene>;
@@ -1325,6 +1347,13 @@ interface BundleExtension {
1325
1347
  fields: Record<string, ExtensionFieldDecl[]>;
1326
1348
  /** The project node's values, raw, when it has any. */
1327
1349
  project?: Record<string, unknown>;
1350
+ /**
1351
+ * Every setting the manifest declares, by setting name, keys sorted: the project's value (`ProjectExtension.
1352
+ * settings`), or else the setting's default (`@wildwinter/toolkit/extensions`' `settingValues`). A setting
1353
+ * names a host field, so a game reads here which gameData field holds what the extension claims. Present
1354
+ * only when the manifest declares settings.
1355
+ */
1356
+ settings?: Record<string, string>;
1328
1357
  }
1329
1358
  /**
1330
1359
  * A compiled extension field declaration (`@wildwinter/toolkit/extensions`' FieldDecl, less the editor's
@@ -1354,4 +1383,4 @@ interface ExtensionFieldDecl {
1354
1383
  /** A node's extension values in a bundle: extension id -> field -> value, raw. */
1355
1384
  type NodeExtensions = Record<string, Record<string, unknown>>;
1356
1385
 
1357
- 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 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, 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 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, UNRESOLVED_KEY, type VcsKind, type WritingStatusDecl, castStringKey, deriveRecordingFolders, effectiveGameId, formatSpeakerLabel, gameIdify, isContentlessBeat, isValidGameId, projectLayout, projectQualifiers, qualifierStringKey, speakerLabelKey, usedQualifiers, usedSpeakerPairs, walkNodes };
1386
+ 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 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, 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 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, UNRESOLVED_KEY, type VcsKind, type WritingStatusDecl, castStringKey, deriveRecordingFolders, effectiveGameId, formatSpeakerLabel, gameIdify, isContentlessBeat, isDialogueScene, isValidGameId, projectLayout, projectQualifiers, qualifierStringKey, speakerLabelKey, textIsAction, usedQualifiers, usedSpeakerPairs, walkNodes };
package/dist/index.js CHANGED
@@ -76,6 +76,27 @@ function usedSpeakerPairs(scenes) {
76
76
  }
77
77
  return out;
78
78
  }
79
+ function isDialogueScene(scene) {
80
+ let found = false;
81
+ for (const block of scene.blocks) {
82
+ walkNodes(block.children, (node) => {
83
+ if (found) return;
84
+ if (node.type === "group") {
85
+ if (node.prompt?.kind === "line" && node.prompt.character) found = true;
86
+ return;
87
+ }
88
+ for (const beat of node.beats ?? []) if (beat.kind === "line" && beat.character) {
89
+ found = true;
90
+ return;
91
+ }
92
+ });
93
+ if (found) return true;
94
+ }
95
+ return false;
96
+ }
97
+ function textIsAction(project, scene) {
98
+ return !project.localiseDialogueText && isDialogueScene(scene);
99
+ }
79
100
  var DEFAULT_PAD_AFTER = 0.6;
80
101
  var PAD_AFTER_MIN = -10;
81
102
  var PAD_AFTER_MAX = 60;
@@ -192,6 +213,7 @@ export {
192
213
  gameIdify,
193
214
  isCaseOnlyPropertyName,
194
215
  isContentlessBeat,
216
+ isDialogueScene,
195
217
  isValidGameId,
196
218
  isValidPropertyName,
197
219
  projectLayout,
@@ -199,6 +221,7 @@ export {
199
221
  propertyNameify,
200
222
  qualifierStringKey,
201
223
  speakerLabelKey,
224
+ textIsAction,
202
225
  usedQualifiers,
203
226
  usedSpeakerPairs,
204
227
  walkNodes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patterkit/model",
3
- "version": "0.16.0",
3
+ "version": "0.18.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",