@novely/core 0.48.0 → 0.49.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 +51 -2
- package/dist/index.global.js +145 -65
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +177 -96
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// src/novely.ts
|
|
2
2
|
import { dequal } from "dequal/lite";
|
|
3
|
-
import { throttle } from "es-toolkit/function";
|
|
3
|
+
import { memoize as memoize4, throttle } from "es-toolkit/function";
|
|
4
4
|
import { merge as deepmerge } from "es-toolkit/object";
|
|
5
|
-
import { DEV as
|
|
5
|
+
import { DEV as DEV5 } from "esm-env";
|
|
6
6
|
|
|
7
7
|
// ../../node_modules/.pnpm/klona@2.0.6/node_modules/klona/full/index.mjs
|
|
8
8
|
function set(obj, key, val) {
|
|
@@ -245,6 +245,7 @@ var getVolumeFromStore = (store2) => {
|
|
|
245
245
|
};
|
|
246
246
|
|
|
247
247
|
// src/utilities/actions-processing.ts
|
|
248
|
+
import { DEV as DEV2 } from "esm-env";
|
|
248
249
|
var isExitImpossible = (path) => {
|
|
249
250
|
const blockStatements = path.filter(([item]) => isBlockStatement(item));
|
|
250
251
|
const blockExitStatements = path.filter(([item]) => isBlockExitStatement(item));
|
|
@@ -256,40 +257,66 @@ var isExitImpossible = (path) => {
|
|
|
256
257
|
}
|
|
257
258
|
return !blockExitStatements.every(([name], i) => name && name.startsWith(blockStatements[i][0]));
|
|
258
259
|
};
|
|
259
|
-
var createReferFunction = (story) => {
|
|
260
|
-
const refer = (path) => {
|
|
260
|
+
var createReferFunction = ({ story, onUnknownSceneHit }) => {
|
|
261
|
+
const refer = async (path) => {
|
|
262
|
+
const { promise: ready, resolve: setReady } = Promise.withResolvers();
|
|
261
263
|
let current = story;
|
|
262
264
|
let precurrent = story;
|
|
263
265
|
const blocks = [];
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
266
|
+
const refer2 = async () => {
|
|
267
|
+
for (const [type, val] of path) {
|
|
268
|
+
if (type === "jump") {
|
|
269
|
+
if (!current[val]) {
|
|
270
|
+
setReady(true);
|
|
271
|
+
await onUnknownSceneHit(val);
|
|
272
|
+
}
|
|
273
|
+
if (DEV2 && !story[val]) {
|
|
274
|
+
throw new Error(`Attempt to jump to unknown scene "${val}"`);
|
|
275
|
+
}
|
|
276
|
+
if (DEV2 && story[val].length === 0) {
|
|
277
|
+
throw new Error(`Attempt to jump to empty scene "${val}"`);
|
|
278
|
+
}
|
|
279
|
+
precurrent = story;
|
|
280
|
+
current = current[val];
|
|
281
|
+
} else if (type === null) {
|
|
282
|
+
precurrent = current;
|
|
283
|
+
current = current[val];
|
|
284
|
+
} else if (type === "choice") {
|
|
285
|
+
blocks.push(precurrent);
|
|
286
|
+
current = current[val + 1][1];
|
|
287
|
+
} else if (type === "condition") {
|
|
288
|
+
blocks.push(precurrent);
|
|
289
|
+
current = current[2][val];
|
|
290
|
+
} else if (type === "block") {
|
|
291
|
+
blocks.push(precurrent);
|
|
292
|
+
current = story[val];
|
|
293
|
+
} else if (type === "block:exit" || type === "choice:exit" || type === "condition:exit") {
|
|
294
|
+
current = blocks.pop();
|
|
295
|
+
}
|
|
282
296
|
}
|
|
283
|
-
|
|
284
|
-
|
|
297
|
+
setReady(false);
|
|
298
|
+
return current;
|
|
299
|
+
};
|
|
300
|
+
const value = refer2();
|
|
301
|
+
const found = await ready;
|
|
302
|
+
return {
|
|
303
|
+
found,
|
|
304
|
+
value
|
|
305
|
+
};
|
|
306
|
+
};
|
|
307
|
+
const referGuarded = async (path) => {
|
|
308
|
+
return await (await refer(path)).value;
|
|
309
|
+
};
|
|
310
|
+
return {
|
|
311
|
+
refer,
|
|
312
|
+
referGuarded
|
|
285
313
|
};
|
|
286
|
-
return refer;
|
|
287
314
|
};
|
|
288
|
-
var exitPath = ({ path, refer, onExitImpossible }) => {
|
|
315
|
+
var exitPath = async ({ path, refer, onExitImpossible }) => {
|
|
289
316
|
const last = path.at(-1);
|
|
290
317
|
const ignore = [];
|
|
291
318
|
let wasExitImpossible = false;
|
|
292
|
-
if (!isAction(refer(path))) {
|
|
319
|
+
if (!isAction(await refer(path))) {
|
|
293
320
|
if (last && isNull(last[0]) && isNumber(last[1])) {
|
|
294
321
|
last[1]--;
|
|
295
322
|
} else {
|
|
@@ -297,7 +324,7 @@ var exitPath = ({ path, refer, onExitImpossible }) => {
|
|
|
297
324
|
}
|
|
298
325
|
}
|
|
299
326
|
if (isExitImpossible(path)) {
|
|
300
|
-
const referred = refer(path);
|
|
327
|
+
const referred = await refer(path);
|
|
301
328
|
if (isAction(referred) && isSkippedDuringRestore(referred[0])) {
|
|
302
329
|
onExitImpossible?.();
|
|
303
330
|
}
|
|
@@ -319,7 +346,7 @@ var exitPath = ({ path, refer, onExitImpossible }) => {
|
|
|
319
346
|
path.push([`${name}:exit`]);
|
|
320
347
|
const prev = findLastPathItemBeforeItemOfType(path.slice(0, i + 1), name);
|
|
321
348
|
if (prev) path.push([null, prev[1] + 1]);
|
|
322
|
-
if (!isAction(refer(path))) {
|
|
349
|
+
if (!isAction(await refer(path))) {
|
|
323
350
|
path.pop();
|
|
324
351
|
continue;
|
|
325
352
|
}
|
|
@@ -338,12 +365,16 @@ var nextPath = (path) => {
|
|
|
338
365
|
}
|
|
339
366
|
return path;
|
|
340
367
|
};
|
|
341
|
-
var collectActionsBeforeBlockingAction = ({
|
|
368
|
+
var collectActionsBeforeBlockingAction = async ({
|
|
369
|
+
path,
|
|
370
|
+
refer,
|
|
371
|
+
clone
|
|
372
|
+
}) => {
|
|
342
373
|
const collection = [];
|
|
343
|
-
let action = refer(path);
|
|
374
|
+
let action = await refer(path);
|
|
344
375
|
while (true) {
|
|
345
376
|
if (action == void 0) {
|
|
346
|
-
const { exitImpossible } = exitPath({
|
|
377
|
+
const { exitImpossible } = await exitPath({
|
|
347
378
|
path,
|
|
348
379
|
refer
|
|
349
380
|
});
|
|
@@ -363,7 +394,7 @@ var collectActionsBeforeBlockingAction = ({ path, refer, clone }) => {
|
|
|
363
394
|
if (!Array.isArray(branchContent)) continue;
|
|
364
395
|
const virtualPath = clone(path);
|
|
365
396
|
virtualPath.push(["choice", i], [null, 0]);
|
|
366
|
-
const innerActions = collectActionsBeforeBlockingAction({
|
|
397
|
+
const innerActions = await collectActionsBeforeBlockingAction({
|
|
367
398
|
path: virtualPath,
|
|
368
399
|
refer,
|
|
369
400
|
clone
|
|
@@ -376,7 +407,7 @@ var collectActionsBeforeBlockingAction = ({ path, refer, clone }) => {
|
|
|
376
407
|
for (const condition of conditions) {
|
|
377
408
|
const virtualPath = clone(path);
|
|
378
409
|
virtualPath.push(["condition", condition], [null, 0]);
|
|
379
|
-
const innerActions = collectActionsBeforeBlockingAction({
|
|
410
|
+
const innerActions = await collectActionsBeforeBlockingAction({
|
|
380
411
|
path: virtualPath,
|
|
381
412
|
refer,
|
|
382
413
|
clone
|
|
@@ -397,7 +428,7 @@ var collectActionsBeforeBlockingAction = ({ path, refer, clone }) => {
|
|
|
397
428
|
} else {
|
|
398
429
|
nextPath(path);
|
|
399
430
|
}
|
|
400
|
-
action = refer(path);
|
|
431
|
+
action = await refer(path);
|
|
401
432
|
}
|
|
402
433
|
return collection;
|
|
403
434
|
};
|
|
@@ -417,7 +448,7 @@ var getOppositeAction = (action) => {
|
|
|
417
448
|
};
|
|
418
449
|
return MAP[action];
|
|
419
450
|
};
|
|
420
|
-
var getActionsFromPath = (story, path, filter) => {
|
|
451
|
+
var getActionsFromPath = async ({ story, path, filter, referGuarded }) => {
|
|
421
452
|
let current = story;
|
|
422
453
|
let precurrent;
|
|
423
454
|
let ignoreNestedBefore = null;
|
|
@@ -432,6 +463,7 @@ var getActionsFromPath = (story, path, filter) => {
|
|
|
432
463
|
}, 0);
|
|
433
464
|
const queue = [];
|
|
434
465
|
const blocks = [];
|
|
466
|
+
await referGuarded(path);
|
|
435
467
|
for (const [type, val] of path) {
|
|
436
468
|
if (type === "jump") {
|
|
437
469
|
precurrent = story;
|
|
@@ -575,7 +607,7 @@ var createQueueProcessor = (queue, options) => {
|
|
|
575
607
|
}
|
|
576
608
|
}
|
|
577
609
|
const run = async (match) => {
|
|
578
|
-
for
|
|
610
|
+
for (const item of processedQueue) {
|
|
579
611
|
const result = match(item);
|
|
580
612
|
if (isPromise(result)) {
|
|
581
613
|
await result;
|
|
@@ -619,13 +651,13 @@ var createControlledPromise = () => {
|
|
|
619
651
|
|
|
620
652
|
// src/utilities/resources.ts
|
|
621
653
|
import { memoize as memoize2 } from "es-toolkit/function";
|
|
622
|
-
import { DEV as
|
|
654
|
+
import { DEV as DEV3 } from "esm-env";
|
|
623
655
|
var getUrlFileExtension = (address) => {
|
|
624
656
|
try {
|
|
625
657
|
const { pathname } = new URL(address, location.href);
|
|
626
658
|
return pathname.split(".").at(-1).split("!")[0].split(":")[0];
|
|
627
659
|
} catch (error) {
|
|
628
|
-
if (
|
|
660
|
+
if (DEV3) {
|
|
629
661
|
console.error(new Error(`Could not construct URL "${address}".`, { cause: error }));
|
|
630
662
|
}
|
|
631
663
|
return "";
|
|
@@ -638,7 +670,7 @@ var fetchContentType = async (url, request) => {
|
|
|
638
670
|
});
|
|
639
671
|
return response.headers.get("Content-Type") || "";
|
|
640
672
|
} catch (error) {
|
|
641
|
-
if (
|
|
673
|
+
if (DEV3) {
|
|
642
674
|
console.error(new Error(`Failed to fetch file at "${url}"`, { cause: error }));
|
|
643
675
|
}
|
|
644
676
|
return "";
|
|
@@ -1031,7 +1063,7 @@ var replace = (input, data, pluralization, actions, pr) => {
|
|
|
1031
1063
|
};
|
|
1032
1064
|
|
|
1033
1065
|
// src/utilities/actions.ts
|
|
1034
|
-
import { DEV as
|
|
1066
|
+
import { DEV as DEV4 } from "esm-env";
|
|
1035
1067
|
var VIRTUAL_ACTIONS = ["say"];
|
|
1036
1068
|
var buildActionObject = ({
|
|
1037
1069
|
rendererActions,
|
|
@@ -1047,7 +1079,7 @@ var buildActionObject = ({
|
|
|
1047
1079
|
if (action === "say") {
|
|
1048
1080
|
action = "dialog";
|
|
1049
1081
|
const [character] = props;
|
|
1050
|
-
if (
|
|
1082
|
+
if (DEV4 && !characters[character]) {
|
|
1051
1083
|
throw new Error(`Attempt to call Say action with unknown character "${character}"`);
|
|
1052
1084
|
}
|
|
1053
1085
|
} else if (action === "choice") {
|
|
@@ -1118,7 +1150,8 @@ var novely = ({
|
|
|
1118
1150
|
cloneFunction: clone = klona,
|
|
1119
1151
|
saveOnUnload = true,
|
|
1120
1152
|
startKey = "start",
|
|
1121
|
-
defaultTypewriterSpeed = DEFAULT_TYPEWRITER_SPEED
|
|
1153
|
+
defaultTypewriterSpeed = DEFAULT_TYPEWRITER_SPEED,
|
|
1154
|
+
storyOptions = { mode: "static" }
|
|
1122
1155
|
}) => {
|
|
1123
1156
|
const languages = Object.keys(translation);
|
|
1124
1157
|
const limitScript = pLimit(1);
|
|
@@ -1128,21 +1161,27 @@ var novely = ({
|
|
|
1128
1161
|
const dataLoaded = createControlledPromise();
|
|
1129
1162
|
let initialScreenWasShown = false;
|
|
1130
1163
|
let destroyed = false;
|
|
1164
|
+
if (storyOptions.mode === "dynamic") {
|
|
1165
|
+
storyOptions.preloadSaves ??= 4;
|
|
1166
|
+
}
|
|
1167
|
+
const storyLoad = storyOptions.mode === "static" ? noop : storyOptions.load;
|
|
1168
|
+
const onUnknownSceneHit = memoize4(async (scene) => {
|
|
1169
|
+
const part = await storyLoad(scene);
|
|
1170
|
+
if (part) {
|
|
1171
|
+
await script(part);
|
|
1172
|
+
}
|
|
1173
|
+
});
|
|
1131
1174
|
const intime = (value) => {
|
|
1132
1175
|
return times.add(value), value;
|
|
1133
1176
|
};
|
|
1134
1177
|
const scriptBase = async (part) => {
|
|
1135
1178
|
if (destroyed) return;
|
|
1136
1179
|
Object.assign(story, flatStory(part));
|
|
1137
|
-
let loadingIsShown = false;
|
|
1138
1180
|
if (!initialScreenWasShown) {
|
|
1139
1181
|
renderer.ui.showLoading();
|
|
1140
|
-
loadingIsShown = true;
|
|
1141
1182
|
}
|
|
1142
1183
|
if (preloadAssets === "blocking" && ASSETS_TO_PRELOAD.size > 0) {
|
|
1143
|
-
|
|
1144
|
-
renderer.ui.showLoading();
|
|
1145
|
-
}
|
|
1184
|
+
renderer.ui.showLoading();
|
|
1146
1185
|
await handleAssetsPreloading({
|
|
1147
1186
|
...renderer.misc,
|
|
1148
1187
|
limiter: limitAssetsDownload,
|
|
@@ -1179,7 +1218,7 @@ var novely = ({
|
|
|
1179
1218
|
if (languages.includes(language)) {
|
|
1180
1219
|
return language;
|
|
1181
1220
|
}
|
|
1182
|
-
if (
|
|
1221
|
+
if (DEV5) {
|
|
1183
1222
|
throw new Error(
|
|
1184
1223
|
`Attempt to use unsupported language "${language}". Supported languages: ${languages.join(", ")}.`
|
|
1185
1224
|
);
|
|
@@ -1195,11 +1234,23 @@ var novely = ({
|
|
|
1195
1234
|
const coreData = store({
|
|
1196
1235
|
dataLoaded: false
|
|
1197
1236
|
});
|
|
1198
|
-
const onDataLoadedPromise = ({ cancelled }) => {
|
|
1237
|
+
const onDataLoadedPromise = async ({ cancelled }) => {
|
|
1199
1238
|
if (cancelled) {
|
|
1200
1239
|
dataLoaded.promise.then(onDataLoadedPromise);
|
|
1201
1240
|
return;
|
|
1202
1241
|
}
|
|
1242
|
+
const preload = () => {
|
|
1243
|
+
const saves = [...storageData.get().saves].reverse();
|
|
1244
|
+
const sliced = saves.slice(0, storyOptions.mode === "dynamic" ? storyOptions.preloadSaves : 0);
|
|
1245
|
+
for (const [path] of sliced) {
|
|
1246
|
+
referGuarded(path);
|
|
1247
|
+
}
|
|
1248
|
+
};
|
|
1249
|
+
if (preloadAssets === "blocking") {
|
|
1250
|
+
await preload();
|
|
1251
|
+
} else {
|
|
1252
|
+
void preload();
|
|
1253
|
+
}
|
|
1203
1254
|
coreData.update((data2) => {
|
|
1204
1255
|
data2.dataLoaded = true;
|
|
1205
1256
|
return data2;
|
|
@@ -1216,7 +1267,7 @@ var novely = ({
|
|
|
1216
1267
|
};
|
|
1217
1268
|
const throttledOnStorageDataChange = throttle(onStorageDataChange, throttleTimeout);
|
|
1218
1269
|
const throttledEmergencyOnStorageDataChange = throttle(() => {
|
|
1219
|
-
if (saveOnUnload === true || saveOnUnload === "prod" && !
|
|
1270
|
+
if (saveOnUnload === true || saveOnUnload === "prod" && !DEV5) {
|
|
1220
1271
|
onStorageDataChange(storageData.get());
|
|
1221
1272
|
}
|
|
1222
1273
|
}, 10);
|
|
@@ -1225,7 +1276,7 @@ var novely = ({
|
|
|
1225
1276
|
let stored = await storage.get();
|
|
1226
1277
|
for (const migration of migrations) {
|
|
1227
1278
|
stored = migration(stored);
|
|
1228
|
-
if (
|
|
1279
|
+
if (DEV5 && !stored) {
|
|
1229
1280
|
throw new Error("Migrations should return a value.");
|
|
1230
1281
|
}
|
|
1231
1282
|
}
|
|
@@ -1303,7 +1354,7 @@ var novely = ({
|
|
|
1303
1354
|
let interacted = 0;
|
|
1304
1355
|
const restore = async (save2) => {
|
|
1305
1356
|
if (isEmpty(story)) {
|
|
1306
|
-
if (
|
|
1357
|
+
if (DEV5) {
|
|
1307
1358
|
throw new Error(
|
|
1308
1359
|
"Story is empty. You should call an `enine.script` function [https://novely.pages.dev/guide/story.html]"
|
|
1309
1360
|
);
|
|
@@ -1325,7 +1376,14 @@ var novely = ({
|
|
|
1325
1376
|
const previous = stack.previous;
|
|
1326
1377
|
const [path] = stack.value = latest;
|
|
1327
1378
|
renderer.ui.showScreen("game");
|
|
1328
|
-
const {
|
|
1379
|
+
const { found } = await refer(path);
|
|
1380
|
+
if (found) context.loading(true);
|
|
1381
|
+
const { queue, skip, skipPreserve } = await getActionsFromPath({
|
|
1382
|
+
story,
|
|
1383
|
+
path,
|
|
1384
|
+
filter: false,
|
|
1385
|
+
referGuarded
|
|
1386
|
+
});
|
|
1329
1387
|
const {
|
|
1330
1388
|
run,
|
|
1331
1389
|
keep: { keep, characters: characters2, audio: audio2 }
|
|
@@ -1334,7 +1392,12 @@ var novely = ({
|
|
|
1334
1392
|
skipPreserve
|
|
1335
1393
|
});
|
|
1336
1394
|
if (previous) {
|
|
1337
|
-
const { queue: prevQueue } = getActionsFromPath(
|
|
1395
|
+
const { queue: prevQueue } = await getActionsFromPath({
|
|
1396
|
+
story,
|
|
1397
|
+
path: previous[0],
|
|
1398
|
+
filter: false,
|
|
1399
|
+
referGuarded
|
|
1400
|
+
});
|
|
1338
1401
|
for (let i = prevQueue.length - 1; i > queue.length - 1; i--) {
|
|
1339
1402
|
const element = prevQueue[i];
|
|
1340
1403
|
if (!isAction(element)) {
|
|
@@ -1352,6 +1415,7 @@ var novely = ({
|
|
|
1352
1415
|
data: latest[1]
|
|
1353
1416
|
});
|
|
1354
1417
|
}
|
|
1418
|
+
context.loading(false);
|
|
1355
1419
|
const lastQueueItem = queue.at(-1);
|
|
1356
1420
|
const lastQueueItemRequiresUserAction = lastQueueItem && isBlockingAction(lastQueueItem);
|
|
1357
1421
|
await run((item) => {
|
|
@@ -1368,10 +1432,13 @@ var novely = ({
|
|
|
1368
1432
|
if (!context.meta.goingBack) {
|
|
1369
1433
|
context.meta.restoring = false;
|
|
1370
1434
|
}
|
|
1371
|
-
render(context);
|
|
1435
|
+
await render(context);
|
|
1372
1436
|
context.meta.restoring = context.meta.goingBack = false;
|
|
1373
1437
|
};
|
|
1374
|
-
const refer = createReferFunction(
|
|
1438
|
+
const { refer, referGuarded } = createReferFunction({
|
|
1439
|
+
story,
|
|
1440
|
+
onUnknownSceneHit
|
|
1441
|
+
});
|
|
1375
1442
|
const exit = (force = false, saving = true) => {
|
|
1376
1443
|
const ctx = renderer.getContext(MAIN_CONTEXT_KEY);
|
|
1377
1444
|
const stack = useStack(ctx);
|
|
@@ -1423,8 +1490,16 @@ var novely = ({
|
|
|
1423
1490
|
});
|
|
1424
1491
|
}
|
|
1425
1492
|
const [path, data2] = save2;
|
|
1426
|
-
const { queue } = getActionsFromPath(story, path, true);
|
|
1427
1493
|
const ctx = renderer.getContext(name);
|
|
1494
|
+
const { found } = await refer(path);
|
|
1495
|
+
if (found) ctx.loading(true);
|
|
1496
|
+
const { queue } = await getActionsFromPath({
|
|
1497
|
+
story,
|
|
1498
|
+
path,
|
|
1499
|
+
filter: true,
|
|
1500
|
+
referGuarded
|
|
1501
|
+
});
|
|
1502
|
+
ctx.loading(false);
|
|
1428
1503
|
ctx.meta.restoring = true;
|
|
1429
1504
|
ctx.meta.preview = true;
|
|
1430
1505
|
const processor = createQueueProcessor(queue, {
|
|
@@ -1476,7 +1551,7 @@ var novely = ({
|
|
|
1476
1551
|
};
|
|
1477
1552
|
const getLanguageDisplayName = (lang) => {
|
|
1478
1553
|
const language = translation[lang];
|
|
1479
|
-
if (
|
|
1554
|
+
if (DEV5 && !language) {
|
|
1480
1555
|
throw new Error(
|
|
1481
1556
|
`Attempt to use unsupported language "${language}". Supported languages: ${languages.join(", ")}.`
|
|
1482
1557
|
);
|
|
@@ -1513,21 +1588,26 @@ var novely = ({
|
|
|
1513
1588
|
}
|
|
1514
1589
|
return String(c) || "";
|
|
1515
1590
|
};
|
|
1516
|
-
const getDialogOverview = () => {
|
|
1591
|
+
const getDialogOverview = async () => {
|
|
1517
1592
|
const { value: save2 } = useStack(MAIN_CONTEXT_KEY);
|
|
1518
1593
|
const stateSnapshots = save2[3];
|
|
1519
1594
|
if (stateSnapshots.length == 0) {
|
|
1520
1595
|
return [];
|
|
1521
1596
|
}
|
|
1522
|
-
const { queue } = getActionsFromPath(
|
|
1597
|
+
const { queue } = await getActionsFromPath({
|
|
1598
|
+
story,
|
|
1599
|
+
path: save2[0],
|
|
1600
|
+
filter: false,
|
|
1601
|
+
referGuarded
|
|
1602
|
+
});
|
|
1523
1603
|
const [lang] = storageData.get().meta;
|
|
1524
1604
|
const dialogItems = [];
|
|
1525
|
-
for (let p = 0, a = stateSnapshots.length, i = queue.length - 1; a > 0; i--) {
|
|
1605
|
+
for (let p = 0, a = stateSnapshots.length, i = queue.length - 1; a > 0 && i > 0; i--) {
|
|
1526
1606
|
const action2 = queue[i];
|
|
1527
1607
|
if (action2[0] === "dialog") {
|
|
1528
1608
|
const [_, name, text] = action2;
|
|
1529
1609
|
let voice = void 0;
|
|
1530
|
-
for (let j = i - 1; j > p; j--) {
|
|
1610
|
+
for (let j = i - 1; j > p && j > 0; j--) {
|
|
1531
1611
|
const action3 = queue[j];
|
|
1532
1612
|
if (isUserRequiredAction(action3) || isSkippedDuringRestore(action3[0])) break;
|
|
1533
1613
|
if (action3[0] === "stopVoice") break;
|
|
@@ -1609,14 +1689,14 @@ var novely = ({
|
|
|
1609
1689
|
matchActionOptions.push(ctx);
|
|
1610
1690
|
if (!ctx.meta.preview) interactivity(true);
|
|
1611
1691
|
},
|
|
1612
|
-
onBeforeActionCall({ action: action2, props, ctx }) {
|
|
1692
|
+
async onBeforeActionCall({ action: action2, props, ctx }) {
|
|
1613
1693
|
if (preloadAssets !== "automatic") return;
|
|
1614
1694
|
if (ctx.meta.preview || ctx.meta.restoring) return;
|
|
1615
1695
|
if (!isBlockingAction([action2, ...props])) return;
|
|
1616
1696
|
try {
|
|
1617
|
-
const collection = collectActionsBeforeBlockingAction({
|
|
1697
|
+
const collection = await collectActionsBeforeBlockingAction({
|
|
1618
1698
|
path: nextPath(clone(useStack(ctx).value[0])),
|
|
1619
|
-
refer,
|
|
1699
|
+
refer: referGuarded,
|
|
1620
1700
|
clone
|
|
1621
1701
|
});
|
|
1622
1702
|
for (const [action3, ...props2] of collection) {
|
|
@@ -1697,11 +1777,11 @@ var novely = ({
|
|
|
1697
1777
|
},
|
|
1698
1778
|
showCharacter({ ctx, push }, [character, emotion, className, style]) {
|
|
1699
1779
|
emotion ??= defaultEmotions[character];
|
|
1700
|
-
if (
|
|
1780
|
+
if (DEV5 && !emotion) {
|
|
1701
1781
|
throw new Error(`Attemp to show character "${character}" without emotion provided.`);
|
|
1702
1782
|
}
|
|
1703
1783
|
if (!emotion) return;
|
|
1704
|
-
if (
|
|
1784
|
+
if (DEV5 && !characters[character].emotions[emotion]) {
|
|
1705
1785
|
throw new Error(`Attempt to show character "${character}" with unknown emotion "${emotion}"`);
|
|
1706
1786
|
}
|
|
1707
1787
|
const handle = ctx.character(character);
|
|
@@ -1768,7 +1848,7 @@ var novely = ({
|
|
|
1768
1848
|
const imageValue = image ? handleImageAsset(image) : "";
|
|
1769
1849
|
return [templateReplace(content, data2), active$, visible$, onSelectWrapped, imageValue];
|
|
1770
1850
|
});
|
|
1771
|
-
if (
|
|
1851
|
+
if (DEV5 && transformedChoices.length === 0) {
|
|
1772
1852
|
throw new Error(
|
|
1773
1853
|
`Running choice without variants to choose from, look at how to use Choice action properly [https://novely.pages.dev/guide/actions/choice#usage]`
|
|
1774
1854
|
);
|
|
@@ -1780,7 +1860,7 @@ var novely = ({
|
|
|
1780
1860
|
}
|
|
1781
1861
|
const stack = useStack(ctx);
|
|
1782
1862
|
const offset = isWithoutQuestion ? 0 : 1;
|
|
1783
|
-
if (
|
|
1863
|
+
if (DEV5 && !transformedChoices[selected]) {
|
|
1784
1864
|
throw new Error("Choice children is empty, either add content there or make item not selectable");
|
|
1785
1865
|
}
|
|
1786
1866
|
stack.value[0].push(["choice", selected + offset], [null, 0]);
|
|
@@ -1789,12 +1869,6 @@ var novely = ({
|
|
|
1789
1869
|
});
|
|
1790
1870
|
},
|
|
1791
1871
|
jump({ ctx, data: data2 }, [scene]) {
|
|
1792
|
-
if (DEV4 && !story[scene]) {
|
|
1793
|
-
throw new Error(`Attempt to jump to unknown scene "${scene}"`);
|
|
1794
|
-
}
|
|
1795
|
-
if (DEV4 && story[scene].length === 0) {
|
|
1796
|
-
throw new Error(`Attempt to jump to empty scene "${scene}"`);
|
|
1797
|
-
}
|
|
1798
1872
|
const stack = useStack(ctx);
|
|
1799
1873
|
stack.value[0] = [
|
|
1800
1874
|
["jump", scene],
|
|
@@ -1816,15 +1890,15 @@ var novely = ({
|
|
|
1816
1890
|
);
|
|
1817
1891
|
},
|
|
1818
1892
|
condition({ ctx, data: data2 }, [condition, variants]) {
|
|
1819
|
-
if (
|
|
1893
|
+
if (DEV5 && Object.values(variants).length === 0) {
|
|
1820
1894
|
throw new Error(`Attempt to use Condition action with empty variants object`);
|
|
1821
1895
|
}
|
|
1822
1896
|
if (!ctx.meta.restoring) {
|
|
1823
1897
|
const val = String(condition(data2));
|
|
1824
|
-
if (
|
|
1898
|
+
if (DEV5 && !variants[val]) {
|
|
1825
1899
|
throw new Error(`Attempt to go to unknown variant "${val}"`);
|
|
1826
1900
|
}
|
|
1827
|
-
if (
|
|
1901
|
+
if (DEV5 && variants[val].length === 0) {
|
|
1828
1902
|
throw new Error(`Attempt to go to empty variant "${val}"`);
|
|
1829
1903
|
}
|
|
1830
1904
|
const stack = useStack(ctx);
|
|
@@ -1878,7 +1952,7 @@ var novely = ({
|
|
|
1878
1952
|
},
|
|
1879
1953
|
animateCharacter({ ctx, push }, [character, className]) {
|
|
1880
1954
|
const classes = className.split(" ");
|
|
1881
|
-
if (
|
|
1955
|
+
if (DEV5 && classes.length === 0) {
|
|
1882
1956
|
throw new Error(
|
|
1883
1957
|
"Attempt to use AnimateCharacter without classes. Classes should be provided [https://novely.pages.dev/guide/actions/animateCharacter.html]"
|
|
1884
1958
|
);
|
|
@@ -1889,17 +1963,17 @@ var novely = ({
|
|
|
1889
1963
|
},
|
|
1890
1964
|
text({ ctx, data: data2, forward }, text) {
|
|
1891
1965
|
const string = text.map((content) => templateReplace(content, data2)).join(" ");
|
|
1892
|
-
if (
|
|
1966
|
+
if (DEV5 && string.length === 0) {
|
|
1893
1967
|
throw new Error(`Action Text was called with empty string or array`);
|
|
1894
1968
|
}
|
|
1895
1969
|
ctx.clearBlockingActions("text");
|
|
1896
1970
|
ctx.text(string, forward);
|
|
1897
1971
|
},
|
|
1898
|
-
exit({ ctx, data: data2 }) {
|
|
1972
|
+
async exit({ ctx, data: data2 }) {
|
|
1899
1973
|
if (ctx.meta.restoring) return;
|
|
1900
|
-
const { exitImpossible } = exitPath({
|
|
1974
|
+
const { exitImpossible } = await exitPath({
|
|
1901
1975
|
path: useStack(ctx).value[0],
|
|
1902
|
-
refer,
|
|
1976
|
+
refer: referGuarded,
|
|
1903
1977
|
onExitImpossible: () => {
|
|
1904
1978
|
match("end", [], {
|
|
1905
1979
|
ctx,
|
|
@@ -1914,7 +1988,7 @@ var novely = ({
|
|
|
1914
1988
|
render(ctx);
|
|
1915
1989
|
},
|
|
1916
1990
|
preload({ ctx, push }, [source]) {
|
|
1917
|
-
if (
|
|
1991
|
+
if (DEV5 && preloadAssets !== "lazy") {
|
|
1918
1992
|
console.error(
|
|
1919
1993
|
`You do not need a preload action becase "preloadAssets" strategy was set to "${preloadAssets}"`
|
|
1920
1994
|
);
|
|
@@ -1925,10 +1999,10 @@ var novely = ({
|
|
|
1925
1999
|
push();
|
|
1926
2000
|
},
|
|
1927
2001
|
block({ ctx }, [scene]) {
|
|
1928
|
-
if (
|
|
2002
|
+
if (DEV5 && !story[scene]) {
|
|
1929
2003
|
throw new Error(`Attempt to call Block action with unknown scene "${scene}"`);
|
|
1930
2004
|
}
|
|
1931
|
-
if (
|
|
2005
|
+
if (DEV5 && story[scene].length === 0) {
|
|
1932
2006
|
throw new Error(`Attempt to call Block action with empty scene "${scene}"`);
|
|
1933
2007
|
}
|
|
1934
2008
|
if (!ctx.meta.restoring) {
|
|
@@ -1945,10 +2019,17 @@ var novely = ({
|
|
|
1945
2019
|
preloadAssets,
|
|
1946
2020
|
storageData
|
|
1947
2021
|
});
|
|
1948
|
-
const render = (ctx) => {
|
|
2022
|
+
const render = async (ctx) => {
|
|
1949
2023
|
const stack = useStack(ctx);
|
|
1950
2024
|
const [path, state] = stack.value;
|
|
1951
|
-
const
|
|
2025
|
+
const { found, value } = await refer(path);
|
|
2026
|
+
if (found) {
|
|
2027
|
+
ctx.loading(true);
|
|
2028
|
+
}
|
|
2029
|
+
const referred = await value;
|
|
2030
|
+
if (found) {
|
|
2031
|
+
ctx.loading(false);
|
|
2032
|
+
}
|
|
1952
2033
|
if (isAction(referred)) {
|
|
1953
2034
|
const [action2, ...props] = referred;
|
|
1954
2035
|
match(action2, props, {
|
|
@@ -2002,7 +2083,7 @@ var novely = ({
|
|
|
2002
2083
|
};
|
|
2003
2084
|
const setStorageData = (data2) => {
|
|
2004
2085
|
if (destroyed) {
|
|
2005
|
-
if (
|
|
2086
|
+
if (DEV5) {
|
|
2006
2087
|
throw new Error(
|
|
2007
2088
|
`function \`setStorageData\` was called after novely instance was destroyed. Data is not updater nor synced after destroy.`
|
|
2008
2089
|
);
|
|
@@ -2296,8 +2377,8 @@ var JP = {
|
|
|
2296
2377
|
};
|
|
2297
2378
|
|
|
2298
2379
|
// src/asset.ts
|
|
2299
|
-
import { memoize as
|
|
2300
|
-
import { DEV as
|
|
2380
|
+
import { memoize as memoize5, once } from "es-toolkit/function";
|
|
2381
|
+
import { DEV as DEV6 } from "esm-env";
|
|
2301
2382
|
|
|
2302
2383
|
// src/audio-codecs.ts
|
|
2303
2384
|
var cut = (str) => str.replace(/^no$/, "");
|
|
@@ -2360,7 +2441,7 @@ loadImageFormatsSupport();
|
|
|
2360
2441
|
|
|
2361
2442
|
// src/asset.ts
|
|
2362
2443
|
var generateRandomId = () => Math.random().toString(36);
|
|
2363
|
-
var getType =
|
|
2444
|
+
var getType = memoize5(
|
|
2364
2445
|
(extensions) => {
|
|
2365
2446
|
if (extensions.every((extension) => HOWLER_SUPPORTED_FILE_FORMATS.has(extension))) {
|
|
2366
2447
|
return "audio";
|
|
@@ -2378,9 +2459,9 @@ var SUPPORT_MAPS = {
|
|
|
2378
2459
|
image: supportsMap2,
|
|
2379
2460
|
audio: supportsMap
|
|
2380
2461
|
};
|
|
2381
|
-
var assetPrivate =
|
|
2462
|
+
var assetPrivate = memoize5(
|
|
2382
2463
|
(variants) => {
|
|
2383
|
-
if (
|
|
2464
|
+
if (DEV6 && variants.length === 0) {
|
|
2384
2465
|
throw new Error(`Attempt to use "asset" function without arguments`);
|
|
2385
2466
|
}
|
|
2386
2467
|
const map = {};
|
|
@@ -2402,7 +2483,7 @@ var assetPrivate = memoize4(
|
|
|
2402
2483
|
return map[extension];
|
|
2403
2484
|
}
|
|
2404
2485
|
}
|
|
2405
|
-
if (
|
|
2486
|
+
if (DEV6) {
|
|
2406
2487
|
throw new Error(`No matching asset was found for ${variants.map((v) => `"${v}"`).join(", ")}`);
|
|
2407
2488
|
}
|
|
2408
2489
|
return "";
|