@novely/core 0.29.1 → 0.29.2

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.js CHANGED
@@ -47,6 +47,7 @@ var MAIN_CONTEXT_KEY = "$MAIN";
47
47
 
48
48
  // src/shared.ts
49
49
  var STACK_MAP = /* @__PURE__ */ new Map();
50
+ var PRELOADED_ASSETS = /* @__PURE__ */ new Set();
50
51
 
51
52
  // src/utils.ts
52
53
  import { DEV } from "esm-env";
@@ -464,13 +465,23 @@ var getResourseType = async (request, url) => {
464
465
  }
465
466
  return "other";
466
467
  };
468
+ var capitalize = (str2) => {
469
+ return str2[0].toUpperCase() + str2.slice(1);
470
+ };
471
+ var getIntlLanguageDisplayName = (lang) => {
472
+ try {
473
+ const intl = new Intl.DisplayNames([lang], {
474
+ type: "language"
475
+ });
476
+ return intl.of(lang) || lang;
477
+ } catch {
478
+ return lang;
479
+ }
480
+ };
467
481
 
468
482
  // src/novely.ts
469
483
  import { dequal } from "dequal/lite";
470
484
 
471
- // src/global.ts
472
- var PRELOADED_ASSETS = /* @__PURE__ */ new Set();
473
-
474
485
  // src/store.ts
