bobe 0.0.11 → 0.0.12
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/bobe.cjs.js +223 -69
- package/dist/bobe.cjs.js.map +1 -1
- package/dist/bobe.esm.js +224 -70
- package/dist/bobe.esm.js.map +1 -1
- package/dist/index.d.ts +56 -17
- package/dist/index.umd.js +223 -69
- package/dist/index.umd.js.map +1 -1
- package/package.json +3 -3
package/dist/bobe.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Store, Keys, effect, shareSignal,
|
|
1
|
+
import { Store, getPulling, setPulling, Keys, effect, shareSignal, $, runWithPulling } from 'aoye';
|
|
2
2
|
export * from 'aoye';
|
|
3
3
|
import { BaseEvent, Queue, isNum } from 'bobe-shared';
|
|
4
4
|
|
|
@@ -21,13 +21,94 @@ var LogicType = /* @__PURE__ */ ((LogicType2) => {
|
|
|
21
21
|
LogicType2[LogicType2["Component"] = 16] = "Component";
|
|
22
22
|
LogicType2[LogicType2["Fragment"] = 32] = "Fragment";
|
|
23
23
|
LogicType2[LogicType2["Root"] = 64] = "Root";
|
|
24
|
+
LogicType2[LogicType2["Real"] = 128] = "Real";
|
|
24
25
|
return LogicType2;
|
|
25
26
|
})(LogicType || {});
|
|
27
|
+
const Logical = 1 /* If */ | 2 /* ElseIf */ | 4 /* Else */ | 8 /* For */;
|
|
28
|
+
var NodeType = /* @__PURE__ */ ((NodeType2) => {
|
|
29
|
+
NodeType2[NodeType2["Logic"] = Logical] = "Logic";
|
|
30
|
+
NodeType2[NodeType2["Real"] = 128 /* Real */] = "Real";
|
|
31
|
+
NodeType2[NodeType2["Component"] = 16 /* Component */] = "Component";
|
|
32
|
+
return NodeType2;
|
|
33
|
+
})(NodeType || {});
|
|
26
34
|
var TerpEvt = /* @__PURE__ */ ((TerpEvt2) => {
|
|
27
35
|
TerpEvt2["AllAttrGot"] = "all-attr-got";
|
|
28
36
|
TerpEvt2["HandledComponentNode"] = "handled-component-node";
|
|
29
37
|
return TerpEvt2;
|
|
30
38
|
})(TerpEvt || {});
|
|
39
|
+
const IsAnchor = /* @__PURE__ */ Symbol("is-anchor");
|
|
40
|
+
|
|
41
|
+
class TypedStack {
|
|
42
|
+
constructor() {
|
|
43
|
+
this.top = null;
|
|
44
|
+
// 存储每种类型最近一次出现的包装单元引用
|
|
45
|
+
// 使用 Record 来动态支持不同的类型标签
|
|
46
|
+
this.lastNodes = {};
|
|
47
|
+
this.length = 0;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* @param rawNode 原始节点数据
|
|
51
|
+
* @param type 节点类型
|
|
52
|
+
*/
|
|
53
|
+
push(rawNode, type) {
|
|
54
|
+
var _a;
|
|
55
|
+
const newNode = {
|
|
56
|
+
data: rawNode,
|
|
57
|
+
type,
|
|
58
|
+
prev: this.top,
|
|
59
|
+
prevSameType: (_a = this.lastNodes[type]) != null ? _a : null
|
|
60
|
+
};
|
|
61
|
+
this.top = newNode;
|
|
62
|
+
this.length++;
|
|
63
|
+
this.lastNodes[type] = newNode;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* 出栈操作
|
|
67
|
+
* @returns 原始节点数据或 null
|
|
68
|
+
*/
|
|
69
|
+
pop() {
|
|
70
|
+
if (!this.top) return null;
|
|
71
|
+
const popped = this.top;
|
|
72
|
+
this.lastNodes[popped.type] = popped.prevSameType;
|
|
73
|
+
this.top = popped.prev;
|
|
74
|
+
this.length--;
|
|
75
|
+
return popped.data;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* O(1) 获取栈顶节点的前一个同类型节点
|
|
79
|
+
*/
|
|
80
|
+
getPrevSameType() {
|
|
81
|
+
if (!this.top || !this.top.prevSameType) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
return this.top.prevSameType.data;
|
|
85
|
+
}
|
|
86
|
+
findPrevSameType(cb) {
|
|
87
|
+
if (!this.top) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
let point = this.top.prevSameType;
|
|
91
|
+
while (point) {
|
|
92
|
+
if (cb(point.data)) {
|
|
93
|
+
return point.data;
|
|
94
|
+
}
|
|
95
|
+
point = point.prevSameType;
|
|
96
|
+
}
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* 获取当前栈顶的类型
|
|
101
|
+
*/
|
|
102
|
+
get peekType() {
|
|
103
|
+
return this.top ? this.top.type : null;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* 获取栈顶元素
|
|
107
|
+
*/
|
|
108
|
+
peek() {
|
|
109
|
+
return this.top.data;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
31
112
|
|
|
32
113
|
var __defProp$1 = Object.defineProperty;
|
|
33
114
|
var __defProps$1 = Object.defineProperties;
|
|
@@ -77,61 +158,94 @@ class Interpreter {
|
|
|
77
158
|
return [hookType, value];
|
|
78
159
|
};
|
|
79
160
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
// anchor: any;
|
|
161
|
+
isLogicNode(node) {
|
|
162
|
+
return node && node.__logicType & Logical;
|
|
163
|
+
}
|
|
84
164
|
program(root, before) {
|
|
165
|
+
var _a;
|
|
85
166
|
const componentNode = {
|
|
86
167
|
__logicType: LogicType.Component,
|
|
87
168
|
realParent: root,
|
|
88
169
|
store: new Store()
|
|
89
170
|
};
|
|
90
171
|
this.tokenizer.consume();
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const
|
|
172
|
+
const stack = new TypedStack();
|
|
173
|
+
stack.push({ node: root, prev: null }, NodeType.Real);
|
|
174
|
+
const ctx = {
|
|
175
|
+
realParent: root,
|
|
176
|
+
prevSibling: before,
|
|
177
|
+
current: null,
|
|
178
|
+
stack,
|
|
179
|
+
before
|
|
180
|
+
};
|
|
181
|
+
const rootPulling = getPulling();
|
|
94
182
|
while (1) {
|
|
95
183
|
if (this.tokenizer.isEof()) {
|
|
96
|
-
|
|
184
|
+
if (!ctx.prevSibling) ctx.prevSibling = before;
|
|
185
|
+
this.handleInsert(root, ctx.current, ctx.prevSibling, componentNode);
|
|
97
186
|
break;
|
|
98
187
|
}
|
|
99
188
|
const token = this.tokenizer.token;
|
|
100
189
|
if (token.type & TokenType.Indent) {
|
|
101
190
|
this.tokenizer.consume();
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
191
|
+
const isLogicNode = this.isLogicNode(ctx.current);
|
|
192
|
+
stack.push(
|
|
193
|
+
{
|
|
194
|
+
node: ctx.current,
|
|
195
|
+
prev: ctx.prevSibling
|
|
196
|
+
},
|
|
197
|
+
ctx.current.__logicType ? isLogicNode ? NodeType.Logic : NodeType.Component : NodeType.Real
|
|
198
|
+
);
|
|
199
|
+
if (ctx.current.__logicType) {
|
|
200
|
+
if (isLogicNode) {
|
|
201
|
+
setPulling(ctx.current.effect.ins);
|
|
202
|
+
}
|
|
203
|
+
} else {
|
|
204
|
+
ctx.realParent = ctx.current;
|
|
205
|
+
ctx.prevSibling = null;
|
|
206
|
+
}
|
|
207
|
+
ctx.current = this.declaration(ctx);
|
|
108
208
|
continue;
|
|
109
209
|
}
|
|
110
|
-
if (current) {
|
|
111
|
-
if (stack.length
|
|
112
|
-
|
|
113
|
-
this.handleInsert(parent, current, prevSibling);
|
|
114
|
-
} else {
|
|
115
|
-
if (!prevSibling) {
|
|
116
|
-
prevSibling = before;
|
|
117
|
-
}
|
|
118
|
-
this.handleInsert(root, current, prevSibling, componentNode);
|
|
210
|
+
if (ctx.current) {
|
|
211
|
+
if (stack.length === 1 && !ctx.prevSibling) {
|
|
212
|
+
ctx.prevSibling = before;
|
|
119
213
|
}
|
|
214
|
+
this.handleInsert(ctx.realParent, ctx.current, ctx.prevSibling);
|
|
120
215
|
}
|
|
121
216
|
if (this.tokenizer.token.type & TokenType.Dedent) {
|
|
122
217
|
this.tokenizer.consume();
|
|
123
|
-
const { node: parent, prev } = stack.
|
|
124
|
-
|
|
125
|
-
|
|
218
|
+
const { node: parent, prev } = stack.peek();
|
|
219
|
+
if (!parent.__logicType) {
|
|
220
|
+
const prevSameType = stack.getPrevSameType();
|
|
221
|
+
ctx.realParent = prevSameType == null ? void 0 : prevSameType.node;
|
|
222
|
+
} else {
|
|
223
|
+
if (this.isLogicNode(parent)) {
|
|
224
|
+
const parentLogic = (_a = stack.getPrevSameType()) == null ? void 0 : _a.node;
|
|
225
|
+
if (parentLogic) {
|
|
226
|
+
setPulling(parentLogic.effect.ins);
|
|
227
|
+
} else {
|
|
228
|
+
setPulling(rootPulling);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
stack.pop();
|
|
233
|
+
ctx.prevSibling = prev;
|
|
234
|
+
ctx.current = parent;
|
|
126
235
|
} else {
|
|
127
|
-
prevSibling = current;
|
|
128
|
-
current = this.declaration(
|
|
236
|
+
ctx.prevSibling = ctx.current || ctx.prevSibling;
|
|
237
|
+
ctx.current = this.declaration(ctx);
|
|
129
238
|
}
|
|
130
239
|
}
|
|
131
|
-
componentNode.lastInserted = this.lastInserted;
|
|
132
|
-
this.lastInserted = null;
|
|
133
240
|
return componentNode;
|
|
134
241
|
}
|
|
242
|
+
insertAfterAnchor(ctx) {
|
|
243
|
+
const { realParent, prevSibling, stack, before } = ctx;
|
|
244
|
+
const afterAnchor = this.createAnchor();
|
|
245
|
+
ctx.prevSibling = stack.length === 1 && !prevSibling ? before : prevSibling;
|
|
246
|
+
this.handleInsert(realParent, afterAnchor, prevSibling);
|
|
247
|
+
return afterAnchor;
|
|
248
|
+
}
|
|
135
249
|
/** 处理
|
|
136
250
|
* 是逻辑 是普通
|
|
137
251
|
* 父节点 将子节点加入 directList 调用 insert 方法挨个插入子节点
|
|
@@ -143,25 +257,14 @@ class Interpreter {
|
|
|
143
257
|
if (!prev || !prev.__logicType) {
|
|
144
258
|
this.insertAfter(parent, child, prev);
|
|
145
259
|
} else {
|
|
146
|
-
const before = prev.
|
|
260
|
+
const before = prev.realAfter;
|
|
147
261
|
this.insertAfter(parent, child, before);
|
|
148
|
-
prev.realAfter = child;
|
|
149
262
|
}
|
|
150
263
|
} else {
|
|
151
264
|
const childCmp = child;
|
|
152
265
|
childCmp.realParent = parent;
|
|
153
|
-
if (
|
|
154
|
-
|
|
155
|
-
this.insertAfter(parent, anchor, prev);
|
|
156
|
-
this.insertAfter(parent, child, anchor);
|
|
157
|
-
childCmp.realBefore = anchor;
|
|
158
|
-
} else if (prev.__logicType) {
|
|
159
|
-
const before = prev.lastInserted;
|
|
160
|
-
const anchor = this.createAnchor();
|
|
161
|
-
this.insertAfter(parent, anchor, before);
|
|
162
|
-
this.insertAfter(parent, child, anchor);
|
|
163
|
-
childCmp.realBefore = anchor;
|
|
164
|
-
prev.realAfter = anchor;
|
|
266
|
+
if (prev.__logicType) {
|
|
267
|
+
childCmp.realBefore = prev.realAfter;
|
|
165
268
|
} else {
|
|
166
269
|
childCmp.realBefore = prev;
|
|
167
270
|
}
|
|
@@ -189,7 +292,7 @@ class Interpreter {
|
|
|
189
292
|
const [hookType, value] = this._hook({});
|
|
190
293
|
let _node;
|
|
191
294
|
if (value === "if") {
|
|
192
|
-
return this.ifDeclaration();
|
|
295
|
+
return this.ifDeclaration(ctx);
|
|
193
296
|
} else if (hookType) {
|
|
194
297
|
if (hookType === "static") {
|
|
195
298
|
if (typeof value === "function" && value.prototype instanceof Store) {
|
|
@@ -263,37 +366,66 @@ class Interpreter {
|
|
|
263
366
|
child[Keys.Raw][key] = value;
|
|
264
367
|
}
|
|
265
368
|
};
|
|
369
|
+
const afterAnchor = this.insertAfterAnchor(ctx);
|
|
266
370
|
tap.once(TerpEvt.AllAttrGot, () => {
|
|
267
|
-
const parent = ctx.
|
|
371
|
+
const parent = ctx.realParent;
|
|
268
372
|
const prev = ctx.prevSibling;
|
|
269
373
|
this.onePropParsed = prevOnePropParsed;
|
|
270
374
|
const componentNode = child["ui"](this.opt, { data: child }, parent, prev);
|
|
375
|
+
componentNode.realAfter = afterAnchor;
|
|
271
376
|
tap.emit(TerpEvt.HandledComponentNode, componentNode);
|
|
272
377
|
});
|
|
273
378
|
return { __logicType: LogicType.Component };
|
|
274
379
|
}
|
|
275
|
-
ifDeclaration() {
|
|
380
|
+
ifDeclaration(ctx) {
|
|
276
381
|
this.tokenizer.consume();
|
|
277
|
-
const [
|
|
382
|
+
const [hookType, value] = this._hook({});
|
|
278
383
|
const ifNode = {
|
|
279
384
|
__logicType: LogicType.If,
|
|
280
|
-
condition: value,
|
|
281
|
-
realParent: null,
|
|
282
385
|
snapshot: this.tokenizer.snapshot(),
|
|
386
|
+
condition: null,
|
|
387
|
+
realParent: null,
|
|
283
388
|
isFirstRender: true,
|
|
284
|
-
|
|
285
|
-
anchor: null
|
|
389
|
+
effect: null
|
|
286
390
|
};
|
|
287
|
-
|
|
391
|
+
const valueIsMapKey = Reflect.has(this.data[Keys.Raw], value);
|
|
392
|
+
let signal;
|
|
393
|
+
if (valueIsMapKey) {
|
|
394
|
+
runWithPulling(() => this.data[value], null);
|
|
395
|
+
const { cells } = this.data[Keys.Meta];
|
|
396
|
+
signal = cells.get(value);
|
|
397
|
+
} else {
|
|
398
|
+
const fn = new Function("data", `let v;with(data){v=${value}};return v;`).bind(void 0, this.data);
|
|
399
|
+
signal = $(fn);
|
|
400
|
+
}
|
|
401
|
+
ifNode.condition = signal;
|
|
402
|
+
ifNode.realAfter = this.insertAfterAnchor(ctx);
|
|
403
|
+
ifNode.effect = effect(
|
|
288
404
|
({ val }) => {
|
|
289
405
|
if (val) {
|
|
290
|
-
|
|
291
|
-
|
|
406
|
+
if (ifNode.isFirstRender) {
|
|
407
|
+
this.tokenizer.consume();
|
|
408
|
+
this.tokenizer.consume();
|
|
409
|
+
} else {
|
|
410
|
+
this.tokenizer.resume(ifNode.snapshot);
|
|
411
|
+
this.program(ifNode.realParent, ifNode.realBefore);
|
|
412
|
+
}
|
|
292
413
|
} else {
|
|
293
|
-
|
|
414
|
+
if (ifNode.isFirstRender) {
|
|
415
|
+
this.tokenizer.skip();
|
|
416
|
+
} else {
|
|
417
|
+
const { realBefore, realAfter, realParent } = ifNode;
|
|
418
|
+
let point = this.nextSib(realBefore);
|
|
419
|
+
while (point !== realAfter) {
|
|
420
|
+
const next = this.nextSib(point);
|
|
421
|
+
this.remove(point, realParent, realBefore);
|
|
422
|
+
point = next;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
294
425
|
}
|
|
426
|
+
ifNode.isFirstRender = false;
|
|
295
427
|
},
|
|
296
|
-
[
|
|
428
|
+
[signal]
|
|
297
429
|
);
|
|
298
430
|
return ifNode;
|
|
299
431
|
}
|
|
@@ -371,6 +503,11 @@ class Interpreter {
|
|
|
371
503
|
nextSib(node) {
|
|
372
504
|
return node.nextSibling;
|
|
373
505
|
}
|
|
506
|
+
_createAnchor() {
|
|
507
|
+
const anchor = this.createAnchor();
|
|
508
|
+
anchor[IsAnchor] = true;
|
|
509
|
+
return anchor;
|
|
510
|
+
}
|
|
374
511
|
createAnchor() {
|
|
375
512
|
return {
|
|
376
513
|
name: "anchor",
|
|
@@ -378,7 +515,6 @@ class Interpreter {
|
|
|
378
515
|
};
|
|
379
516
|
}
|
|
380
517
|
insertAfter(parent, node, prev) {
|
|
381
|
-
this.lastInserted = node;
|
|
382
518
|
return this.defaultInsert(parent, node, prev);
|
|
383
519
|
}
|
|
384
520
|
defaultInsert(parent, node, prev) {
|
|
@@ -390,11 +526,11 @@ class Interpreter {
|
|
|
390
526
|
parent.firstChild = node;
|
|
391
527
|
}
|
|
392
528
|
}
|
|
393
|
-
remove(
|
|
394
|
-
return this.defaultRemove(
|
|
529
|
+
remove(node, parent, prev) {
|
|
530
|
+
return this.defaultRemove(node, parent, prev);
|
|
395
531
|
}
|
|
396
532
|
// TODO: 默认改成 prevItem
|
|
397
|
-
defaultRemove(
|
|
533
|
+
defaultRemove(node, parent, prevSibling) {
|
|
398
534
|
const next = node.nextSibling;
|
|
399
535
|
if (prevSibling) {
|
|
400
536
|
prevSibling.nextSibling = next;
|
|
@@ -467,7 +603,7 @@ const _Tokenizer = class _Tokenizer {
|
|
|
467
603
|
};
|
|
468
604
|
}
|
|
469
605
|
skip() {
|
|
470
|
-
const
|
|
606
|
+
const logicDentLen = this.dentStack[this.dentStack.length - 1];
|
|
471
607
|
let needIndent = false;
|
|
472
608
|
let skipFragment = ``;
|
|
473
609
|
this.token = void 0;
|
|
@@ -488,7 +624,7 @@ const _Tokenizer = class _Tokenizer {
|
|
|
488
624
|
const { value, isEmptyLine } = this.getDentValue();
|
|
489
625
|
const currLen = value.length;
|
|
490
626
|
if (isEmptyLine) continue;
|
|
491
|
-
if (
|
|
627
|
+
if (currLen > logicDentLen) {
|
|
492
628
|
skipFragment += value;
|
|
493
629
|
} else {
|
|
494
630
|
for (let i = this.dentStack.length - 1; i >= 0; i--) {
|
|
@@ -497,6 +633,9 @@ const _Tokenizer = class _Tokenizer {
|
|
|
497
633
|
if (currLen > expLen) {
|
|
498
634
|
throw SyntaxError(`\u7F29\u8FDB\u9519\u8BEF\uFF0C\u7F29\u8FDB\u957F\u5EA6\u4E0D\u5339\u914D`);
|
|
499
635
|
}
|
|
636
|
+
if (this.shorterThanBaseDentEof()) {
|
|
637
|
+
break;
|
|
638
|
+
}
|
|
500
639
|
this.dentStack.pop();
|
|
501
640
|
if (!this.token) {
|
|
502
641
|
this.setToken(TokenType.Dedent, String(expLen));
|
|
@@ -761,12 +900,15 @@ ${_Tokenizer.EofId}`;
|
|
|
761
900
|
return indentHasLen;
|
|
762
901
|
}
|
|
763
902
|
if (currLen < prevLen) {
|
|
764
|
-
for (let i = this.dentStack.length
|
|
903
|
+
for (let i = this.dentStack.length; i--; ) {
|
|
765
904
|
const expLen = this.dentStack[i];
|
|
766
|
-
|
|
767
|
-
if (currLen > expLen
|
|
905
|
+
if (currLen === expLen) break;
|
|
906
|
+
if (currLen > expLen) {
|
|
768
907
|
throw SyntaxError("\u7F29\u8FDB\u5927\u5C0F\u4E0D\u7EDF\u4E00");
|
|
769
908
|
}
|
|
909
|
+
if (this.shorterThanBaseDentEof()) {
|
|
910
|
+
return;
|
|
911
|
+
}
|
|
770
912
|
this.dentStack.pop();
|
|
771
913
|
if (!this.token) {
|
|
772
914
|
this.setToken(TokenType.Dedent, String(expLen));
|
|
@@ -777,14 +919,26 @@ ${_Tokenizer.EofId}`;
|
|
|
777
919
|
value: String(expLen)
|
|
778
920
|
});
|
|
779
921
|
}
|
|
780
|
-
if (currLen === expLen) {
|
|
781
|
-
break;
|
|
782
|
-
}
|
|
783
922
|
}
|
|
784
923
|
return indentHasLen;
|
|
785
924
|
}
|
|
786
925
|
return indentHasLen;
|
|
787
926
|
}
|
|
927
|
+
shorterThanBaseDentEof() {
|
|
928
|
+
const yes = this.dentStack.length === 1;
|
|
929
|
+
if (yes) {
|
|
930
|
+
if (!this.token) {
|
|
931
|
+
this.setToken(TokenType.Identifier, _Tokenizer.EofId);
|
|
932
|
+
} else {
|
|
933
|
+
this.waitingTokens.push({
|
|
934
|
+
type: TokenType.Identifier,
|
|
935
|
+
typeName: TokenType[TokenType.Identifier],
|
|
936
|
+
value: _Tokenizer.EofId
|
|
937
|
+
});
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
return yes;
|
|
941
|
+
}
|
|
788
942
|
identifier(char) {
|
|
789
943
|
let value = char;
|
|
790
944
|
let nextC;
|