@patterkit/model 0.17.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,6 +673,11 @@ 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
@@ -707,6 +723,11 @@ interface LocaleFile {
707
723
  scene: string;
708
724
  locale: string;
709
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;
710
731
  /** beatId -> text. */
711
732
  strings: Record<string, string>;
712
733
  }
@@ -919,7 +940,7 @@ interface HandoffFile {
919
940
  }
920
941
  /** An editable line as sent. */
921
942
  interface HandoffLine {
922
- /** 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). */
923
944
  id: string;
924
945
  kind: "line" | "narration" | "option";
925
946
  /** The speaker, speaker qualifier (`gameId`), and direction as sent (spoken lines only). */
@@ -1362,4 +1383,4 @@ interface ExtensionFieldDecl {
1362
1383
  /** A node's extension values in a bundle: extension id -> field -> value, raw. */
1363
1384
  type NodeExtensions = Record<string, Record<string, unknown>>;
1364
1385
 
1365
- 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,6 +673,11 @@ 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
@@ -707,6 +723,11 @@ interface LocaleFile {
707
723
  scene: string;
708
724
  locale: string;
709
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;
710
731
  /** beatId -> text. */
711
732
  strings: Record<string, string>;
712
733
  }
@@ -919,7 +940,7 @@ interface HandoffFile {
919
940
  }
920
941
  /** An editable line as sent. */
921
942
  interface HandoffLine {
922
- /** 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). */
923
944
  id: string;
924
945
  kind: "line" | "narration" | "option";
925
946
  /** The speaker, speaker qualifier (`gameId`), and direction as sent (spoken lines only). */
@@ -1362,4 +1383,4 @@ interface ExtensionFieldDecl {
1362
1383
  /** A node's extension values in a bundle: extension id -> field -> value, raw. */
1363
1384
  type NodeExtensions = Record<string, Record<string, unknown>>;
1364
1385
 
1365
- 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.17.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",