@novely/core 0.40.3 → 0.42.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.js CHANGED
@@ -1,7 +1,8 @@
1
1
  // src/constants.ts
2
- var SKIPPED_DURING_RESTORE = /* @__PURE__ */ new Set(["dialog", "say", "choice", "input", "vibrate", "text"]);
2
+ var SKIPPED_DURING_RESTORE = /* @__PURE__ */ new Set(["dialog", "choice", "input", "vibrate", "text"]);
3
3
  var BLOCK_EXIT_STATEMENTS = /* @__PURE__ */ new Set(["choice:exit", "condition:exit", "block:exit"]);
4
4
  var BLOCK_STATEMENTS = /* @__PURE__ */ new Set(["choice", "condition", "block"]);
5
+ var VIRTUAL_ACTIONS = /* @__PURE__ */ new Set(["say", "choiceExtended"]);
5
6
  var AUDIO_ACTIONS = /* @__PURE__ */ new Set([
6
7
  "playMusic",
7
8
  "stopMusic",
@@ -53,55 +54,6 @@ var ASSETS_TO_PRELOAD = /* @__PURE__ */ new Set();
53
54
 
54
55
  // src/utils.ts
55
56
  import { DEV as DEV2 } from "esm-env";
56
-
57
- // ../../node_modules/.pnpm/klona@2.0.6/node_modules/klona/full/index.mjs
58
- function set(obj, key, val) {
59
- if (typeof val.value === "object") val.value = klona(val.value);
60
- if (!val.enumerable || val.get || val.set || !val.configurable || !val.writable || key === "__proto__") {
61
- Object.defineProperty(obj, key, val);
62
- } else obj[key] = val.value;
63
- }
64
- function klona(x) {
65
- if (typeof x !== "object") return x;
66
- var i = 0, k, list, tmp, str2 = Object.prototype.toString.call(x);
67
- if (str2 === "[object Object]") {
68
- tmp = Object.create(x.__proto__ || null);
69
- } else if (str2 === "[object Array]") {
70
- tmp = Array(x.length);
71
- } else if (str2 === "[object Set]") {
72
- tmp = /* @__PURE__ */ new Set();
73
- x.forEach(function(val) {
74
- tmp.add(klona(val));
75
- });
76
- } else if (str2 === "[object Map]") {
77
- tmp = /* @__PURE__ */ new Map();
78
- x.forEach(function(val, key) {
79
- tmp.set(klona(key), klona(val));
80
- });
81
- } else if (str2 === "[object Date]") {
82
- tmp = /* @__PURE__ */ new Date(+x);
83
- } else if (str2 === "[object RegExp]") {
84
- tmp = new RegExp(x.source, x.flags);
85
- } else if (str2 === "[object DataView]") {
86
- tmp = new x.constructor(klona(x.buffer));
87
- } else if (str2 === "[object ArrayBuffer]") {
88
- tmp = x.slice(0);
89
- } else if (str2.slice(-6) === "Array]") {
90
- tmp = new x.constructor(x);
91
- }
92
- if (tmp) {
93
- for (list = Object.getOwnPropertySymbols(x); i < list.length; i++) {
94
- set(tmp, list[i], Object.getOwnPropertyDescriptor(x, list[i]));
95
- }
96
- for (i = 0, list = Object.getOwnPropertyNames(x); i < list.length; i++) {
97
- if (Object.hasOwnProperty.call(tmp, k = list[i]) && tmp[k] === x[k]) continue;
98
- set(tmp, k, Object.getOwnPropertyDescriptor(x, k));
99
- }
100
- }
101
- return tmp || x;
102
- }
103
-
104
- // src/utils.ts
105
57
  import { memoize as memoize2 } from "es-toolkit/function";
106
58
 
107
59
  // src/asset.ts
@@ -239,13 +191,11 @@ var isAsset = (suspect) => {
239
191
  var matchAction = ({ getContext, onBeforeActionCall, push, forward }, values) => {
240
192
  return (action, props, { ctx, data }) => {
241
193
  const context = typeof ctx === "string" ? getContext(ctx) : ctx;
242
- if (action !== "say") {
243
- onBeforeActionCall({
244
- action,
245
- props,
246
- ctx: context
247
- });
248
- }
194
+ onBeforeActionCall({
195
+ action,
196
+ props,
197
+ ctx: context
198
+ });
249
199
  return values[action]({
250
200
  ctx: context,
251
201
  data,
@@ -733,7 +683,7 @@ var nextPath = (path) => {
733
683
  var isBlockingAction = (action) => {
734
684
  return isUserRequiredAction(action) || isSkippedDuringRestore(action[0]) && action[0] !== "vibrate";
735
685
  };
736
- var collectActionsBeforeBlockingAction = ({ path, refer }) => {
686
+ var collectActionsBeforeBlockingAction = ({ path, refer, clone }) => {
737
687
  const collection = [];
738
688
  let action = refer(path);
739
689
  while (true) {
@@ -756,11 +706,12 @@ var collectActionsBeforeBlockingAction = ({ path, refer }) => {
756
706
  for (let i = 0; i < choiceProps.length; i++) {
757
707
  const branchContent = choiceProps[i];
758
708
  if (!Array.isArray(branchContent)) continue;
759
- const virtualPath = klona(path);
709
+ const virtualPath = clone(path);
760
710
  virtualPath.push(["choice", i], [null, 0]);
761
711
  const innerActions = collectActionsBeforeBlockingAction({
762
712
  path: virtualPath,
763
- refer
713
+ refer,
714
+ clone
764
715
  });
765
716
  collection.push(...innerActions);
766
717
  }
@@ -768,11 +719,12 @@ var collectActionsBeforeBlockingAction = ({ path, refer }) => {
768
719
  const conditionProps = props;
769
720
  const conditions = Object.keys(conditionProps[1]);
770
721
  for (const condition of conditions) {
771
- const virtualPath = klona(path);
722
+ const virtualPath = clone(path);
772
723
  virtualPath.push(["condition", condition], [null, 0]);
773
724
  const innerActions = collectActionsBeforeBlockingAction({
774
725
  path: virtualPath,
775
- refer
726
+ refer,
727
+ clone
776
728
  });
777
729
  collection.push(...innerActions);
778
730
  }
@@ -854,6 +806,53 @@ var store = (current, subscribers = /* @__PURE__ */ new Set()) => {
854
806
  return { subscribe, update, set: set2, get };
855
807
  };
856
808
 
809
+ // ../../node_modules/.pnpm/klona@2.0.6/node_modules/klona/full/index.mjs
810
+ function set(obj, key, val) {
811
+ if (typeof val.value === "object") val.value = klona(val.value);
812
+ if (!val.enumerable || val.get || val.set || !val.configurable || !val.writable || key === "__proto__") {
813
+ Object.defineProperty(obj, key, val);
814
+ } else obj[key] = val.value;
815
+ }
816
+ function klona(x) {
817
+ if (typeof x !== "object") return x;
818
+ var i = 0, k, list, tmp, str2 = Object.prototype.toString.call(x);
819
+ if (str2 === "[object Object]") {
820
+ tmp = Object.create(x.__proto__ || null);
821
+ } else if (str2 === "[object Array]") {
822
+ tmp = Array(x.length);
823
+ } else if (str2 === "[object Set]") {
824
+ tmp = /* @__PURE__ */ new Set();
825
+ x.forEach(function(val) {
826
+ tmp.add(klona(val));
827
+ });
828
+ } else if (str2 === "[object Map]") {
829
+ tmp = /* @__PURE__ */ new Map();
830
+ x.forEach(function(val, key) {
831
+ tmp.set(klona(key), klona(val));
832
+ });
833
+ } else if (str2 === "[object Date]") {
834
+ tmp = /* @__PURE__ */ new Date(+x);
835
+ } else if (str2 === "[object RegExp]") {
836
+ tmp = new RegExp(x.source, x.flags);
837
+ } else if (str2 === "[object DataView]") {
838
+ tmp = new x.constructor(klona(x.buffer));
839
+ } else if (str2 === "[object ArrayBuffer]") {
840
+ tmp = x.slice(0);
841
+ } else if (str2.slice(-6) === "Array]") {
842
+ tmp = new x.constructor(x);
843
+ }
844
+ if (tmp) {
845
+ for (list = Object.getOwnPropertySymbols(x); i < list.length; i++) {
846
+ set(tmp, list[i], Object.getOwnPropertyDescriptor(x, list[i]));
847
+ }
848
+ for (i = 0, list = Object.getOwnPropertyNames(x); i < list.length; i++) {
849
+ if (Object.hasOwnProperty.call(tmp, k = list[i]) && tmp[k] === x[k]) continue;
850
+ set(tmp, k, Object.getOwnPropertyDescriptor(x, k));
851
+ }
852
+ }
853
+ return tmp || x;
854
+ }
855
+
857
856
  // src/translation.ts
858
857
  var RGX = /{{(.*?)}}/g;
859
858
  var split = (input, delimeters) => {
@@ -1103,6 +1102,14 @@ var huntAssets = ({ volume, lang, mode, characters, action, props, handle }) =>
1103
1102
  }
1104
1103
  return;
1105
1104
  }
1105
+ if (action === "choice") {
1106
+ for (let i = 1; i < props.length; i++) {
1107
+ const data = props[i];
1108
+ if (Array.isArray(data)) {
1109
+ handle(handleImageAsset(data[4]));
1110
+ }
1111
+ }
1112
+ }
1106
1113
  };
1107
1114
 
1108
1115
  // src/novely.ts
@@ -1126,6 +1133,7 @@ var novely = ({
1126
1133
  preloadAssets = "lazy",
1127
1134
  parallelAssetsDownloadLimit = 15,
1128
1135
  fetch: request = fetch,
1136
+ cloneFunction: clone = klona,
1129
1137
  saveOnUnload = true,
1130
1138
  startKey = "start"
1131
1139
  }) => {
@@ -1178,6 +1186,28 @@ var novely = ({
1178
1186
  return renderer.actions[action2];
1179
1187
  }
1180
1188
  return (...props) => {
1189
+ if (VIRTUAL_ACTIONS.has(action2)) {
1190
+ if (action2 === "say") {
1191
+ action2 = "dialog";
1192
+ const [character] = props;
1193
+ if (DEV3 && !characters[character]) {
1194
+ throw new Error(`Attempt to call Say action with unknown character "${character}"`);
1195
+ }
1196
+ } else if (action2 === "choiceExtended") {
1197
+ action2 = "choice";
1198
+ const choices = props[1];
1199
+ const mappedChoices = choices.map((choice) => [
1200
+ choice.title,
1201
+ choice.children,
1202
+ choice.active,
1203
+ choice.visible,
1204
+ choice.image
1205
+ ]);
1206
+ for (let i = 0; i < mappedChoices.length; i++) {
1207
+ props[i + 1] = mappedChoices[i];
1208
+ }
1209
+ }
1210
+ }
1181
1211
  if (preloadAssets === "blocking") {
1182
1212
  huntAssets({
1183
1213
  action: action2,
@@ -1193,7 +1223,7 @@ var novely = ({
1193
1223
  };
1194
1224
  }
1195
1225
  });
1196
- const getDefaultSave = (state = {}) => {
1226
+ const getDefaultSave = (state) => {
1197
1227
  return [
1198
1228
  [
1199
1229
  ["jump", startKey],
@@ -1215,7 +1245,7 @@ var novely = ({
1215
1245
  };
1216
1246
  const initialData = {
1217
1247
  saves: [],
1218
- data: klona(defaultData),
1248
+ data: clone(defaultData),
1219
1249
  meta: [getLanguageWithoutParameters(), DEFAULT_TYPEWRITER_SPEED, 1, 1, 1]
1220
1250
  };
1221
1251
  const storageData = store(initialData);
@@ -1265,7 +1295,7 @@ var novely = ({
1265
1295
  storageData.set(stored);
1266
1296
  };
1267
1297
  storageDelay.then(getStoredData);
1268
- const initial = getDefaultSave(klona(defaultState));
1298
+ const initial = getDefaultSave(clone(defaultState));
1269
1299
  const unsubscribeFromBrowserVisibilityChange = setupBrowserVisibilityChangeListeners({
1270
1300
  onChange: throttledEmergencyOnStorageDataChange
1271
1301
  });
@@ -1273,7 +1303,7 @@ var novely = ({
1273
1303
  if (!coreData.get().dataLoaded) return;
1274
1304
  if (!autosaves && type === "auto") return;
1275
1305
  const stack = useStack(MAIN_CONTEXT_KEY);
1276
- const current = klona(stack.value);
1306
+ const current = clone(stack.value);
1277
1307
  storageData.update((prev) => {
1278
1308
  const replace2 = () => {
1279
1309
  prev.saves[prev.saves.length - 1] = current;
@@ -1303,7 +1333,7 @@ var novely = ({
1303
1333
  };
1304
1334
  const newGame = () => {
1305
1335
  if (!coreData.get().dataLoaded) return;
1306
- const save2 = getDefaultSave(klona(defaultState));
1336
+ const save2 = getDefaultSave(clone(defaultState));
1307
1337
  if (autosaves) {
1308
1338
  storageData.update((prev) => {
1309
1339
  return prev.saves.push(save2), prev;
@@ -1332,7 +1362,7 @@ var novely = ({
1332
1362
  if (!coreData.get().dataLoaded) return;
1333
1363
  let latest = save2 || storageData.get().saves.at(-1);
1334
1364
  if (!latest) {
1335
- latest = klona(initial);
1365
+ latest = clone(initial);
1336
1366
  storageData.update((prev) => {
1337
1367
  prev.saves.push(latest);
1338
1368
  return prev;
@@ -1444,7 +1474,7 @@ var novely = ({
1444
1474
  const processor = createQueueProcessor(queue, {
1445
1475
  skip: EMPTY_SET
1446
1476
  });
1447
- useStack(ctx).push(klona(save2));
1477
+ useStack(ctx).push(clone(save2));
1448
1478
  const assets = [];
1449
1479
  await processor.run(([action2, ...props]) => {
1450
1480
  if (isAudioAction(action2)) return;
@@ -1539,7 +1569,7 @@ var novely = ({
1539
1569
  const enmemory = (ctx) => {
1540
1570
  if (ctx.meta.restoring) return;
1541
1571
  const stack = useStack(ctx);
1542
- const current = klona(stack.value);
1572
+ const current = clone(stack.value);
1543
1573
  current[2][1] = "auto";
1544
1574
  stack.push(current);
1545
1575
  save("auto");
@@ -1567,8 +1597,9 @@ var novely = ({
1567
1597
  if (!isBlockingAction([action2, ...props])) return;
1568
1598
  try {
1569
1599
  const collection = collectActionsBeforeBlockingAction({
1570
- path: nextPath(klona(useStack(ctx).value[0])),
1571
- refer
1600
+ path: nextPath(clone(useStack(ctx).value[0])),
1601
+ refer,
1602
+ clone
1572
1603
  });
1573
1604
  for (const [action3, ...props2] of collection) {
1574
1605
  huntAssets({
@@ -1686,15 +1717,6 @@ var novely = ({
1686
1717
  forward
1687
1718
  );
1688
1719
  },
1689
- say({ ctx, data: data2 }, [character, content]) {
1690
- if (DEV3 && !characters[character]) {
1691
- throw new Error(`Attempt to call Say action with unknown character "${character}"`);
1692
- }
1693
- match("dialog", [character, content], {
1694
- ctx,
1695
- data: data2
1696
- });
1697
- },
1698
1720
  function({ ctx, push }, [fn]) {
1699
1721
  const { restoring, goingBack, preview: preview2 } = ctx.meta;
1700
1722
  const result = fn({
@@ -1715,15 +1737,20 @@ var novely = ({
1715
1737
  choices.unshift(question);
1716
1738
  question = "";
1717
1739
  }
1718
- const transformedChoices = choices.map(([content, action2, visible]) => {
1719
- const shown = !visible || visible({
1740
+ const transformedChoices = choices.map(([content, action2, active, visible, image]) => {
1741
+ const activeValue = !active || active({
1742
+ lang: getLanguageFromStore(storageData),
1743
+ state: getStateAtCtx(ctx)
1744
+ });
1745
+ const visibleValue = !visible || visible({
1720
1746
  lang: getLanguageFromStore(storageData),
1721
1747
  state: getStateAtCtx(ctx)
1722
1748
  });
1723
- if (DEV3 && action2.length === 0 && !shown) {
1749
+ const imageValue = image ? handleImageAsset(image) : "";
1750
+ if (DEV3 && action2.length === 0 && (!activeValue && !visibleValue)) {
1724
1751
  console.warn(`Choice children should not be empty, either add content there or make item not selectable`);
1725
1752
  }
1726
- return [templateReplace(content, data2), shown];
1753
+ return [templateReplace(content, data2), activeValue, visibleValue, imageValue];
1727
1754
  });
1728
1755
  if (DEV3 && transformedChoices.length === 0) {
1729
1756
  throw new Error(`Running choice without variants to choose from, look at how to use Choice action properly [https://novely.pages.dev/guide/actions/choice#usage]`);
@@ -1950,7 +1977,7 @@ var novely = ({
1950
1977
  c: null
1951
1978
  };
1952
1979
  const getCurrentStorageData = () => {
1953
- return coreData.get().dataLoaded ? klona(storageData.get()) : null;
1980
+ return coreData.get().dataLoaded ? clone(storageData.get()) : null;
1954
1981
  };
1955
1982
  const setStorageData = (data2) => {
1956
1983
  if (destroyed) {