@patterkit/model 0.2.0 → 0.3.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 +27 -0
- package/dist/index.d.cts +37 -4
- package/dist/index.d.ts +37 -4
- package/dist/index.js +22 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
COMMON_GENDERS: () => COMMON_GENDERS,
|
|
23
24
|
DEFAULT_CAPTION_CHARACTER: () => DEFAULT_CAPTION_CHARACTER,
|
|
24
25
|
DEFAULT_CAPTION_DELIMITERS: () => DEFAULT_CAPTION_DELIMITERS,
|
|
25
26
|
DEFAULT_DOCUMENTATION_CLASSES: () => DEFAULT_DOCUMENTATION_CLASSES,
|
|
@@ -28,12 +29,16 @@ __export(index_exports, {
|
|
|
28
29
|
PROJECT_LOCALE_SCENE: () => PROJECT_LOCALE_SCENE,
|
|
29
30
|
RERECORD_STATUS: () => RERECORD_STATUS,
|
|
30
31
|
RERECORD_STATUS_DECL: () => RERECORD_STATUS_DECL,
|
|
32
|
+
RESERVED_PROPERTY_NAMES: () => RESERVED_PROPERTY_NAMES,
|
|
31
33
|
castStringKey: () => castStringKey,
|
|
32
34
|
deriveRecordingFolders: () => deriveRecordingFolders,
|
|
33
35
|
effectiveGameId: () => effectiveGameId,
|
|
34
36
|
gameIdify: () => gameIdify,
|
|
37
|
+
isCaseOnlyPropertyName: () => isCaseOnlyPropertyName,
|
|
35
38
|
isContentlessBeat: () => isContentlessBeat,
|
|
36
39
|
isValidGameId: () => isValidGameId,
|
|
40
|
+
isValidPropertyName: () => isValidPropertyName,
|
|
41
|
+
propertyNameify: () => propertyNameify,
|
|
37
42
|
walkNodes: () => walkNodes
|
|
38
43
|
});
|
|
39
44
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -57,10 +62,27 @@ function gameIdify(text) {
|
|
|
57
62
|
function isValidGameId(gameId) {
|
|
58
63
|
return /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(gameId);
|
|
59
64
|
}
|
|
65
|
+
var RESERVED_PROPERTY_NAMES = ["true", "false", "and", "or", "not"];
|
|
66
|
+
function propertyNameify(text) {
|
|
67
|
+
const trimmed = text.trim();
|
|
68
|
+
const deliberateLeading = trimmed.startsWith("_");
|
|
69
|
+
let out = trimmed.toLowerCase().replace(/['\u2019]/g, "").replace(/[^a-z0-9_]+/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "");
|
|
70
|
+
if (out === "") return "";
|
|
71
|
+
if (deliberateLeading || /^[0-9]/.test(out)) out = `_${out}`;
|
|
72
|
+
if (RESERVED_PROPERTY_NAMES.includes(out)) out = `${out}_`;
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
function isValidPropertyName(name) {
|
|
76
|
+
return /^[a-z_][a-z0-9_]*$/.test(name) && !RESERVED_PROPERTY_NAMES.includes(name);
|
|
77
|
+
}
|
|
78
|
+
function isCaseOnlyPropertyName(name) {
|
|
79
|
+
return !isValidPropertyName(name) && isValidPropertyName(name.toLowerCase());
|
|
80
|
+
}
|
|
60
81
|
function effectiveGameId(entity) {
|
|
61
82
|
const g = entity.gameId?.trim();
|
|
62
83
|
return g ? g : gameIdify(entity.name);
|
|
63
84
|
}
|
|
85
|
+
var COMMON_GENDERS = ["male", "female", "neuter"];
|
|
64
86
|
var DEFAULT_WRITING_STATUSES = [
|
|
65
87
|
{ name: "stub", colour: 0 },
|
|
66
88
|
// red
|
|
@@ -108,6 +130,7 @@ var DEFAULT_CAPTION_DELIMITERS = { open: "[", close: "]" };
|
|
|
108
130
|
var DEFAULT_CAPTION_CHARACTER = "SFX";
|
|
109
131
|
// Annotate the CommonJS export names for ESM import in node:
|
|
110
132
|
0 && (module.exports = {
|
|
133
|
+
COMMON_GENDERS,
|
|
111
134
|
DEFAULT_CAPTION_CHARACTER,
|
|
112
135
|
DEFAULT_CAPTION_DELIMITERS,
|
|
113
136
|
DEFAULT_DOCUMENTATION_CLASSES,
|
|
@@ -116,11 +139,15 @@ var DEFAULT_CAPTION_CHARACTER = "SFX";
|
|
|
116
139
|
PROJECT_LOCALE_SCENE,
|
|
117
140
|
RERECORD_STATUS,
|
|
118
141
|
RERECORD_STATUS_DECL,
|
|
142
|
+
RESERVED_PROPERTY_NAMES,
|
|
119
143
|
castStringKey,
|
|
120
144
|
deriveRecordingFolders,
|
|
121
145
|
effectiveGameId,
|
|
122
146
|
gameIdify,
|
|
147
|
+
isCaseOnlyPropertyName,
|
|
123
148
|
isContentlessBeat,
|
|
124
149
|
isValidGameId,
|
|
150
|
+
isValidPropertyName,
|
|
151
|
+
propertyNameify,
|
|
125
152
|
walkNodes
|
|
126
153
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -207,6 +207,21 @@ declare function isContentlessBeat(beat: Beat, hasText: boolean): boolean;
|
|
|
207
207
|
declare function gameIdify(text: string): string;
|
|
208
208
|
/** A valid authored game id: lowercase alphanumerics + hyphens, no leading / trailing hyphen. */
|
|
209
209
|
declare function isValidGameId(gameId: string): boolean;
|
|
210
|
+
/** The words `@wildwinter/expr` lexes as keywords, so no property may be called one.
|
|
211
|
+
* `packages/model/test/property-name-grammar.test.ts` probes the real parser rather
|
|
212
|
+
* than trusting this copy. */
|
|
213
|
+
declare const RESERVED_PROPERTY_NAMES: readonly string[];
|
|
214
|
+
/** Coerce a label into a legal property name: lower case, apostrophes dropped, runs of
|
|
215
|
+
* anything else to a single underscore, no trailing underscore, an underscore in front
|
|
216
|
+
* of a leading digit, one behind a keyword. "" when nothing usable was left. */
|
|
217
|
+
declare function propertyNameify(text: string): string;
|
|
218
|
+
/** Is this a name an expression can actually reach? Lower case letters, digits and
|
|
219
|
+
* underscores, not starting with a digit, not a keyword. "" is not a name. */
|
|
220
|
+
declare function isValidPropertyName(name: string): boolean;
|
|
221
|
+
/** True when folding case ALONE would make it legal (`isNight`). The only violation a
|
|
222
|
+
* loader may repair without guessing at intent: every reference is folded already, so
|
|
223
|
+
* folding the declaration to match changes nothing observable. */
|
|
224
|
+
declare function isCaseOnlyPropertyName(name: string): boolean;
|
|
210
225
|
/** The effective address: the explicit `gameId` if pinned, else derived from `name`. */
|
|
211
226
|
declare function effectiveGameId(entity: {
|
|
212
227
|
gameId?: string;
|
|
@@ -296,8 +311,15 @@ interface CoverageDriver {
|
|
|
296
311
|
/** A character's grammatical gender, for localisation. Translators need it to inflect the speaker's own
|
|
297
312
|
* lines in gendered languages (adjectives, participles, pronouns), which the source text alone often
|
|
298
313
|
* cannot tell them. Absent means "not specified". Authoring-only: it never reaches the runtime bundle,
|
|
299
|
-
* but it IS carried into the localisation handoff formats as translator context (spec §14).
|
|
300
|
-
|
|
314
|
+
* but it IS carried into the localisation handoff formats as translator context (spec §14).
|
|
315
|
+
*
|
|
316
|
+
* Free text, not a closed set: real languages need more than three genders (common/utrum, animate/
|
|
317
|
+
* inanimate, and so on) and translators name them differently. `COMMON_GENDERS` seeds the editor's
|
|
318
|
+
* auto-suggest so the everyday values stay spelled consistently; anything else is still valid. */
|
|
319
|
+
type GrammaticalGender = string;
|
|
320
|
+
/** The everyday grammatical genders the Cast editor offers as auto-suggest defaults. Not exhaustive and
|
|
321
|
+
* not enforced - a project may use any string (see `GrammaticalGender`). */
|
|
322
|
+
declare const COMMON_GENDERS: readonly ["male", "female", "neuter"];
|
|
301
323
|
interface CastMember {
|
|
302
324
|
/** Canonical speaker name (matched by a beat's `character`); language-neutral key. */
|
|
303
325
|
name: string;
|
|
@@ -349,7 +371,7 @@ interface WritingStatusDecl {
|
|
|
349
371
|
/** Threshold marker: this status and every later one classify as "ready to ship". */
|
|
350
372
|
readyToShip?: boolean;
|
|
351
373
|
/** Theme character-palette slot (0-11) for the per-line status badge / inspector swatch (Patterpad #196).
|
|
352
|
-
* A slot (not a hex) so it adapts to light/dark + the
|
|
374
|
+
* A slot (not a hex) so it adapts to light/dark + the colour themes. Absent = no colour (neutral). */
|
|
353
375
|
colour?: number;
|
|
354
376
|
}
|
|
355
377
|
/**
|
|
@@ -600,6 +622,17 @@ interface CommentMessage {
|
|
|
600
622
|
author: string;
|
|
601
623
|
ts: string;
|
|
602
624
|
body: string;
|
|
625
|
+
/** A TOMBSTONE: the words are gone, the turn in the conversation is not.
|
|
626
|
+
*
|
|
627
|
+
* Removing a reply outright would renumber the argument around it, so what is
|
|
628
|
+
* left records who spoke and when, and that they withdrew it. The `body` is
|
|
629
|
+
* EMPTIED rather than kept and hidden, because "deleted" has to mean gone from
|
|
630
|
+
* a file that lives in version control.
|
|
631
|
+
*
|
|
632
|
+
* This is the one message allowed an empty body: `saveSceneComments` prunes
|
|
633
|
+
* empty messages so a cancelled composer leaves nothing behind, and without
|
|
634
|
+
* this flag a tombstone would be pruned on the way to disk. */
|
|
635
|
+
deleted?: boolean;
|
|
603
636
|
}
|
|
604
637
|
/** A sub-text range a comment is pinned to, within its anchor node's say text (#148). Offsets are
|
|
605
638
|
* character positions over the rendered (plain) source text - inline formatting is marks, not part of
|
|
@@ -819,4 +852,4 @@ declare const DEFAULT_CAPTION_DELIMITERS: CaptionDelimiters;
|
|
|
819
852
|
* captions are off). Applies even to a project that pins no `closedCaptions`. */
|
|
820
853
|
declare const DEFAULT_CAPTION_CHARACTER = "SFX";
|
|
821
854
|
|
|
822
|
-
export { type AuthoringFile, type Beat, type Block, type Bundle, type BundleCastMember, 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_RECORDING_STATUSES, DEFAULT_WRITING_STATUSES, type DocLine, type DocumentationClass, type EditRecord, type Effect, type EstimatingConfig, type Expression, type FlowFile, type FlowNode, type GameData, type GameDataField, type GameDataFieldType, type GameDataFields, type GameDataNodeKind, type GameEventBeat, type GrammaticalGender, type Group, type HostScopeDecl, type HostScopeRegistry, type HostScopeSpec, type Jump, type JumpTarget, type LineBeat, type LocaleFile, PROJECT_LOCALE_SCENE, type ProjectDictionary, type ProjectFile, type PromptBeat, type PropertyDecl, type PropertyType, RERECORD_STATUS, RERECORD_STATUS_DECL, type RecordingFolder, type RecordingStatusDecl, type ScalarValue, type Scene, type Selector, type SelectorExhaust, type SelectorOrder, type SequenceOptions, type Snippet, type Suggestion, type TextBeat, type VcsKind, type WritingStatusDecl, castStringKey, deriveRecordingFolders, effectiveGameId, gameIdify, isContentlessBeat, isValidGameId, walkNodes };
|
|
855
|
+
export { type AuthoringFile, type Beat, type Block, type Bundle, type BundleCastMember, 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_RECORDING_STATUSES, DEFAULT_WRITING_STATUSES, type DocLine, type DocumentationClass, type EditRecord, type Effect, type EstimatingConfig, type Expression, type FlowFile, type FlowNode, type GameData, type GameDataField, type GameDataFieldType, type GameDataFields, type GameDataNodeKind, type GameEventBeat, type GrammaticalGender, type Group, type HostScopeDecl, type HostScopeRegistry, type HostScopeSpec, type Jump, type JumpTarget, type LineBeat, type LocaleFile, PROJECT_LOCALE_SCENE, type ProjectDictionary, type ProjectFile, type PromptBeat, type PropertyDecl, type PropertyType, RERECORD_STATUS, RERECORD_STATUS_DECL, RESERVED_PROPERTY_NAMES, type RecordingFolder, type RecordingStatusDecl, type ScalarValue, type Scene, type Selector, type SelectorExhaust, type SelectorOrder, type SequenceOptions, type Snippet, type Suggestion, type TextBeat, type VcsKind, type WritingStatusDecl, castStringKey, deriveRecordingFolders, effectiveGameId, gameIdify, isCaseOnlyPropertyName, isContentlessBeat, isValidGameId, isValidPropertyName, propertyNameify, walkNodes };
|
package/dist/index.d.ts
CHANGED
|
@@ -207,6 +207,21 @@ declare function isContentlessBeat(beat: Beat, hasText: boolean): boolean;
|
|
|
207
207
|
declare function gameIdify(text: string): string;
|
|
208
208
|
/** A valid authored game id: lowercase alphanumerics + hyphens, no leading / trailing hyphen. */
|
|
209
209
|
declare function isValidGameId(gameId: string): boolean;
|
|
210
|
+
/** The words `@wildwinter/expr` lexes as keywords, so no property may be called one.
|
|
211
|
+
* `packages/model/test/property-name-grammar.test.ts` probes the real parser rather
|
|
212
|
+
* than trusting this copy. */
|
|
213
|
+
declare const RESERVED_PROPERTY_NAMES: readonly string[];
|
|
214
|
+
/** Coerce a label into a legal property name: lower case, apostrophes dropped, runs of
|
|
215
|
+
* anything else to a single underscore, no trailing underscore, an underscore in front
|
|
216
|
+
* of a leading digit, one behind a keyword. "" when nothing usable was left. */
|
|
217
|
+
declare function propertyNameify(text: string): string;
|
|
218
|
+
/** Is this a name an expression can actually reach? Lower case letters, digits and
|
|
219
|
+
* underscores, not starting with a digit, not a keyword. "" is not a name. */
|
|
220
|
+
declare function isValidPropertyName(name: string): boolean;
|
|
221
|
+
/** True when folding case ALONE would make it legal (`isNight`). The only violation a
|
|
222
|
+
* loader may repair without guessing at intent: every reference is folded already, so
|
|
223
|
+
* folding the declaration to match changes nothing observable. */
|
|
224
|
+
declare function isCaseOnlyPropertyName(name: string): boolean;
|
|
210
225
|
/** The effective address: the explicit `gameId` if pinned, else derived from `name`. */
|
|
211
226
|
declare function effectiveGameId(entity: {
|
|
212
227
|
gameId?: string;
|
|
@@ -296,8 +311,15 @@ interface CoverageDriver {
|
|
|
296
311
|
/** A character's grammatical gender, for localisation. Translators need it to inflect the speaker's own
|
|
297
312
|
* lines in gendered languages (adjectives, participles, pronouns), which the source text alone often
|
|
298
313
|
* cannot tell them. Absent means "not specified". Authoring-only: it never reaches the runtime bundle,
|
|
299
|
-
* but it IS carried into the localisation handoff formats as translator context (spec §14).
|
|
300
|
-
|
|
314
|
+
* but it IS carried into the localisation handoff formats as translator context (spec §14).
|
|
315
|
+
*
|
|
316
|
+
* Free text, not a closed set: real languages need more than three genders (common/utrum, animate/
|
|
317
|
+
* inanimate, and so on) and translators name them differently. `COMMON_GENDERS` seeds the editor's
|
|
318
|
+
* auto-suggest so the everyday values stay spelled consistently; anything else is still valid. */
|
|
319
|
+
type GrammaticalGender = string;
|
|
320
|
+
/** The everyday grammatical genders the Cast editor offers as auto-suggest defaults. Not exhaustive and
|
|
321
|
+
* not enforced - a project may use any string (see `GrammaticalGender`). */
|
|
322
|
+
declare const COMMON_GENDERS: readonly ["male", "female", "neuter"];
|
|
301
323
|
interface CastMember {
|
|
302
324
|
/** Canonical speaker name (matched by a beat's `character`); language-neutral key. */
|
|
303
325
|
name: string;
|
|
@@ -349,7 +371,7 @@ interface WritingStatusDecl {
|
|
|
349
371
|
/** Threshold marker: this status and every later one classify as "ready to ship". */
|
|
350
372
|
readyToShip?: boolean;
|
|
351
373
|
/** Theme character-palette slot (0-11) for the per-line status badge / inspector swatch (Patterpad #196).
|
|
352
|
-
* A slot (not a hex) so it adapts to light/dark + the
|
|
374
|
+
* A slot (not a hex) so it adapts to light/dark + the colour themes. Absent = no colour (neutral). */
|
|
353
375
|
colour?: number;
|
|
354
376
|
}
|
|
355
377
|
/**
|
|
@@ -600,6 +622,17 @@ interface CommentMessage {
|
|
|
600
622
|
author: string;
|
|
601
623
|
ts: string;
|
|
602
624
|
body: string;
|
|
625
|
+
/** A TOMBSTONE: the words are gone, the turn in the conversation is not.
|
|
626
|
+
*
|
|
627
|
+
* Removing a reply outright would renumber the argument around it, so what is
|
|
628
|
+
* left records who spoke and when, and that they withdrew it. The `body` is
|
|
629
|
+
* EMPTIED rather than kept and hidden, because "deleted" has to mean gone from
|
|
630
|
+
* a file that lives in version control.
|
|
631
|
+
*
|
|
632
|
+
* This is the one message allowed an empty body: `saveSceneComments` prunes
|
|
633
|
+
* empty messages so a cancelled composer leaves nothing behind, and without
|
|
634
|
+
* this flag a tombstone would be pruned on the way to disk. */
|
|
635
|
+
deleted?: boolean;
|
|
603
636
|
}
|
|
604
637
|
/** A sub-text range a comment is pinned to, within its anchor node's say text (#148). Offsets are
|
|
605
638
|
* character positions over the rendered (plain) source text - inline formatting is marks, not part of
|
|
@@ -819,4 +852,4 @@ declare const DEFAULT_CAPTION_DELIMITERS: CaptionDelimiters;
|
|
|
819
852
|
* captions are off). Applies even to a project that pins no `closedCaptions`. */
|
|
820
853
|
declare const DEFAULT_CAPTION_CHARACTER = "SFX";
|
|
821
854
|
|
|
822
|
-
export { type AuthoringFile, type Beat, type Block, type Bundle, type BundleCastMember, 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_RECORDING_STATUSES, DEFAULT_WRITING_STATUSES, type DocLine, type DocumentationClass, type EditRecord, type Effect, type EstimatingConfig, type Expression, type FlowFile, type FlowNode, type GameData, type GameDataField, type GameDataFieldType, type GameDataFields, type GameDataNodeKind, type GameEventBeat, type GrammaticalGender, type Group, type HostScopeDecl, type HostScopeRegistry, type HostScopeSpec, type Jump, type JumpTarget, type LineBeat, type LocaleFile, PROJECT_LOCALE_SCENE, type ProjectDictionary, type ProjectFile, type PromptBeat, type PropertyDecl, type PropertyType, RERECORD_STATUS, RERECORD_STATUS_DECL, type RecordingFolder, type RecordingStatusDecl, type ScalarValue, type Scene, type Selector, type SelectorExhaust, type SelectorOrder, type SequenceOptions, type Snippet, type Suggestion, type TextBeat, type VcsKind, type WritingStatusDecl, castStringKey, deriveRecordingFolders, effectiveGameId, gameIdify, isContentlessBeat, isValidGameId, walkNodes };
|
|
855
|
+
export { type AuthoringFile, type Beat, type Block, type Bundle, type BundleCastMember, 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_RECORDING_STATUSES, DEFAULT_WRITING_STATUSES, type DocLine, type DocumentationClass, type EditRecord, type Effect, type EstimatingConfig, type Expression, type FlowFile, type FlowNode, type GameData, type GameDataField, type GameDataFieldType, type GameDataFields, type GameDataNodeKind, type GameEventBeat, type GrammaticalGender, type Group, type HostScopeDecl, type HostScopeRegistry, type HostScopeSpec, type Jump, type JumpTarget, type LineBeat, type LocaleFile, PROJECT_LOCALE_SCENE, type ProjectDictionary, type ProjectFile, type PromptBeat, type PropertyDecl, type PropertyType, RERECORD_STATUS, RERECORD_STATUS_DECL, RESERVED_PROPERTY_NAMES, type RecordingFolder, type RecordingStatusDecl, type ScalarValue, type Scene, type Selector, type SelectorExhaust, type SelectorOrder, type SequenceOptions, type Snippet, type Suggestion, type TextBeat, type VcsKind, type WritingStatusDecl, castStringKey, deriveRecordingFolders, effectiveGameId, gameIdify, isCaseOnlyPropertyName, isContentlessBeat, isValidGameId, isValidPropertyName, propertyNameify, walkNodes };
|
package/dist/index.js
CHANGED
|
@@ -19,10 +19,27 @@ function gameIdify(text) {
|
|
|
19
19
|
function isValidGameId(gameId) {
|
|
20
20
|
return /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(gameId);
|
|
21
21
|
}
|
|
22
|
+
var RESERVED_PROPERTY_NAMES = ["true", "false", "and", "or", "not"];
|
|
23
|
+
function propertyNameify(text) {
|
|
24
|
+
const trimmed = text.trim();
|
|
25
|
+
const deliberateLeading = trimmed.startsWith("_");
|
|
26
|
+
let out = trimmed.toLowerCase().replace(/['\u2019]/g, "").replace(/[^a-z0-9_]+/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "");
|
|
27
|
+
if (out === "") return "";
|
|
28
|
+
if (deliberateLeading || /^[0-9]/.test(out)) out = `_${out}`;
|
|
29
|
+
if (RESERVED_PROPERTY_NAMES.includes(out)) out = `${out}_`;
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
32
|
+
function isValidPropertyName(name) {
|
|
33
|
+
return /^[a-z_][a-z0-9_]*$/.test(name) && !RESERVED_PROPERTY_NAMES.includes(name);
|
|
34
|
+
}
|
|
35
|
+
function isCaseOnlyPropertyName(name) {
|
|
36
|
+
return !isValidPropertyName(name) && isValidPropertyName(name.toLowerCase());
|
|
37
|
+
}
|
|
22
38
|
function effectiveGameId(entity) {
|
|
23
39
|
const g = entity.gameId?.trim();
|
|
24
40
|
return g ? g : gameIdify(entity.name);
|
|
25
41
|
}
|
|
42
|
+
var COMMON_GENDERS = ["male", "female", "neuter"];
|
|
26
43
|
var DEFAULT_WRITING_STATUSES = [
|
|
27
44
|
{ name: "stub", colour: 0 },
|
|
28
45
|
// red
|
|
@@ -69,6 +86,7 @@ function castStringKey(name) {
|
|
|
69
86
|
var DEFAULT_CAPTION_DELIMITERS = { open: "[", close: "]" };
|
|
70
87
|
var DEFAULT_CAPTION_CHARACTER = "SFX";
|
|
71
88
|
export {
|
|
89
|
+
COMMON_GENDERS,
|
|
72
90
|
DEFAULT_CAPTION_CHARACTER,
|
|
73
91
|
DEFAULT_CAPTION_DELIMITERS,
|
|
74
92
|
DEFAULT_DOCUMENTATION_CLASSES,
|
|
@@ -77,11 +95,15 @@ export {
|
|
|
77
95
|
PROJECT_LOCALE_SCENE,
|
|
78
96
|
RERECORD_STATUS,
|
|
79
97
|
RERECORD_STATUS_DECL,
|
|
98
|
+
RESERVED_PROPERTY_NAMES,
|
|
80
99
|
castStringKey,
|
|
81
100
|
deriveRecordingFolders,
|
|
82
101
|
effectiveGameId,
|
|
83
102
|
gameIdify,
|
|
103
|
+
isCaseOnlyPropertyName,
|
|
84
104
|
isContentlessBeat,
|
|
85
105
|
isValidGameId,
|
|
106
|
+
isValidPropertyName,
|
|
107
|
+
propertyNameify,
|
|
86
108
|
walkNodes
|
|
87
109
|
};
|
package/package.json
CHANGED