@novely/core 0.29.1 → 0.30.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.d.ts +78 -20
- package/dist/index.global.js +80 -32
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +80 -32
- package/dist/index.js.map +1 -1
- package/package.json +63 -63
- package/dist/chunk-YQR6UQKB.js +0 -403
- package/dist/chunk-YQR6UQKB.js.map +0 -1
- package/dist/utils-RKG56tcx.d.ts +0 -448
- package/dist/utils.d.ts +0 -1
- package/dist/utils.global.js +0 -411
- package/dist/utils.global.js.map +0 -1
- package/dist/utils.js +0 -63
- package/dist/utils.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
type Name<Keys extends string = string> = string | Record<Keys, string>;
|
|
2
|
-
type Emotions<Keys extends string = string> = Record<Keys, string | string[]>;
|
|
3
|
-
type Character<LanguageKeys extends string = string> = {
|
|
4
|
-
name: Name<LanguageKeys>;
|
|
5
|
-
color: string;
|
|
6
|
-
emotions: Emotions;
|
|
7
|
-
};
|
|
8
|
-
|
|
9
1
|
interface LocalStorageStorageSettings {
|
|
10
2
|
key: string;
|
|
11
3
|
}
|
|
@@ -17,7 +9,7 @@ declare const localStorageStorage: (options: LocalStorageStorageSettings) => Sto
|
|
|
17
9
|
|
|
18
10
|
type PluralType = Intl.LDMLPluralRule;
|
|
19
11
|
type Pluralization = Partial<Record<PluralType, string>>;
|
|
20
|
-
type AllowedContent = string | ((state: State) => string | string[]) | string[] | (string | ((state: State) => string | string[]))[];
|
|
12
|
+
type AllowedContent = string | ((state: State | Data) => string | string[]) | string[] | (string | ((state: State | Data) => string | string[]))[];
|
|
21
13
|
type TranslationActions = Partial<Record<string, (str: string) => string>>;
|
|
22
14
|
|
|
23
15
|
declare const RU: {
|
|
@@ -215,6 +207,7 @@ type RendererInit = {
|
|
|
215
207
|
preview: (save: Save<State>, name: string) => Promise<void>;
|
|
216
208
|
removeContext: (name: string) => void;
|
|
217
209
|
getStateFunction: (context: string) => StateFunction<State>;
|
|
210
|
+
getLanguageDisplayName: (lang: Lang) => string;
|
|
218
211
|
};
|
|
219
212
|
|
|
220
213
|
declare const getLanguage: (languages: string[]) => string;
|
|
@@ -236,7 +229,7 @@ type Save<S extends State = State> = [
|
|
|
236
229
|
type Lang = string;
|
|
237
230
|
type TypewriterSpeed = 'Slow' | 'Medium' | 'Fast' | 'Auto';
|
|
238
231
|
type SoundVolume = number;
|
|
239
|
-
type StorageMeta<L extends
|
|
232
|
+
type StorageMeta<L extends Lang = string> = [
|
|
240
233
|
lang: L,
|
|
241
234
|
typewriter_speed: TypewriterSpeed,
|
|
242
235
|
music_volume: SoundVolume,
|
|
@@ -244,7 +237,7 @@ type StorageMeta<L extends string = string> = [
|
|
|
244
237
|
voice_volume: SoundVolume
|
|
245
238
|
];
|
|
246
239
|
type Migration = (save: unknown) => unknown;
|
|
247
|
-
type StorageData<L extends
|
|
240
|
+
type StorageData<L extends Lang = string, D extends Data = Data> = {
|
|
248
241
|
saves: Save[];
|
|
249
242
|
data: D;
|
|
250
243
|
meta: StorageMeta<L>;
|
|
@@ -275,6 +268,10 @@ type TranslationDescription = {
|
|
|
275
268
|
* IETF BCP 47 language tag
|
|
276
269
|
*/
|
|
277
270
|
tag?: string;
|
|
271
|
+
/**
|
|
272
|
+
* Custom name
|
|
273
|
+
*/
|
|
274
|
+
nameOverride?: string;
|
|
278
275
|
plural?: Record<string, Pluralization>;
|
|
279
276
|
actions?: TranslationActions;
|
|
280
277
|
};
|
|
@@ -298,6 +295,36 @@ interface NovelyInit<$Language extends Lang, Characters extends Record<string, C
|
|
|
298
295
|
* ```
|
|
299
296
|
*/
|
|
300
297
|
characters: Characters;
|
|
298
|
+
/**
|
|
299
|
+
* Define default emotions for characters
|
|
300
|
+
* @example
|
|
301
|
+
* ```ts
|
|
302
|
+
* const engine = novely({
|
|
303
|
+
* characters: {
|
|
304
|
+
* Yuki: {
|
|
305
|
+
* name: 'Yuki',
|
|
306
|
+
* color: '#f595f6',
|
|
307
|
+
* emotions: {
|
|
308
|
+
* normal: './normal.png'
|
|
309
|
+
* }
|
|
310
|
+
* }
|
|
311
|
+
* },
|
|
312
|
+
* defaultEmotions: {
|
|
313
|
+
* Yuki: 'normal'
|
|
314
|
+
* }
|
|
315
|
+
* });
|
|
316
|
+
*
|
|
317
|
+
* engine.script({
|
|
318
|
+
* start: [
|
|
319
|
+
* // Without emotion!
|
|
320
|
+
* engine.action.showCharacter('Yuki')
|
|
321
|
+
* ]
|
|
322
|
+
* })
|
|
323
|
+
* ```
|
|
324
|
+
*/
|
|
325
|
+
defaultEmotions?: {
|
|
326
|
+
[Character in keyof NoInfer<Characters>]?: (keyof NoInfer<Characters>[Character]['emotions'] & string);
|
|
327
|
+
};
|
|
301
328
|
/**
|
|
302
329
|
* An object that provides access to the game's storage system.
|
|
303
330
|
* @default localStorage // at key `novely-game-storage`
|
|
@@ -409,12 +436,40 @@ interface NovelyInit<$Language extends Lang, Characters extends Record<string, C
|
|
|
409
436
|
* @default true
|
|
410
437
|
*/
|
|
411
438
|
saveOnUnload?: boolean | 'prod';
|
|
439
|
+
/**
|
|
440
|
+
* The key that signifies the start of the game. It is not recommended to override this parameter.
|
|
441
|
+
*
|
|
442
|
+
* @default 'start'
|
|
443
|
+
* @example
|
|
444
|
+
* ```ts
|
|
445
|
+
* const engine = novely({
|
|
446
|
+
* ...,
|
|
447
|
+
* startKey: 'PART_1'
|
|
448
|
+
* })
|
|
449
|
+
*
|
|
450
|
+
* engine.script({
|
|
451
|
+
* // now game will start from here
|
|
452
|
+
* PART_1: [
|
|
453
|
+
*
|
|
454
|
+
* ]
|
|
455
|
+
* })
|
|
456
|
+
* ```
|
|
457
|
+
*/
|
|
458
|
+
startKey?: 'start' | (string & Record<never, never>);
|
|
412
459
|
}
|
|
413
460
|
type StateFunction<S extends State> = {
|
|
414
461
|
(value: DeepPartial<S> | ((prev: S) => S)): void;
|
|
415
462
|
(): S;
|
|
416
463
|
};
|
|
417
464
|
|
|
465
|
+
type Name<$Lang extends Lang> = string | Record<$Lang, string>;
|
|
466
|
+
type Emotions<Emotion extends string = string> = Record<Emotion, string | string[]>;
|
|
467
|
+
type Character<$Lang extends Lang = string> = {
|
|
468
|
+
name: Name<$Lang>;
|
|
469
|
+
color: string;
|
|
470
|
+
emotions: Emotions;
|
|
471
|
+
};
|
|
472
|
+
|
|
418
473
|
type ValidAction = ['choice', number] | ['clear', Set<keyof DefaultActionProxy>?, Set<string>?, {
|
|
419
474
|
music: Set<string>;
|
|
420
475
|
sounds: Set<string>;
|
|
@@ -515,10 +570,11 @@ type ChoiceCheckFunctionProps<L extends string, S extends State> = {
|
|
|
515
570
|
type ChoiceCheckFunction<L extends string, S extends State> = {
|
|
516
571
|
(props: ChoiceCheckFunctionProps<L, S>): boolean;
|
|
517
572
|
};
|
|
573
|
+
type ConditionCheckFunction<S extends State, R extends string | true | false> = (state: S) => R;
|
|
518
574
|
type FunctionAction<L extends string, S extends State> = (props: FunctionActionProps<L, S>) => Thenable<void>;
|
|
519
575
|
type ActionInputSetup = (input: HTMLInputElement, cleanup: (cb: () => void) => void) => void;
|
|
520
576
|
type BackgroundImage = Partial<Record<'portrait' | 'landscape' | 'all', string>> & Record<string, string>;
|
|
521
|
-
type ActionProxy<Characters extends Record<string, Character>, Languages extends
|
|
577
|
+
type ActionProxy<Characters extends Record<string, Character>, Languages extends Lang, S extends State> = {
|
|
522
578
|
choice: {
|
|
523
579
|
(...choices: [name: TextContent<Languages, S>, actions: ValidAction[], active?: ChoiceCheckFunction<Languages, S>][]): ValidAction;
|
|
524
580
|
(question: TextContent<Languages, S>, ...choices: [name: TextContent<Languages, S>, actions: ValidAction[], active?: ChoiceCheckFunction<Languages, S>][]): ValidAction;
|
|
@@ -527,7 +583,7 @@ type ActionProxy<Characters extends Record<string, Character>, Languages extends
|
|
|
527
583
|
music: Set<string>;
|
|
528
584
|
sounds: Set<string>;
|
|
529
585
|
}) => ValidAction;
|
|
530
|
-
condition: <T extends string | true | false>(condition:
|
|
586
|
+
condition: <T extends string | true | false>(condition: ConditionCheckFunction<S, T>, variants: Record<T extends true ? 'true' : T extends false ? 'false' : T, ValidAction[]>) => ValidAction;
|
|
531
587
|
exit: () => ValidAction;
|
|
532
588
|
dialog: {
|
|
533
589
|
<C extends keyof Characters>(character: C, content: TextContent<Languages, S>, emotion?: keyof Characters[C]['emotions']): ValidAction;
|
|
@@ -553,7 +609,7 @@ type ActionProxy<Characters extends Record<string, Character>, Languages extends
|
|
|
553
609
|
stopVoice: () => ValidAction;
|
|
554
610
|
jump: (scene: string) => ValidAction;
|
|
555
611
|
showCharacter: {
|
|
556
|
-
<C extends keyof Characters>(character: C, emotion
|
|
612
|
+
<C extends keyof Characters>(character: C, emotion?: keyof Characters[C]['emotions'], className?: string, style?: string): ValidAction;
|
|
557
613
|
};
|
|
558
614
|
hideCharacter: (character: keyof Characters, className?: string, style?: string, duration?: number) => ValidAction;
|
|
559
615
|
animateCharacter: (character: keyof Characters, timeout: number, ...classes: string[]) => ValidAction;
|
|
@@ -567,10 +623,12 @@ type ActionProxy<Characters extends Record<string, Character>, Languages extends
|
|
|
567
623
|
preload: (source: string) => ValidAction;
|
|
568
624
|
block: (scene: string) => ValidAction;
|
|
569
625
|
};
|
|
570
|
-
type DefaultActionProxy = ActionProxy<Record<string, Character>,
|
|
626
|
+
type DefaultActionProxy = ActionProxy<Record<string, Character>, Lang, State>;
|
|
571
627
|
type GetActionParameters<T extends Capitalize<keyof DefaultActionProxy>> = Parameters<DefaultActionProxy[Uncapitalize<T>]>;
|
|
572
628
|
|
|
573
|
-
|
|
629
|
+
type ConditionParams<T> = T extends ActionProxy<Record<string, Character>, Lang, infer $State> ? Parameters<ConditionCheckFunction<$State, string | boolean>>[0] : never;
|
|
630
|
+
|
|
631
|
+
declare const novely: <$Language extends string, Characters extends Record<string, Character<$Language>>, StateScheme extends State, DataScheme extends Data>({ characters, defaultEmotions, storage, storageDelay, renderer: createRenderer, initialScreen, translation, state: defaultState, data: defaultData, autosaves, migrations, throttleTimeout, getLanguage, overrideLanguage, askBeforeExit, preloadAssets, parallelAssetsDownloadLimit, fetch: request, saveOnUnload, startKey }: NovelyInit<$Language, Characters, StateScheme, DataScheme>) => {
|
|
574
632
|
/**
|
|
575
633
|
* Function to set game script
|
|
576
634
|
*
|
|
@@ -596,7 +654,7 @@ declare const novely: <Languages extends string, Characters extends Record<strin
|
|
|
596
654
|
* })
|
|
597
655
|
* ```
|
|
598
656
|
*/
|
|
599
|
-
action: ActionProxy<Characters,
|
|
657
|
+
action: ActionProxy<Characters, $Language, StateScheme>;
|
|
600
658
|
/**
|
|
601
659
|
* @deprecated Will be removed BUT replaced with state passed into actions as a parameter
|
|
602
660
|
*/
|
|
@@ -621,7 +679,7 @@ declare const novely: <Languages extends string, Characters extends Record<strin
|
|
|
621
679
|
/**
|
|
622
680
|
* @deprecated Renamed into `templateReplace`
|
|
623
681
|
*/
|
|
624
|
-
unwrap(content: TextContent
|
|
682
|
+
unwrap(content: TextContent<$Language, DataScheme>): string;
|
|
625
683
|
/**
|
|
626
684
|
* Replaces content inside {{braces}} with using global data
|
|
627
685
|
* @example
|
|
@@ -634,7 +692,7 @@ declare const novely: <Languages extends string, Characters extends Record<strin
|
|
|
634
692
|
* })
|
|
635
693
|
* ```
|
|
636
694
|
*/
|
|
637
|
-
templateReplace(content: TextContent
|
|
695
|
+
templateReplace(content: TextContent<$Language, DataScheme>): string;
|
|
638
696
|
/**
|
|
639
697
|
* Cancel data loading, hide UI, ignore page change events
|
|
640
698
|
* Data updates still will work in case Novely already was loaded
|
|
@@ -642,4 +700,4 @@ declare const novely: <Languages extends string, Characters extends Record<strin
|
|
|
642
700
|
destroy(): void;
|
|
643
701
|
};
|
|
644
702
|
|
|
645
|
-
export { type ActionInputOnInputMeta, type ActionInputSetup, type ActionProxy, type AllowedContent, type AudioHandle, type BackgroundImage, type BaseTranslationStrings, type Character, type CharacterHandle, type Context, type CoreData, type CustomHandler, type CustomHandlerFunctionGetFn, type CustomHandlerFunctionParameters, type CustomHandlerGetResult, type CustomHandlerGetResultDataFunction, type Data, type DeepPartial, type DefaultActionProxy, EN, type Emotions, type FunctionableValue, type GetActionParameters, JP, KK, type Lang, type NovelyInit, type NovelyScreen, type Path, type PluralType, type Pluralization, RU, type Renderer, type RendererInit, type Save, type Stack, type StackHolder, type State, type StateFunction, type Storage, type StorageData, type StorageMeta, type Stored, type Story, type TextContent, type Thenable, type TranslationActions, type TypewriterSpeed, type ValidAction, localStorageStorage, novely };
|
|
703
|
+
export { type ActionInputOnInputMeta, type ActionInputSetup, type ActionProxy, type AllowedContent, type AudioHandle, type BackgroundImage, type BaseTranslationStrings, type Character, type CharacterHandle, type ConditionParams, type Context, type CoreData, type CustomHandler, type CustomHandlerFunctionGetFn, type CustomHandlerFunctionParameters, type CustomHandlerGetResult, type CustomHandlerGetResultDataFunction, type Data, type DeepPartial, type DefaultActionProxy, EN, type Emotions, type FunctionableValue, type GetActionParameters, JP, KK, type Lang, type NovelyInit, type NovelyScreen, type Path, type PluralType, type Pluralization, RU, type Renderer, type RendererInit, type Save, type Stack, type StackHolder, type State, type StateFunction, type Storage, type StorageData, type StorageMeta, type Stored, type Story, type TextContent, type Thenable, type TranslationActions, type TypewriterSpeed, type ValidAction, localStorageStorage, novely };
|
package/dist/index.global.js
CHANGED
|
@@ -209,6 +209,7 @@ var Novely = (() => {
|
|
|
209
209
|
|
|
210
210
|
// src/shared.ts
|
|
211
211
|
var STACK_MAP = /* @__PURE__ */ new Map();
|
|
212
|
+
var PRELOADED_ASSETS = /* @__PURE__ */ new Set();
|
|
212
213
|
|
|
213
214
|
// ../../node_modules/.pnpm/esm-env@1.0.0/node_modules/esm-env/prod-ssr.js
|
|
214
215
|
var DEV = false;
|
|
@@ -628,6 +629,19 @@ var Novely = (() => {
|
|
|
628
629
|
}
|
|
629
630
|
return "other";
|
|
630
631
|
};
|
|
632
|
+
var capitalize = (str2) => {
|
|
633
|
+
return str2[0].toUpperCase() + str2.slice(1);
|
|
634
|
+
};
|
|
635
|
+
var getIntlLanguageDisplayName = (lang) => {
|
|
636
|
+
try {
|
|
637
|
+
const intl = new Intl.DisplayNames([lang], {
|
|
638
|
+
type: "language"
|
|
639
|
+
});
|
|
640
|
+
return intl.of(lang) || lang;
|
|
641
|
+
} catch {
|
|
642
|
+
return lang;
|
|
643
|
+
}
|
|
644
|
+
};
|
|
631
645
|
|
|
632
646
|
// ../../node_modules/.pnpm/dequal@2.0.3/node_modules/dequal/lite/index.mjs
|
|
633
647
|
var has = Object.prototype.hasOwnProperty;
|
|
@@ -661,9 +675,6 @@ var Novely = (() => {
|
|
|
661
675
|
return foo !== foo && bar !== bar;
|
|
662
676
|
}
|
|
663
677
|
|
|
664
|
-
// src/global.ts
|
|
665
|
-
var PRELOADED_ASSETS = /* @__PURE__ */ new Set();
|
|
666
|
-
|
|
667
678
|
// src/store.ts
|
|
668
679
|
var store = (current, subscribers = /* @__PURE__ */ new Set()) => {
|
|
669
680
|
const subscribe = (cb) => {
|
|
@@ -688,7 +699,7 @@ var Novely = (() => {
|
|
|
688
699
|
return { subscribe, update, set, get };
|
|
689
700
|
};
|
|
690
701
|
|
|
691
|
-
//
|
|
702
|
+
// ../../node_modules/.pnpm/@novely+deepmerge@0.0.0/node_modules/@novely/deepmerge/dist/index.js
|
|
692
703
|
var { isArray } = Array;
|
|
693
704
|
var { hasOwnProperty, propertyIsEnumerable, getOwnPropertySymbols } = Object;
|
|
694
705
|
var propertyIsOnObject = (object, property) => {
|
|
@@ -811,10 +822,10 @@ var Novely = (() => {
|
|
|
811
822
|
}
|
|
812
823
|
return c;
|
|
813
824
|
};
|
|
814
|
-
var replace = (
|
|
815
|
-
return
|
|
825
|
+
var replace = (input, data, pluralization, actions, pr) => {
|
|
826
|
+
return input.replaceAll(RGX, (x, key, y) => {
|
|
816
827
|
x = 0;
|
|
817
|
-
y =
|
|
828
|
+
y = data;
|
|
818
829
|
const [pathstr, plural, action] = split(key.trim(), ["@", "%"]);
|
|
819
830
|
if (!pathstr) {
|
|
820
831
|
return "";
|
|
@@ -825,7 +836,7 @@ var Novely = (() => {
|
|
|
825
836
|
if (plural && pluralization && y && pr) {
|
|
826
837
|
y = pluralization[plural][pr.select(y)];
|
|
827
838
|
}
|
|
828
|
-
const actionHandler = actions && action
|
|
839
|
+
const actionHandler = actions && action ? actions[action] : void 0;
|
|
829
840
|
if (actionHandler)
|
|
830
841
|
y = actionHandler(y);
|
|
831
842
|
return y == null ? "" : y;
|
|
@@ -853,10 +864,28 @@ var Novely = (() => {
|
|
|
853
864
|
};
|
|
854
865
|
};
|
|
855
866
|
|
|
867
|
+
// src/browser.ts
|
|
868
|
+
var setupBrowserVisibilityChangeListeners = ({ onChange }) => {
|
|
869
|
+
if (typeof document === "undefined")
|
|
870
|
+
return noop;
|
|
871
|
+
const onVisibilityChange = () => {
|
|
872
|
+
if (document.visibilityState === "hidden") {
|
|
873
|
+
onChange();
|
|
874
|
+
}
|
|
875
|
+
};
|
|
876
|
+
addEventListener("visibilitychange", onVisibilityChange);
|
|
877
|
+
addEventListener("beforeunload", onChange);
|
|
878
|
+
return () => {
|
|
879
|
+
removeEventListener("visibilitychange", onVisibilityChange);
|
|
880
|
+
removeEventListener("beforeunload", onChange);
|
|
881
|
+
};
|
|
882
|
+
};
|
|
883
|
+
|
|
856
884
|
// src/novely.ts
|
|
857
885
|
var import_p_limit = __toESM(require_p_limit(), 1);
|
|
858
886
|
var novely = ({
|
|
859
887
|
characters,
|
|
888
|
+
defaultEmotions = {},
|
|
860
889
|
storage = localStorageStorage({ key: "novely-game-storage" }),
|
|
861
890
|
storageDelay = Promise.resolve(),
|
|
862
891
|
renderer: createRenderer,
|
|
@@ -873,7 +902,8 @@ var Novely = (() => {
|
|
|
873
902
|
preloadAssets = "lazy",
|
|
874
903
|
parallelAssetsDownloadLimit = 15,
|
|
875
904
|
fetch: request = fetch,
|
|
876
|
-
saveOnUnload = true
|
|
905
|
+
saveOnUnload = true,
|
|
906
|
+
startKey = "start"
|
|
877
907
|
}) => {
|
|
878
908
|
const languages = Object.keys(translation);
|
|
879
909
|
const limitScript = (0, import_p_limit.default)(1);
|
|
@@ -969,7 +999,7 @@ var Novely = (() => {
|
|
|
969
999
|
const getDefaultSave = (state = {}) => {
|
|
970
1000
|
return [
|
|
971
1001
|
[
|
|
972
|
-
["jump",
|
|
1002
|
+
["jump", startKey],
|
|
973
1003
|
[null, 0]
|
|
974
1004
|
],
|
|
975
1005
|
state,
|
|
@@ -1037,13 +1067,9 @@ var Novely = (() => {
|
|
|
1037
1067
|
};
|
|
1038
1068
|
storageDelay.then(getStoredData);
|
|
1039
1069
|
const initial = getDefaultSave(klona(defaultState));
|
|
1040
|
-
const
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
}
|
|
1044
|
-
};
|
|
1045
|
-
addEventListener("visibilitychange", onVisibilityChange);
|
|
1046
|
-
addEventListener("beforeunload", throttledEmergencyOnStorageDataChange);
|
|
1070
|
+
const unsubscribeFromBrowserVisibilityChange = setupBrowserVisibilityChangeListeners({
|
|
1071
|
+
onChange: throttledEmergencyOnStorageDataChange
|
|
1072
|
+
});
|
|
1047
1073
|
const save = (type) => {
|
|
1048
1074
|
if (!coreData.get().dataLoaded)
|
|
1049
1075
|
return;
|
|
@@ -1097,6 +1123,12 @@ var Novely = (() => {
|
|
|
1097
1123
|
};
|
|
1098
1124
|
let interacted = 0;
|
|
1099
1125
|
const restore = async (save2) => {
|
|
1126
|
+
if (isEmpty(story)) {
|
|
1127
|
+
if (DEV) {
|
|
1128
|
+
throw new Error("Story is empty. You should call an `enine.script` function [https://novely.pages.dev/guide/story.html]");
|
|
1129
|
+
}
|
|
1130
|
+
return;
|
|
1131
|
+
}
|
|
1100
1132
|
if (!coreData.get().dataLoaded)
|
|
1101
1133
|
return;
|
|
1102
1134
|
let latest = save2 || storageData.get().saves.at(-1);
|
|
@@ -1206,20 +1238,26 @@ var Novely = (() => {
|
|
|
1206
1238
|
};
|
|
1207
1239
|
const back = async () => {
|
|
1208
1240
|
const stack = useStack(MAIN_CONTEXT_KEY);
|
|
1241
|
+
const valueBeforeBack = stack.value;
|
|
1209
1242
|
stack.back();
|
|
1243
|
+
if (dequal(valueBeforeBack, stack.value) && !stack.previous) {
|
|
1244
|
+
return;
|
|
1245
|
+
}
|
|
1210
1246
|
await restore(stack.value);
|
|
1211
1247
|
};
|
|
1212
1248
|
const t = (key, lang) => {
|
|
1213
1249
|
return translation[lang].internal[key];
|
|
1214
1250
|
};
|
|
1215
1251
|
const preview = async (save2, name) => {
|
|
1252
|
+
if (isEmpty(story))
|
|
1253
|
+
return;
|
|
1216
1254
|
const [path, data2] = save2;
|
|
1217
1255
|
const { queue } = getActionsFromPath(story, path, true);
|
|
1218
1256
|
const ctx = renderer.getContext(name);
|
|
1219
1257
|
ctx.meta.restoring = true;
|
|
1220
1258
|
ctx.meta.preview = true;
|
|
1221
1259
|
const processor = createQueueProcessor(queue, {
|
|
1222
|
-
skip:
|
|
1260
|
+
skip: EMPTY_SET
|
|
1223
1261
|
});
|
|
1224
1262
|
useStack(ctx).push(klona(save2));
|
|
1225
1263
|
await processor.run(([action2, ...props]) => {
|
|
@@ -1255,6 +1293,13 @@ var Novely = (() => {
|
|
|
1255
1293
|
};
|
|
1256
1294
|
return state;
|
|
1257
1295
|
};
|
|
1296
|
+
const getLanguageDisplayName = (lang) => {
|
|
1297
|
+
const language = translation[lang];
|
|
1298
|
+
if (DEV && !language) {
|
|
1299
|
+
throw new Error(`Attempt to use unsupported language "${language}". Supported languages: ${languages.join(", ")}.`);
|
|
1300
|
+
}
|
|
1301
|
+
return capitalize(language.nameOverride || getIntlLanguageDisplayName(lang));
|
|
1302
|
+
};
|
|
1258
1303
|
const renderer = createRenderer({
|
|
1259
1304
|
mainContextKey: MAIN_CONTEXT_KEY,
|
|
1260
1305
|
characters,
|
|
@@ -1270,7 +1315,8 @@ var Novely = (() => {
|
|
|
1270
1315
|
getStateFunction,
|
|
1271
1316
|
languages,
|
|
1272
1317
|
storageData,
|
|
1273
|
-
coreData
|
|
1318
|
+
coreData,
|
|
1319
|
+
getLanguageDisplayName
|
|
1274
1320
|
});
|
|
1275
1321
|
const useStack = createUseStackFunction(renderer);
|
|
1276
1322
|
useStack(MAIN_CONTEXT_KEY).push(initial);
|
|
@@ -1357,6 +1403,12 @@ var Novely = (() => {
|
|
|
1357
1403
|
push();
|
|
1358
1404
|
},
|
|
1359
1405
|
showCharacter({ ctx, push }, [character, emotion, className, style]) {
|
|
1406
|
+
emotion ??= defaultEmotions[character];
|
|
1407
|
+
if (DEV && !emotion) {
|
|
1408
|
+
throw new Error(`Attemp to show character "${character}" without emotion provided.`);
|
|
1409
|
+
}
|
|
1410
|
+
if (!emotion)
|
|
1411
|
+
return;
|
|
1360
1412
|
if (DEV && !characters[character].emotions[emotion]) {
|
|
1361
1413
|
throw new Error(`Attempt to show character "${character}" with unknown emotion "${emotion}"`);
|
|
1362
1414
|
}
|
|
@@ -1494,11 +1546,7 @@ var Novely = (() => {
|
|
|
1494
1546
|
end({ ctx }) {
|
|
1495
1547
|
if (ctx.meta.preview)
|
|
1496
1548
|
return;
|
|
1497
|
-
|
|
1498
|
-
ctx.clear(EMPTY_SET, EMPTY_SET, { music: EMPTY_SET, sounds: EMPTY_SET }, noop);
|
|
1499
|
-
renderer.ui.showScreen("mainmenu");
|
|
1500
|
-
interactivity(false);
|
|
1501
|
-
times.clear();
|
|
1549
|
+
exit(true);
|
|
1502
1550
|
},
|
|
1503
1551
|
input({ ctx, data: data2, forward }, [question, onInput, setup]) {
|
|
1504
1552
|
ctx.input(
|
|
@@ -1622,6 +1670,11 @@ var Novely = (() => {
|
|
|
1622
1670
|
ctx,
|
|
1623
1671
|
data: stack.value[1]
|
|
1624
1672
|
});
|
|
1673
|
+
} else if (Object.values(story).some((branch) => branch === referred)) {
|
|
1674
|
+
match("end", [], {
|
|
1675
|
+
ctx,
|
|
1676
|
+
data: stack.value[1]
|
|
1677
|
+
});
|
|
1625
1678
|
} else {
|
|
1626
1679
|
match("exit", [], {
|
|
1627
1680
|
ctx,
|
|
@@ -1633,14 +1686,10 @@ var Novely = (() => {
|
|
|
1633
1686
|
interacted = value ? interacted + 1 : 0;
|
|
1634
1687
|
};
|
|
1635
1688
|
const templateReplace = (content, values) => {
|
|
1636
|
-
const {
|
|
1637
|
-
data: data2,
|
|
1638
|
-
meta: [lang]
|
|
1639
|
-
} = storageData.get();
|
|
1689
|
+
const { data: data2, meta: [lang] } = storageData.get();
|
|
1640
1690
|
const obj = values || data2;
|
|
1641
|
-
const cnt = isFunction(content) ? content(obj) : typeof content === "string" ? content : content[lang];
|
|
1642
1691
|
const str2 = flattenAllowedContent(
|
|
1643
|
-
isFunction(
|
|
1692
|
+
!isFunction(content) && !isString(content) ? content[lang] : content,
|
|
1644
1693
|
obj
|
|
1645
1694
|
);
|
|
1646
1695
|
const t2 = translation[lang];
|
|
@@ -1740,8 +1789,7 @@ var Novely = (() => {
|
|
|
1740
1789
|
destroy() {
|
|
1741
1790
|
dataLoaded.cancel();
|
|
1742
1791
|
UIInstance.unmount();
|
|
1743
|
-
|
|
1744
|
-
removeEventListener("beforeunload", throttledEmergencyOnStorageDataChange);
|
|
1792
|
+
unsubscribeFromBrowserVisibilityChange();
|
|
1745
1793
|
}
|
|
1746
1794
|
};
|
|
1747
1795
|
};
|