475
486
  var store = (current, subscribers = /* @__PURE__ */ new Set()) => {
476
487
  const subscribe = (cb) => {
@@ -506,7 +517,9 @@ var propertyIsOnObject = (object, property) => {
506
517
  }
507
518
  };
508
519
  var propertyIsUnsafe = (target, key) => {
509
- return propertyIsOnObject(target, key) && !(hasOwnProperty.call(target, key) && propertyIsEnumerable.call(target, key));
520
+ return propertyIsOnObject(target, key) && // Properties are safe to merge if they don't exist in the target yet,
521
+ !(hasOwnProperty.call(target, key) && // unsafe if they exist up the prototype chain,
522
+ propertyIsEnumerable.call(target, key));
510
523
  };
511
524
  var getEnumerableOwnPropertySymbols = (target) => {
512
525
  if (!getOwnPropertySymbols)
@@ -618,10 +631,10 @@ var flattenAllowedContent = (c, state) => {
618
631
  }
619
632
  return c;
620
633
  };
621
- var replace = (str2, obj, pluralization, actions, pr) => {
622
- return str2.replaceAll(RGX, (x, key, y) => {
634
+ var replace = (input, data, pluralization, actions, pr) => {
635
+ return input.replaceAll(RGX, (x, key, y) => {
623
636
  x = 0;
624
- y = obj;
637
+ y = data;
625
638
  const [pathstr, plural, action] = split(key.trim(), ["@", "%"]);
626
639
  if (!pathstr) {
627
640
  return "";
@@ -632,7 +645,7 @@ var replace = (str2, obj, pluralization, actions, pr) => {
632
645
  if (plural && pluralization && y && pr) {
633
646
  y = pluralization[plural][pr.select(y)];
634
647
  }
635
- const actionHandler = actions && action && actions[action];
648
+ const actionHandler = actions && action ? actions[action] : void 0;
636
649
  if (actionHandler)
637
650
  y = actionHandler(y);
638
651
  return y == null ? "" : y;
@@ -660,6 +673,23 @@ var localStorageStorage = (options) => {
660
673
  };
661
674
  };
662
675
 
676
+ // src/browser.ts
677
+ var setupBrowserVisibilityChangeListeners = ({ onChange }) => {
678
+ if (typeof document === "undefined")
679
+ return noop;
680
+ const onVisibilityChange = () => {
681
+ if (document.visibilityState === "hidden") {
682
+ onChange();
683
+ }
684
+ };
685
+ addEventListener("visibilitychange", onVisibilityChange);
686
+ addEventListener("beforeunload", onChange);
687
+ return () => {
688
+ removeEventListener("visibilitychange", onVisibilityChange);
689
+ removeEventListener("beforeunload", onChange);
690
+ };
691
+ };
692
+
663
693
  // src/novely.ts
664
694
  import pLimit from "p-limit";
665
695
  import { DEV as DEV2 } from "esm-env";
@@ -681,7 +711,8 @@ var novely = ({
681
711
  preloadAssets = "lazy",
682
712
  parallelAssetsDownloadLimit = 15,
683
713
  fetch: request = fetch,
684
- saveOnUnload = true
714
+ saveOnUnload = true,
715
+ startKey = "start"
685
716
  }) => {
686
717
  const languages = Object.keys(translation);
687
718
  const limitScript = pLimit(1);
@@ -777,7 +808,7 @@ var novely = ({
777
808
  const getDefaultSave = (state = {}) => {
778
809
  return [
779
810
  [
780
- ["jump", "start"],
811
+ ["jump", startKey],
781
812
  [null, 0]
782
813
  ],
783
814
  state,
@@ -845,13 +876,9 @@ var novely = ({
845
876
  };
846
877
  storageDelay.then(getStoredData);
847
878
  const initial = getDefaultSave(klona(defaultState));
848
- const onVisibilityChange = () => {
849
- if (document.visibilityState === "hidden") {
850
- throttledEmergencyOnStorageDataChange();
851
- }
852
- };
853
- addEventListener("visibilitychange", onVisibilityChange);
854
- addEventListener("beforeunload", throttledEmergencyOnStorageDataChange);
879
+ const unsubscribeFromBrowserVisibilityChange = setupBrowserVisibilityChangeListeners({
880
+ onChange: throttledEmergencyOnStorageDataChange
881
+ });
855
882
  const save = (type) => {
856
883
  if (!coreData.get().dataLoaded)
857
884
  return;
@@ -1014,7 +1041,11 @@ var novely = ({
1014
1041
  };
1015
1042
  const back = async () => {
1016
1043
  const stack = useStack(MAIN_CONTEXT_KEY);
1044
+ const valueBeforeBack = stack.value;
1017
1045
  stack.back();
1046
+ if (dequal(valueBeforeBack, stack.value) && !stack.previous) {
1047
+ return;
1048
+ }
1018
1049
  await restore(stack.value);
1019
1050
  };
1020
1051
  const t = (key, lang) => {
@@ -1027,7 +1058,7 @@ var novely = ({
1027
1058
  ctx.meta.restoring = true;
1028
1059
  ctx.meta.preview = true;
1029
1060
  const processor = createQueueProcessor(queue, {
1030
- skip: /* @__PURE__ */ new Set()
1061
+ skip: EMPTY_SET
1031
1062
  });
1032
1063
  useStack(ctx).push(klona(save2));
1033
1064
  await processor.run(([action2, ...props]) => {
@@ -1063,6 +1094,13 @@ var novely = ({
1063
1094
  };
1064
1095
  return state;
1065
1096
  };
1097
+ const getLanguageDisplayName = (lang) => {
1098
+ const language = translation[lang];
1099
+ if (DEV2 && !language) {
1100
+ throw new Error(`Attempt to use unsupported language "${language}". Supported languages: ${languages.join(", ")}.`);
1101
+ }
1102
+ return capitalize(language.nameOverride || getIntlLanguageDisplayName(lang));
1103
+ };
1066
1104
  const renderer = createRenderer({
1067
1105
  mainContextKey: MAIN_CONTEXT_KEY,
1068
1106
  characters,
@@ -1078,7 +1116,8 @@ var novely = ({
1078
1116
  getStateFunction,
1079
1117
  languages,
1080
1118
  storageData,
1081
- coreData
1119
+ coreData,
1120
+ getLanguageDisplayName
1082
1121
  });
1083
1122
  const useStack = createUseStackFunction(renderer);
1084
1123
  useStack(MAIN_CONTEXT_KEY).push(initial);
@@ -1430,6 +1469,11 @@ var novely = ({
1430
1469
  ctx,
1431
1470
  data: stack.value[1]
1432
1471
  });
1472
+ } else if (Object.values(story).some((branch) => branch === referred)) {
1473
+ match("end", [], {
1474
+ ctx,
1475
+ data: stack.value[1]
1476
+ });
1433
1477
  } else {
1434
1478
  match("exit", [], {
1435
1479
  ctx,
@@ -1441,14 +1485,10 @@ var novely = ({
1441
1485
  interacted = value ? interacted + 1 : 0;
1442
1486
  };
1443
1487
  const templateReplace = (content, values) => {
1444
- const {
1445
- data: data2,
1446
- meta: [lang]
1447
- } = storageData.get();
1488
+ const { data: data2, meta: [lang] } = storageData.get();
1448
1489
  const obj = values || data2;
1449
- const cnt = isFunction(content) ? content(obj) : typeof content === "string" ? content : content[lang];
1450
1490
  const str2 = flattenAllowedContent(
1451
- isFunction(cnt) ? cnt(obj) : cnt,
1491
+ !isFunction(content) && !isString(content) ? content[lang] : content,
1452
1492
  obj
1453
1493
  );
1454
1494
  const t2 = translation[lang];
@@ -1548,8 +1588,7 @@ var novely = ({
1548
1588
  destroy() {
1549
1589
  dataLoaded.cancel();
1550
1590
  UIInstance.unmount();
1551
- removeEventListener("visibilitychange", onVisibilityChange);
1552
- removeEventListener("beforeunload", throttledEmergencyOnStorageDataChange);
1591
+ unsubscribeFromBrowserVisibilityChange();
1553
1592
  }
1554
1593
  };
1555
1594
  };