@novely/core 0.9.1 → 0.11.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 +10 -11
- package/dist/index.global.js +136 -47
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +127 -40
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ type Character<LanguageKeys extends string = string> = {
|
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
type Thenable<T> = T | Promise<T>;
|
|
17
|
-
type PathItem = [null, number | string] | ['choice'
|
|
17
|
+
type PathItem = [null, number | string] | ['choice', number] | ['choice:exit'] | ['condition', string] | ['condition:exit'] | ['exit'] | ['block', string] | ['block:exit'];
|
|
18
18
|
type Path = PathItem[];
|
|
19
19
|
type State = Record<string, any>;
|
|
20
20
|
type Data = Record<string, any>;
|
|
@@ -23,7 +23,7 @@ type SaveType = 'manual' | 'auto';
|
|
|
23
23
|
type SaveMeta = [SaveDate, SaveType];
|
|
24
24
|
type Save = [Path, State, SaveMeta];
|
|
25
25
|
type Lang = string;
|
|
26
|
-
type TypewriterSpeed = 'Slow' | 'Medium' | 'Fast' | 'Auto' | (string &
|
|
26
|
+
type TypewriterSpeed = 'Slow' | 'Medium' | 'Fast' | 'Auto' | (string & Record<never, never>);
|
|
27
27
|
type StorageMeta = [Lang, TypewriterSpeed];
|
|
28
28
|
type Migration = (save: unknown) => unknown;
|
|
29
29
|
type StorageData = {
|
|
@@ -44,8 +44,9 @@ type NovelyScreen = 'mainmenu' | 'game' | 'saves' | 'settings';
|
|
|
44
44
|
type DeepPartial<T> = unknown extends T ? T : T extends object ? {
|
|
45
45
|
[P in keyof T]?: T[P] extends Array<infer U> ? Array<DeepPartial<U>> : T[P] extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>> : DeepPartial<T[P]>;
|
|
46
46
|
} : T;
|
|
47
|
+
type NonEmptyRecord<T extends Record<PropertyKey, unknown>> = keyof T extends never ? never : T;
|
|
47
48
|
|
|
48
|
-
type ValidAction = ['choice', [number]] | ['clear', [Set<keyof DefaultActionProxyProvider>?, Set<string>?]] | ['condition', [() => boolean, Record<string, ValidAction[]>]] | ['dialog', [string | undefined, Unwrappable, string | undefined]] | ['end', []] | ['showBackground', [string]] | ['playMusic', [string]] | ['stopMusic', [string]] | ['jump', [string]] | ['showCharacter', [string, keyof Character['emotions'], string?, string?]] | ['hideCharacter', [string, string?, string?, number?]] | ['animateCharacter', [string, number, ...string[]]] | ['wait', [FunctionableValue<number>]] | ['function', [() => Thenable<void>]] | ['input', [string, (meta: ActionInputOnInputMeta) => void, ActionInputSetup?]] | ['custom', [CustomHandler]] | ['vibrate', [...number[]]] | ['next', []] | ['text', [...string[]]] | ['exit'] | ['preload', [string]] | ValidAction[];
|
|
49
|
+
type ValidAction = ['choice', [number]] | ['clear', [Set<keyof DefaultActionProxyProvider>?, Set<string>?]] | ['condition', [() => boolean, Record<string, ValidAction[]>]] | ['dialog', [string | undefined, Unwrappable, string | undefined]] | ['end', []] | ['showBackground', [string | NonEmptyRecord<BackgroundImage>]] | ['playMusic', [string]] | ['stopMusic', [string]] | ['jump', [string]] | ['showCharacter', [string, keyof Character['emotions'], string?, string?]] | ['hideCharacter', [string, string?, string?, number?]] | ['animateCharacter', [string, number, ...string[]]] | ['wait', [FunctionableValue<number>]] | ['function', [() => Thenable<void>]] | ['input', [string, (meta: ActionInputOnInputMeta) => void, ActionInputSetup?]] | ['custom', [CustomHandler]] | ['vibrate', [...number[]]] | ['next', []] | ['text', [...string[]]] | ['exit', []] | ['preload', [string]] | ['block', [string]] | ValidAction[];
|
|
49
50
|
type Story = Record<string, ValidAction[]>;
|
|
50
51
|
type Unwrappable = string | ((lang: string, obj: Record<string, unknown>) => string) | Record<string, string | (() => string)>;
|
|
51
52
|
type FunctionableValue<T> = T | (() => T);
|
|
@@ -100,6 +101,7 @@ interface ActionInputOnInputMeta {
|
|
|
100
101
|
value: string;
|
|
101
102
|
}
|
|
102
103
|
type ActionInputSetup = (input: HTMLInputElement, cleanup: (cb: () => void) => void) => void;
|
|
104
|
+
type BackgroundImage = Partial<Record<"portrait" | "landscape" | "all", string>> & Record<(string), string>;
|
|
103
105
|
type ActionProxyProvider<Characters extends Record<string, Character>> = {
|
|
104
106
|
choice: {
|
|
105
107
|
(...choices: ([Unwrappable, ValidAction[]] | [Unwrappable, ValidAction[], () => boolean])[]): ValidAction;
|
|
@@ -114,19 +116,15 @@ type ActionProxyProvider<Characters extends Record<string, Character>> = {
|
|
|
114
116
|
(person: string, content: Unwrappable, emotion?: undefined): ValidAction;
|
|
115
117
|
};
|
|
116
118
|
end: () => ValidAction;
|
|
117
|
-
showBackground: (background: string) => ValidAction;
|
|
119
|
+
showBackground: <T extends string | BackgroundImage>(background: T extends string ? T : T extends Record<PropertyKey, unknown> ? NonEmptyRecord<T> : never) => ValidAction;
|
|
118
120
|
playMusic: (audio: string) => ValidAction;
|
|
119
121
|
stopMusic: (audio: string) => ValidAction;
|
|
120
122
|
jump: (scene: string) => ValidAction;
|
|
121
123
|
showCharacter: {
|
|
122
124
|
<C extends keyof Characters>(character: C, emotion: keyof Characters[C]['emotions'], className?: string, style?: string): ValidAction;
|
|
123
125
|
};
|
|
124
|
-
hideCharacter:
|
|
125
|
-
|
|
126
|
-
};
|
|
127
|
-
animateCharacter: {
|
|
128
|
-
<C extends keyof Characters>(character: C, timeout: number, ...classes: string[]): ValidAction;
|
|
129
|
-
};
|
|
126
|
+
hideCharacter: (character: keyof Characters, className?: string, style?: string, duration?: number) => ValidAction;
|
|
127
|
+
animateCharacter: (character: keyof Characters, timeout: number, ...classes: string[]) => ValidAction;
|
|
130
128
|
wait: (time: FunctionableValue<number>) => ValidAction;
|
|
131
129
|
function: (fn: (restoring: boolean, goingBack: boolean) => Thenable<void>) => ValidAction;
|
|
132
130
|
input: (question: Unwrappable, onInput: (meta: ActionInputOnInputMeta) => void, setup?: ActionInputSetup) => ValidAction;
|
|
@@ -135,6 +133,7 @@ type ActionProxyProvider<Characters extends Record<string, Character>> = {
|
|
|
135
133
|
next: () => ValidAction;
|
|
136
134
|
text: (...text: Unwrappable[]) => ValidAction;
|
|
137
135
|
preload: (source: string) => ValidAction;
|
|
136
|
+
block: (scene: string) => ValidAction;
|
|
138
137
|
};
|
|
139
138
|
type DefaultActionProxyProvider = ActionProxyProvider<Record<string, Character>>;
|
|
140
139
|
type GetActionParameters<T extends Capitalize<keyof DefaultActionProxyProvider>> = Parameters<DefaultActionProxyProvider[Uncapitalize<T>]>;
|
|
@@ -165,7 +164,7 @@ interface RendererStore {
|
|
|
165
164
|
}
|
|
166
165
|
type Renderer = {
|
|
167
166
|
character: (character: string) => CharacterHandle;
|
|
168
|
-
background: (background: string) => void;
|
|
167
|
+
background: (background: string | BackgroundImage) => void;
|
|
169
168
|
dialog: (content: string, name: string, character?: string, emotion?: string) => (resolve: () => void, goingBack: boolean) => void;
|
|
170
169
|
choices: (question: string, choices: ([string, ValidAction[]] | [string, ValidAction[], () => boolean])[]) => (resolve: (selected: number) => void) => void;
|
|
171
170
|
input: (question: string, onInput: Parameters<DefaultActionProxyProvider['input']>[1], setup?: Parameters<DefaultActionProxyProvider['input']>[2]) => (resolve: () => void) => void;
|
package/dist/index.global.js
CHANGED
|
@@ -141,6 +141,13 @@ var Novely = (() => {
|
|
|
141
141
|
novely: () => novely
|
|
142
142
|
});
|
|
143
143
|
|
|
144
|
+
// src/constants.ts
|
|
145
|
+
var SKIPPED_DURING_RESTORE = /* @__PURE__ */ new Set(["dialog", "choice", "input", "vibrate", "text"]);
|
|
146
|
+
var BLOCK_EXIT_STATEMENTS = /* @__PURE__ */ new Set(["choice:exit", "condition:exit", "block:exit"]);
|
|
147
|
+
var BLOCK_STATEMENTS = /* @__PURE__ */ new Set(["choice", "condition", "block"]);
|
|
148
|
+
var EMPTY_SET = /* @__PURE__ */ new Set();
|
|
149
|
+
var DEFAULT_TYPEWRITER_SPEED = "Medium";
|
|
150
|
+
|
|
144
151
|
// src/utils.ts
|
|
145
152
|
var matchAction = (values) => {
|
|
146
153
|
return (action, props) => {
|
|
@@ -213,8 +220,8 @@ var Novely = (() => {
|
|
|
213
220
|
}
|
|
214
221
|
};
|
|
215
222
|
var findLastIndex = (array, fn) => {
|
|
216
|
-
for (let i = array.length - 1; i
|
|
217
|
-
if (fn(array[i])) {
|
|
223
|
+
for (let i = array.length - 1; i >= 0; i--) {
|
|
224
|
+
if (fn(array[i], array[i + 1])) {
|
|
218
225
|
return i;
|
|
219
226
|
}
|
|
220
227
|
}
|
|
@@ -242,6 +249,24 @@ var Novely = (() => {
|
|
|
242
249
|
});
|
|
243
250
|
return { resolve, reject, promise };
|
|
244
251
|
};
|
|
252
|
+
var findLastPathItemBeforeItemOfType = (path, name) => {
|
|
253
|
+
const index = findLastIndex(path, ([_name, _value], next) => {
|
|
254
|
+
return isNull(_name) && isNumber(_value) && next != null && next[0] === name;
|
|
255
|
+
});
|
|
256
|
+
return path[index];
|
|
257
|
+
};
|
|
258
|
+
var isBlockStatement = (statement) => {
|
|
259
|
+
return BLOCK_STATEMENTS.has(statement);
|
|
260
|
+
};
|
|
261
|
+
var isBlockExitStatement = (statement) => {
|
|
262
|
+
return BLOCK_EXIT_STATEMENTS.has(statement);
|
|
263
|
+
};
|
|
264
|
+
var isSkippedDurigRestore = (item) => {
|
|
265
|
+
return SKIPPED_DURING_RESTORE.has(item);
|
|
266
|
+
};
|
|
267
|
+
var isAction = (element) => {
|
|
268
|
+
return Array.isArray(element) && isString(element[0]);
|
|
269
|
+
};
|
|
245
270
|
|
|
246
271
|
// src/global.ts
|
|
247
272
|
var PRELOADED_ASSETS = /* @__PURE__ */ new Set();
|
|
@@ -298,13 +323,8 @@ var Novely = (() => {
|
|
|
298
323
|
return val;
|
|
299
324
|
}
|
|
300
325
|
|
|
301
|
-
// src/constants.ts
|
|
302
|
-
var SKIPPED_DURING_RESTORE = /* @__PURE__ */ new Set(["dialog", "choice", "input", "vibrate", "text"]);
|
|
303
|
-
var EMPTY_SET = /* @__PURE__ */ new Set();
|
|
304
|
-
var DEFAULT_TYPEWRITER_SPEED = "Medium";
|
|
305
|
-
|
|
306
326
|
// ../t9n/dist/index.js
|
|
307
|
-
var
|
|
327
|
+
var g = (e, r) => {
|
|
308
328
|
let o = [];
|
|
309
329
|
for (let a of r) {
|
|
310
330
|
if (!e)
|
|
@@ -318,15 +338,15 @@ var Novely = (() => {
|
|
|
318
338
|
var l = (e) => Array.isArray(e) ? e.map((r) => l(r)).join("<br>") : typeof e == "function" ? l(e()) : e;
|
|
319
339
|
var x = (e, r, o, a, n) => l(e).replaceAll(c, (i, s, t) => {
|
|
320
340
|
i = 0, t = r;
|
|
321
|
-
let [
|
|
322
|
-
if (!
|
|
341
|
+
let [u, S, p] = g(s.trim(), ["@", "%"]);
|
|
342
|
+
if (!u)
|
|
323
343
|
return "";
|
|
324
|
-
let
|
|
325
|
-
for (; t && i <
|
|
326
|
-
t = t[
|
|
327
|
-
|
|
328
|
-
let
|
|
329
|
-
return
|
|
344
|
+
let m = u.split(".");
|
|
345
|
+
for (; t && i < m.length; )
|
|
346
|
+
t = t[m[i++]];
|
|
347
|
+
S && o && t && n && (t = o[S][n.select(t)]);
|
|
348
|
+
let d = a && p && a[p];
|
|
349
|
+
return d && (t = d(t)), t ?? "";
|
|
330
350
|
});
|
|
331
351
|
|
|
332
352
|
// src/novely.ts
|
|
@@ -534,31 +554,46 @@ var Novely = (() => {
|
|
|
534
554
|
latest = klona(initial);
|
|
535
555
|
}
|
|
536
556
|
restoring = true, stack.value = latest;
|
|
557
|
+
const path = stack.value[0];
|
|
537
558
|
let current = story;
|
|
559
|
+
let precurrent;
|
|
560
|
+
let ignoreNested = false;
|
|
538
561
|
let index = 0;
|
|
539
562
|
const max = stack.value[0].reduce((acc, [type, val]) => {
|
|
540
|
-
if (isNull(type) && isNumber(val))
|
|
563
|
+
if (isNull(type) && isNumber(val)) {
|
|
541
564
|
return acc + 1;
|
|
565
|
+
}
|
|
542
566
|
return acc;
|
|
543
567
|
}, 0);
|
|
544
568
|
const queue = [];
|
|
545
569
|
const keep = /* @__PURE__ */ new Set();
|
|
546
570
|
const characters2 = /* @__PURE__ */ new Set();
|
|
547
|
-
|
|
571
|
+
const blocks = [];
|
|
572
|
+
for (const [type, val] of path) {
|
|
548
573
|
if (type === null) {
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
} else if (isNumber(val)) {
|
|
574
|
+
precurrent = current;
|
|
575
|
+
if (isNumber(val)) {
|
|
552
576
|
index++;
|
|
553
|
-
|
|
554
|
-
|
|
577
|
+
let startIndex = 0;
|
|
578
|
+
if (ignoreNested) {
|
|
579
|
+
const prev = findLastPathItemBeforeItemOfType(path.slice(0, index), "block");
|
|
580
|
+
if (prev) {
|
|
581
|
+
startIndex = prev[1];
|
|
582
|
+
ignoreNested = false;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
for (let i = startIndex; i <= val; i++) {
|
|
586
|
+
const item = current[i];
|
|
587
|
+
if (!isAction(item))
|
|
588
|
+
continue;
|
|
589
|
+
const [action2, ...meta] = item;
|
|
555
590
|
const push2 = () => {
|
|
556
591
|
keep.add(action2);
|
|
557
592
|
queue.push([action2, meta]);
|
|
558
593
|
};
|
|
559
594
|
if (action2 === "showCharacter")
|
|
560
595
|
characters2.add(meta[0]);
|
|
561
|
-
if (
|
|
596
|
+
if (isSkippedDurigRestore(action2) || isUserRequiredAction(action2, meta)) {
|
|
562
597
|
if (index === max && i === val) {
|
|
563
598
|
push2();
|
|
564
599
|
} else {
|
|
@@ -567,12 +602,20 @@ var Novely = (() => {
|
|
|
567
602
|
}
|
|
568
603
|
push2();
|
|
569
604
|
}
|
|
570
|
-
current = current[val];
|
|
571
605
|
}
|
|
606
|
+
current = current[val];
|
|
572
607
|
} else if (type === "choice") {
|
|
608
|
+
blocks.push(precurrent = current);
|
|
573
609
|
current = current[val + 1][1];
|
|
574
610
|
} else if (type === "condition") {
|
|
611
|
+
blocks.push(precurrent = current);
|
|
575
612
|
current = current[2][val];
|
|
613
|
+
} else if (type === "block") {
|
|
614
|
+
blocks.push(precurrent);
|
|
615
|
+
current = story[val];
|
|
616
|
+
} else if (type === "block:exit" || type === "choice:exit" || type === "condition:exit") {
|
|
617
|
+
current = blocks.pop();
|
|
618
|
+
ignoreNested = true;
|
|
576
619
|
}
|
|
577
620
|
}
|
|
578
621
|
renderer.ui.showScreen("game");
|
|
@@ -587,7 +630,8 @@ var Novely = (() => {
|
|
|
587
630
|
const c0 = _meta[0];
|
|
588
631
|
const c1 = meta[0];
|
|
589
632
|
const isIdenticalID = c0.id && c1.id && c0.id === c1.id;
|
|
590
|
-
|
|
633
|
+
const isIdenticalByReference = c0 === c1;
|
|
634
|
+
return isIdenticalID || isIdenticalByReference || str(c0) === str(c1);
|
|
591
635
|
});
|
|
592
636
|
if (notLatest)
|
|
593
637
|
continue;
|
|
@@ -618,15 +662,25 @@ var Novely = (() => {
|
|
|
618
662
|
}
|
|
619
663
|
restoring = goingBack = false, render();
|
|
620
664
|
};
|
|
621
|
-
const refer = () => {
|
|
665
|
+
const refer = (path = stack.value[0]) => {
|
|
622
666
|
let current = story;
|
|
623
|
-
|
|
667
|
+
let precurrent = story;
|
|
668
|
+
const blocks = [];
|
|
669
|
+
for (const [type, val] of path) {
|
|
624
670
|
if (type === null) {
|
|
671
|
+
precurrent = current;
|
|
625
672
|
current = current[val];
|
|
626
673
|
} else if (type === "choice") {
|
|
674
|
+
blocks.push(precurrent = current);
|
|
627
675
|
current = current[val + 1][1];
|
|
628
676
|
} else if (type === "condition") {
|
|
677
|
+
blocks.push(precurrent = current);
|
|
629
678
|
current = current[2][val];
|
|
679
|
+
} else if (type === "block") {
|
|
680
|
+
blocks.push(precurrent);
|
|
681
|
+
current = story[val];
|
|
682
|
+
} else if (type === "block:exit" || type === "choice:exit" || type === "condition:exit") {
|
|
683
|
+
current = blocks.pop();
|
|
630
684
|
}
|
|
631
685
|
}
|
|
632
686
|
return current;
|
|
@@ -707,7 +761,8 @@ var Novely = (() => {
|
|
|
707
761
|
}
|
|
708
762
|
return c2 || "";
|
|
709
763
|
})();
|
|
710
|
-
renderer.dialog(unwrap(content), unwrap(name), character, emotion)
|
|
764
|
+
const run = renderer.dialog(unwrap(content), unwrap(name), character, emotion);
|
|
765
|
+
run(forward, goingBack);
|
|
711
766
|
},
|
|
712
767
|
function([fn]) {
|
|
713
768
|
const result = fn(restoring, goingBack);
|
|
@@ -724,10 +779,11 @@ var Novely = (() => {
|
|
|
724
779
|
const unwrapped = choices.map(([content, action2, visible]) => {
|
|
725
780
|
return [unwrap(content), action2, visible];
|
|
726
781
|
});
|
|
727
|
-
renderer.choices(
|
|
782
|
+
const run = renderer.choices(
|
|
728
783
|
unwrap(question),
|
|
729
784
|
unwrapped
|
|
730
|
-
)
|
|
785
|
+
);
|
|
786
|
+
run((selected) => {
|
|
731
787
|
enmemory();
|
|
732
788
|
const offset = isWithoutQuestion ? 0 : 1;
|
|
733
789
|
stack.value[0].push(["choice", selected + offset], [null, 0]);
|
|
@@ -747,9 +803,13 @@ var Novely = (() => {
|
|
|
747
803
|
renderer.clear(goingBack, keep || EMPTY_SET, characters2 || EMPTY_SET)(push);
|
|
748
804
|
},
|
|
749
805
|
condition([condition]) {
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
806
|
+
if (!restoring) {
|
|
807
|
+
stack.value[0].push(
|
|
808
|
+
["condition", String(condition())],
|
|
809
|
+
[null, 0]
|
|
810
|
+
);
|
|
811
|
+
render();
|
|
812
|
+
}
|
|
753
813
|
},
|
|
754
814
|
end() {
|
|
755
815
|
match("clear", []);
|
|
@@ -801,24 +861,55 @@ var Novely = (() => {
|
|
|
801
861
|
renderer.text(text.map((content) => unwrap(content)).join(" "), forward, goingBack);
|
|
802
862
|
},
|
|
803
863
|
exit() {
|
|
864
|
+
if (restoring)
|
|
865
|
+
return;
|
|
804
866
|
const path = stack.value[0];
|
|
805
|
-
|
|
867
|
+
const last = path.at(-1);
|
|
868
|
+
const ignore = [];
|
|
869
|
+
if (!isAction(refer(path))) {
|
|
870
|
+
if (last && isNull(last[0]) && isNumber(last[1])) {
|
|
871
|
+
last[1]--;
|
|
872
|
+
} else {
|
|
873
|
+
path.pop();
|
|
874
|
+
}
|
|
875
|
+
}
|
|
806
876
|
for (let i = path.length - 1; i > 0; i--) {
|
|
807
|
-
|
|
877
|
+
const [name] = path[i];
|
|
878
|
+
if (isBlockExitStatement(name)) {
|
|
879
|
+
ignore.push(name);
|
|
880
|
+
}
|
|
881
|
+
if (!isBlockStatement(name))
|
|
808
882
|
continue;
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
883
|
+
if (ignore.at(-1)?.startsWith(name)) {
|
|
884
|
+
ignore.pop();
|
|
885
|
+
continue;
|
|
886
|
+
}
|
|
887
|
+
path.push([`${name}:exit`]);
|
|
888
|
+
const prev = findLastPathItemBeforeItemOfType(path.slice(0, i + 1), name);
|
|
889
|
+
if (prev)
|
|
890
|
+
path.push([null, prev[1] + 1]);
|
|
891
|
+
if (!isAction(refer(path))) {
|
|
892
|
+
path.pop();
|
|
893
|
+
continue;
|
|
894
|
+
}
|
|
812
895
|
break;
|
|
813
896
|
}
|
|
814
|
-
|
|
815
|
-
render();
|
|
897
|
+
render();
|
|
816
898
|
},
|
|
817
899
|
preload([source]) {
|
|
818
900
|
if (!PRELOADED_ASSETS.has(source) && !goingBack && !restoring) {
|
|
819
901
|
PRELOADED_ASSETS.add(document.createElement("img").src = source);
|
|
820
902
|
}
|
|
821
903
|
push();
|
|
904
|
+
},
|
|
905
|
+
block([scene]) {
|
|
906
|
+
if (!restoring) {
|
|
907
|
+
stack.value[0].push(
|
|
908
|
+
["block", scene],
|
|
909
|
+
[null, 0]
|
|
910
|
+
);
|
|
911
|
+
render();
|
|
912
|
+
}
|
|
822
913
|
}
|
|
823
914
|
});
|
|
824
915
|
const enmemory = () => {
|
|
@@ -832,13 +923,11 @@ var Novely = (() => {
|
|
|
832
923
|
const next = () => {
|
|
833
924
|
const path = stack.value[0];
|
|
834
925
|
const last = path.at(-1);
|
|
835
|
-
if (
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
return;
|
|
926
|
+
if (last && isNull(last[0]) && isNumber(last[1])) {
|
|
927
|
+
last[1]++;
|
|
928
|
+
} else {
|
|
929
|
+
path.push([null, 0]);
|
|
840
930
|
}
|
|
841
|
-
path.push([null, 0]);
|
|
842
931
|
};
|
|
843
932
|
const render = () => {
|
|
844
933
|
const referred = refer();
|