bobe 0.0.15 → 0.0.16
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 +280 -219
- package/dist/bobe.cjs.js.map +1 -1
- package/dist/bobe.esm.js +281 -220
- package/dist/bobe.esm.js.map +1 -1
- package/dist/index.d.ts +61 -53
- package/dist/index.umd.js +280 -219
- 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 {
|
|
1
|
+
import { getPulling, setPulling, Store, Keys, effect, shareSignal, $, runWithPulling } from 'aoye';
|
|
2
2
|
export * from 'aoye';
|
|
3
3
|
import { BaseEvent, Queue, isNum } from 'bobe-shared';
|
|
4
4
|
|
|
@@ -13,25 +13,27 @@ var TokenType = /* @__PURE__ */ ((TokenType2) => {
|
|
|
13
13
|
TokenType2[TokenType2["InsertionExp"] = 128] = "InsertionExp";
|
|
14
14
|
return TokenType2;
|
|
15
15
|
})(TokenType || {});
|
|
16
|
-
var
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
var
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
16
|
+
var FakeType = /* @__PURE__ */ ((FakeType2) => {
|
|
17
|
+
FakeType2[FakeType2["If"] = 1] = "If";
|
|
18
|
+
FakeType2[FakeType2["Fail"] = 2] = "Fail";
|
|
19
|
+
FakeType2[FakeType2["Else"] = 4] = "Else";
|
|
20
|
+
FakeType2[FakeType2["For"] = 8] = "For";
|
|
21
|
+
FakeType2[FakeType2["Component"] = 16] = "Component";
|
|
22
|
+
FakeType2[FakeType2["Fragment"] = 32] = "Fragment";
|
|
23
|
+
FakeType2[FakeType2["ForItem"] = 64] = "ForItem";
|
|
24
|
+
return FakeType2;
|
|
25
|
+
})(FakeType || {});
|
|
26
|
+
const CondBit = 1 /* If */ | 2 /* Fail */ | 4 /* Else */;
|
|
27
|
+
const LogicalBit = 1 /* If */ | 2 /* Fail */ | 4 /* Else */ | 8 /* For */ | 64 /* ForItem */;
|
|
28
|
+
const TokenizerSwitcherBit = 16 /* Component */ | 32 /* Fragment */;
|
|
29
|
+
var NodeSort = /* @__PURE__ */ ((NodeSort2) => {
|
|
30
|
+
NodeSort2[NodeSort2["Logic"] = 1] = "Logic";
|
|
31
|
+
NodeSort2[NodeSort2["Real"] = 2] = "Real";
|
|
32
|
+
NodeSort2[NodeSort2["Component"] = 4] = "Component";
|
|
33
|
+
NodeSort2[NodeSort2["CtxProvider"] = 8] = "CtxProvider";
|
|
34
|
+
NodeSort2[NodeSort2["TokenizerSwitcher"] = 16] = "TokenizerSwitcher";
|
|
35
|
+
return NodeSort2;
|
|
36
|
+
})(NodeSort || {});
|
|
35
37
|
var TerpEvt = /* @__PURE__ */ ((TerpEvt2) => {
|
|
36
38
|
TerpEvt2["AllAttrGot"] = "all-attr-got";
|
|
37
39
|
TerpEvt2["HandledComponentNode"] = "handled-component-node";
|
|
@@ -39,140 +41,119 @@ var TerpEvt = /* @__PURE__ */ ((TerpEvt2) => {
|
|
|
39
41
|
})(TerpEvt || {});
|
|
40
42
|
const IsAnchor = /* @__PURE__ */ Symbol("is-anchor");
|
|
41
43
|
|
|
42
|
-
class
|
|
44
|
+
class MultiTypeStack {
|
|
43
45
|
constructor() {
|
|
46
|
+
// 记录全局栈顶
|
|
44
47
|
this.top = null;
|
|
45
|
-
//
|
|
46
|
-
|
|
47
|
-
this.lastNodes = {};
|
|
48
|
+
// 记录每个类别的当前最新节点(各分类的“栈顶”)
|
|
49
|
+
this.typeTops = {};
|
|
48
50
|
this.length = 0;
|
|
49
51
|
}
|
|
50
52
|
/**
|
|
51
|
-
*
|
|
52
|
-
* @param
|
|
53
|
+
* 入栈操作
|
|
54
|
+
* @param value 数据
|
|
55
|
+
* @param bits 该节点所属的类别数组
|
|
53
56
|
*/
|
|
54
|
-
push(
|
|
55
|
-
var _a;
|
|
57
|
+
push(value, bits) {
|
|
56
58
|
const newNode = {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
value,
|
|
60
|
+
types: bits,
|
|
61
|
+
prevGlobal: this.top,
|
|
62
|
+
prevByType: {}
|
|
61
63
|
};
|
|
64
|
+
let bit;
|
|
65
|
+
while (1) {
|
|
66
|
+
bit = bits & ~bits + 1;
|
|
67
|
+
if (!bit) break;
|
|
68
|
+
bits &= ~bit;
|
|
69
|
+
newNode.prevByType[bit] = this.typeTops[bit] || void 0;
|
|
70
|
+
this.typeTops[bit] = newNode;
|
|
71
|
+
}
|
|
62
72
|
this.top = newNode;
|
|
63
73
|
this.length++;
|
|
64
|
-
this.lastNodes[type] = newNode;
|
|
65
74
|
}
|
|
66
75
|
/**
|
|
67
76
|
* 出栈操作
|
|
68
|
-
* @returns 原始节点数据或 null
|
|
69
77
|
*/
|
|
70
78
|
pop() {
|
|
71
|
-
if (!this.top) return
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
79
|
+
if (!this.top) return void 0;
|
|
80
|
+
const poppedNode = this.top;
|
|
81
|
+
let { types: bits } = poppedNode;
|
|
82
|
+
let bit;
|
|
83
|
+
while (1) {
|
|
84
|
+
bit = bits & ~bits + 1;
|
|
85
|
+
if (!bit) break;
|
|
86
|
+
bits &= ~bit;
|
|
87
|
+
this.typeTops[bit] = poppedNode.prevByType[bit];
|
|
88
|
+
}
|
|
89
|
+
this.top = poppedNode.prevGlobal;
|
|
75
90
|
this.length--;
|
|
76
|
-
return
|
|
91
|
+
return [poppedNode.value, poppedNode.types];
|
|
77
92
|
}
|
|
78
93
|
/**
|
|
79
|
-
*
|
|
94
|
+
* 获取某个类别的当前“顶部”元素
|
|
80
95
|
*/
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
return this.top.prevSameType.data;
|
|
96
|
+
peekByType(cat) {
|
|
97
|
+
var _a;
|
|
98
|
+
return (_a = this.typeTops[cat]) == null ? void 0 : _a.value;
|
|
86
99
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
let point = this.top.prevSameType;
|
|
92
|
-
while (point) {
|
|
93
|
-
if (cb(point.data)) {
|
|
94
|
-
return point.data;
|
|
95
|
-
}
|
|
96
|
-
point = point.prevSameType;
|
|
97
|
-
}
|
|
98
|
-
return null;
|
|
100
|
+
peekType() {
|
|
101
|
+
var _a;
|
|
102
|
+
return (_a = this.top) == null ? void 0 : _a.types;
|
|
99
103
|
}
|
|
100
104
|
/**
|
|
101
|
-
*
|
|
105
|
+
* 获取全局栈顶
|
|
102
106
|
*/
|
|
103
|
-
|
|
104
|
-
|
|
107
|
+
peek() {
|
|
108
|
+
var _a;
|
|
109
|
+
return (_a = this.top) == null ? void 0 : _a.value;
|
|
105
110
|
}
|
|
106
111
|
/**
|
|
107
|
-
*
|
|
112
|
+
* 1. 全局向前遍历 (不分类)
|
|
113
|
+
* 从栈顶开始,沿着全局链条向栈底遍历
|
|
108
114
|
*/
|
|
109
|
-
|
|
110
|
-
|
|
115
|
+
forEach(callback) {
|
|
116
|
+
let current = this.top;
|
|
117
|
+
while (current !== null) {
|
|
118
|
+
const shouldBreak = callback(current.value, current.types);
|
|
119
|
+
if (shouldBreak) break;
|
|
120
|
+
current = current.prevGlobal;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* 2. 按类别向前遍历
|
|
125
|
+
* 仅遍历属于指定类别 cat 的节点
|
|
126
|
+
*/
|
|
127
|
+
forEachByType(cat, callback) {
|
|
128
|
+
let current = this.typeTops[cat];
|
|
129
|
+
while (current) {
|
|
130
|
+
const shouldBreak = callback(current.value);
|
|
131
|
+
if (shouldBreak) break;
|
|
132
|
+
current = current.prevByType[cat];
|
|
133
|
+
}
|
|
111
134
|
}
|
|
112
135
|
}
|
|
113
136
|
|
|
114
|
-
var __defProp$1 = Object.defineProperty;
|
|
115
|
-
var __defProps$1 = Object.defineProperties;
|
|
116
|
-
var __getOwnPropDescs$1 = Object.getOwnPropertyDescriptors;
|
|
117
|
-
var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols;
|
|
118
|
-
var __hasOwnProp$1 = Object.prototype.hasOwnProperty;
|
|
119
|
-
var __propIsEnum$1 = Object.prototype.propertyIsEnumerable;
|
|
120
|
-
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
121
|
-
var __spreadValues$1 = (a, b) => {
|
|
122
|
-
for (var prop in b || (b = {}))
|
|
123
|
-
if (__hasOwnProp$1.call(b, prop))
|
|
124
|
-
__defNormalProp$1(a, prop, b[prop]);
|
|
125
|
-
if (__getOwnPropSymbols$1)
|
|
126
|
-
for (var prop of __getOwnPropSymbols$1(b)) {
|
|
127
|
-
if (__propIsEnum$1.call(b, prop))
|
|
128
|
-
__defNormalProp$1(a, prop, b[prop]);
|
|
129
|
-
}
|
|
130
|
-
return a;
|
|
131
|
-
};
|
|
132
|
-
var __spreadProps$1 = (a, b) => __defProps$1(a, __getOwnPropDescs$1(b));
|
|
133
137
|
const tap = new BaseEvent();
|
|
134
138
|
class Interpreter {
|
|
135
139
|
constructor(tokenizer) {
|
|
136
140
|
this.tokenizer = tokenizer;
|
|
137
|
-
|
|
138
|
-
this.HookId = "_h_o_o_k_";
|
|
139
|
-
/** 用于渲染的数据 */
|
|
140
|
-
this.data = {};
|
|
141
|
-
/** 模板字符串动态节点索引 */
|
|
142
|
-
this.hookI = 0;
|
|
143
|
-
this._hook = (props) => {
|
|
144
|
-
const value = this.tokenizer.token.value;
|
|
145
|
-
const isDynamicHook = this.tokenizer.token.type & TokenType.InsertionExp;
|
|
146
|
-
const isStaticHook = typeof value === "string" && value.indexOf(this.HookId) === 0;
|
|
147
|
-
const hookType = isDynamicHook ? "dynamic" : isStaticHook ? "static" : void 0;
|
|
148
|
-
if (this.hook && isStaticHook) {
|
|
149
|
-
const hookI = Number(value.slice(this.HookId.length));
|
|
150
|
-
const res = this.hook(__spreadProps$1(__spreadValues$1({}, props), {
|
|
151
|
-
HookId: this.HookId,
|
|
152
|
-
i: hookI
|
|
153
|
-
}));
|
|
154
|
-
this.hookI++;
|
|
155
|
-
return [hookType, res];
|
|
156
|
-
} else if (isDynamicHook) {
|
|
157
|
-
return [hookType, value];
|
|
158
|
-
}
|
|
159
|
-
return [hookType, value];
|
|
160
|
-
};
|
|
141
|
+
this.rootComponent = null;
|
|
161
142
|
}
|
|
162
143
|
isLogicNode(node) {
|
|
163
|
-
return node && node.__logicType &
|
|
144
|
+
return node && node.__logicType & LogicalBit;
|
|
164
145
|
}
|
|
165
|
-
program(root, before) {
|
|
166
|
-
var _a;
|
|
167
|
-
|
|
168
|
-
__logicType: LogicType.Component,
|
|
169
|
-
realParent: root,
|
|
170
|
-
store: new Store()
|
|
171
|
-
};
|
|
146
|
+
program(root, componentNode, before) {
|
|
147
|
+
var _a, _b;
|
|
148
|
+
this.rootComponent = componentNode;
|
|
172
149
|
this.tokenizer.consume();
|
|
173
|
-
const stack = new
|
|
174
|
-
stack.push({ node: root, prev: null },
|
|
175
|
-
|
|
150
|
+
const stack = new MultiTypeStack();
|
|
151
|
+
stack.push({ node: root, prev: null }, NodeSort.Real);
|
|
152
|
+
stack.push(
|
|
153
|
+
{ node: componentNode, prev: null },
|
|
154
|
+
NodeSort.Component | NodeSort.CtxProvider | NodeSort.TokenizerSwitcher
|
|
155
|
+
);
|
|
156
|
+
const ctx = this.ctx = {
|
|
176
157
|
realParent: root,
|
|
177
158
|
prevSibling: before,
|
|
178
159
|
current: null,
|
|
@@ -195,7 +176,7 @@ class Interpreter {
|
|
|
195
176
|
node: ctx.current,
|
|
196
177
|
prev: ctx.prevSibling
|
|
197
178
|
},
|
|
198
|
-
ctx.current.__logicType ?
|
|
179
|
+
!ctx.current.__logicType ? NodeSort.Real : (ctx.current.__logicType & LogicalBit ? NodeSort.Logic : 0) | (ctx.current.__logicType & TokenizerSwitcherBit ? NodeSort.TokenizerSwitcher : 0) | (ctx.current.__logicType === FakeType.Component ? NodeSort.Component : 0) | NodeSort.CtxProvider
|
|
199
180
|
);
|
|
200
181
|
if (ctx.current.__logicType) {
|
|
201
182
|
if (isLogicNode) {
|
|
@@ -211,28 +192,31 @@ class Interpreter {
|
|
|
211
192
|
continue;
|
|
212
193
|
}
|
|
213
194
|
if (ctx.current) {
|
|
214
|
-
if (stack.length ===
|
|
195
|
+
if (stack.length === 2 && !ctx.prevSibling) {
|
|
215
196
|
ctx.prevSibling = before;
|
|
216
197
|
}
|
|
217
198
|
this.handleInsert(ctx.realParent, ctx.current, ctx.prevSibling);
|
|
218
199
|
}
|
|
219
200
|
if (this.tokenizer.token.type & TokenType.Dedent) {
|
|
220
201
|
this.tokenizer.consume();
|
|
221
|
-
const { node: parent, prev } = stack.
|
|
202
|
+
const [{ node: parent, prev }, sort] = stack.pop();
|
|
222
203
|
if (!parent.__logicType) {
|
|
223
|
-
const prevSameType = stack.
|
|
204
|
+
const prevSameType = stack.peekByType(NodeSort.Real);
|
|
224
205
|
ctx.realParent = (prevSameType == null ? void 0 : prevSameType.node) || root;
|
|
225
206
|
} else {
|
|
226
|
-
if (
|
|
227
|
-
const parentLogic = (_a = stack.
|
|
207
|
+
if (sort & NodeSort.Logic) {
|
|
208
|
+
const parentLogic = (_a = stack.peekByType(NodeSort.Logic)) == null ? void 0 : _a.node;
|
|
228
209
|
if (parentLogic) {
|
|
229
210
|
setPulling(parentLogic.effect.ins);
|
|
230
211
|
} else {
|
|
231
212
|
setPulling(rootPulling);
|
|
232
213
|
}
|
|
233
214
|
}
|
|
215
|
+
if (sort & NodeSort.TokenizerSwitcher) {
|
|
216
|
+
const switcher = (_b = stack.peekByType(NodeSort.TokenizerSwitcher)) == null ? void 0 : _b.node;
|
|
217
|
+
this.tokenizer = switcher.tokenizer;
|
|
218
|
+
}
|
|
234
219
|
}
|
|
235
|
-
stack.pop();
|
|
236
220
|
ctx.prevSibling = prev;
|
|
237
221
|
ctx.current = parent;
|
|
238
222
|
} else {
|
|
@@ -242,10 +226,15 @@ class Interpreter {
|
|
|
242
226
|
}
|
|
243
227
|
return componentNode;
|
|
244
228
|
}
|
|
229
|
+
switcherIsRootComponent() {
|
|
230
|
+
var _a;
|
|
231
|
+
const currentSwitcher = (_a = this.ctx.stack.peekByType(NodeSort.TokenizerSwitcher)) == null ? void 0 : _a.node;
|
|
232
|
+
return currentSwitcher === this.rootComponent;
|
|
233
|
+
}
|
|
245
234
|
insertAfterAnchor(ctx) {
|
|
246
235
|
const { realParent, prevSibling, stack, before } = ctx;
|
|
247
236
|
const afterAnchor = this.createAnchor();
|
|
248
|
-
ctx.prevSibling = stack.length ===
|
|
237
|
+
ctx.prevSibling = stack.length === 2 && !prevSibling ? before : prevSibling;
|
|
249
238
|
this.handleInsert(realParent, afterAnchor, prevSibling);
|
|
250
239
|
return afterAnchor;
|
|
251
240
|
}
|
|
@@ -292,7 +281,7 @@ class Interpreter {
|
|
|
292
281
|
* <declaration> ::= <tagName=token> <headerLine> <extensionLines>
|
|
293
282
|
* */
|
|
294
283
|
declaration(ctx) {
|
|
295
|
-
const [hookType, value] = this._hook({});
|
|
284
|
+
const [hookType, value] = this.tokenizer._hook({});
|
|
296
285
|
let _node;
|
|
297
286
|
if (value === "if" || value === "else" || value === "fail") {
|
|
298
287
|
return this.condDeclaration(ctx);
|
|
@@ -301,12 +290,13 @@ class Interpreter {
|
|
|
301
290
|
if (typeof value === "function" && value.prototype instanceof Store) {
|
|
302
291
|
_node = this.componentDeclaration(value, ctx);
|
|
303
292
|
} else if (typeof value === "function") {
|
|
304
|
-
_node = this.fragmentDeclaration(value);
|
|
293
|
+
_node = this.fragmentDeclaration(value, ctx);
|
|
305
294
|
} else {
|
|
306
295
|
throw new SyntaxError(`declaration \u4E0D\u652F\u6301 ${value} \u7C7B\u578B\u7684\u9759\u6001\u63D2\u503C`);
|
|
307
296
|
}
|
|
308
297
|
} else {
|
|
309
|
-
|
|
298
|
+
const data = this.getData();
|
|
299
|
+
Boolean(data[Keys.Raw][value]);
|
|
310
300
|
new Function("data", `let v;with(data){v=(${value})};return v`);
|
|
311
301
|
_node = this.createNode(value);
|
|
312
302
|
}
|
|
@@ -316,19 +306,26 @@ class Interpreter {
|
|
|
316
306
|
this.tokenizer.consume();
|
|
317
307
|
this.headerLine(_node);
|
|
318
308
|
this.extensionLines(_node);
|
|
319
|
-
if (_node.__logicType ===
|
|
309
|
+
if (_node.__logicType === FakeType.Component) {
|
|
320
310
|
tap.once(TerpEvt.HandledComponentNode, (node) => _node = node);
|
|
321
311
|
tap.emit(TerpEvt.AllAttrGot);
|
|
322
312
|
}
|
|
323
313
|
return _node;
|
|
324
314
|
}
|
|
315
|
+
getData() {
|
|
316
|
+
const { node } = this.ctx.stack.peekByType(NodeSort.CtxProvider);
|
|
317
|
+
return node.data || node.owner.data;
|
|
318
|
+
}
|
|
325
319
|
// TODO: 指定挂载位置
|
|
326
|
-
fragmentDeclaration(renderFragment) {
|
|
320
|
+
fragmentDeclaration(renderFragment, ctx) {
|
|
321
|
+
const data = this.getData();
|
|
322
|
+
const tokenizer = renderFragment.call(data, this.opt, { data, root: "", anchor: "" });
|
|
327
323
|
const fragmentNode = {
|
|
328
|
-
__logicType:
|
|
329
|
-
realParent: null
|
|
324
|
+
__logicType: FakeType.Fragment,
|
|
325
|
+
realParent: null,
|
|
326
|
+
tokenizer,
|
|
327
|
+
data: null
|
|
330
328
|
};
|
|
331
|
-
renderFragment.call(this.data, this.opt, { data: this.data, root: "", anchor: "" });
|
|
332
329
|
return fragmentNode;
|
|
333
330
|
}
|
|
334
331
|
/**
|
|
@@ -339,15 +336,17 @@ class Interpreter {
|
|
|
339
336
|
*
|
|
340
337
|
* mapKey 映射, 对应子组件的属性
|
|
341
338
|
* */
|
|
342
|
-
onePropParsed(node, key, value, valueIsMapKey, hookI) {
|
|
343
|
-
if (
|
|
339
|
+
onePropParsed(data, node, key, value, valueIsMapKey, isFn, hookI) {
|
|
340
|
+
if (isFn) {
|
|
341
|
+
this.setProp(node, key, value, hookI);
|
|
342
|
+
} else if (typeof value === "function") {
|
|
344
343
|
effect(() => {
|
|
345
344
|
const res = value();
|
|
346
345
|
this.setProp(node, key, res, hookI);
|
|
347
346
|
});
|
|
348
347
|
} else if (valueIsMapKey) {
|
|
349
348
|
effect(() => {
|
|
350
|
-
const res =
|
|
349
|
+
const res = data[value];
|
|
351
350
|
this.setProp(node, key, res, hookI);
|
|
352
351
|
});
|
|
353
352
|
} else {
|
|
@@ -356,10 +355,18 @@ class Interpreter {
|
|
|
356
355
|
}
|
|
357
356
|
componentDeclaration(Component, ctx) {
|
|
358
357
|
const child = Component.new();
|
|
358
|
+
const componentNode = {
|
|
359
|
+
__logicType: FakeType.Component,
|
|
360
|
+
realParent: ctx.realParent,
|
|
361
|
+
data: child,
|
|
362
|
+
tokenizer: null
|
|
363
|
+
};
|
|
359
364
|
const prevOnePropParsed = this.onePropParsed;
|
|
360
|
-
this.onePropParsed = (node, key, value, valueIsMapKey, hookI) => {
|
|
361
|
-
if (
|
|
362
|
-
|
|
365
|
+
this.onePropParsed = (data, node, key, value, valueIsMapKey, isFn, hookI) => {
|
|
366
|
+
if (isFn) {
|
|
367
|
+
child[Keys.Raw][key] = value;
|
|
368
|
+
} else if (valueIsMapKey) {
|
|
369
|
+
shareSignal(data, value, child, key);
|
|
363
370
|
} else if (typeof value === "function") {
|
|
364
371
|
const meta = child[Keys.Meta];
|
|
365
372
|
const cells = meta.cells;
|
|
@@ -369,37 +376,40 @@ class Interpreter {
|
|
|
369
376
|
child[Keys.Raw][key] = value;
|
|
370
377
|
}
|
|
371
378
|
};
|
|
372
|
-
|
|
379
|
+
componentNode.realAfter = this.insertAfterAnchor(ctx);
|
|
373
380
|
const { realParent, prevSibling } = ctx;
|
|
374
381
|
tap.once(TerpEvt.AllAttrGot, () => {
|
|
375
|
-
const parent = realParent;
|
|
376
|
-
const prev = prevSibling;
|
|
377
382
|
this.onePropParsed = prevOnePropParsed;
|
|
378
|
-
const
|
|
379
|
-
componentNode.
|
|
383
|
+
const subTkr = child["ui"](true);
|
|
384
|
+
componentNode.tokenizer = subTkr;
|
|
385
|
+
this.tokenizer = subTkr;
|
|
380
386
|
tap.emit(TerpEvt.HandledComponentNode, componentNode);
|
|
381
387
|
});
|
|
382
|
-
return
|
|
388
|
+
return componentNode;
|
|
383
389
|
}
|
|
384
390
|
// TODO: 优化代码逻辑,拆分 if elseif else
|
|
385
391
|
condDeclaration(ctx) {
|
|
392
|
+
var _a;
|
|
386
393
|
const { prevSibling } = ctx;
|
|
387
394
|
const snapbackUp = this.tokenizer.snapshot();
|
|
388
395
|
const keyWord = this.tokenizer.consume();
|
|
389
396
|
const noSelfCond = this.tokenizer.token.type === TokenType.NewLine;
|
|
390
|
-
const [hookType, value] = this._hook({});
|
|
397
|
+
const [hookType, value] = this.tokenizer._hook({});
|
|
391
398
|
const isElse = keyWord.value === "else";
|
|
392
399
|
const isIf = keyWord.value === "if";
|
|
393
|
-
const preIsCond = (prevSibling == null ? void 0 : prevSibling.__logicType) &
|
|
400
|
+
const preIsCond = (prevSibling == null ? void 0 : prevSibling.__logicType) & CondBit;
|
|
394
401
|
const needCalcWithPrevIf = isElse && preIsCond;
|
|
402
|
+
const data = this.getData();
|
|
403
|
+
const owner = (_a = ctx.stack.peekByType(NodeSort.TokenizerSwitcher)) == null ? void 0 : _a.node;
|
|
395
404
|
const ifNode = {
|
|
396
|
-
__logicType: isElse ?
|
|
405
|
+
__logicType: isElse ? FakeType.Else : isIf ? FakeType.If : FakeType.Fail,
|
|
397
406
|
snapshot: noSelfCond ? snapbackUp : this.tokenizer.snapshot(),
|
|
398
407
|
condition: null,
|
|
399
408
|
realParent: null,
|
|
400
409
|
preCond: preIsCond ? prevSibling : null,
|
|
401
410
|
isFirstRender: true,
|
|
402
|
-
effect: null
|
|
411
|
+
effect: null,
|
|
412
|
+
owner
|
|
403
413
|
};
|
|
404
414
|
let signal;
|
|
405
415
|
if (noSelfCond) {
|
|
@@ -410,7 +420,7 @@ class Interpreter {
|
|
|
410
420
|
if (point.condition.v) {
|
|
411
421
|
return false;
|
|
412
422
|
}
|
|
413
|
-
if (point.__logicType ===
|
|
423
|
+
if (point.__logicType === FakeType.If) {
|
|
414
424
|
break;
|
|
415
425
|
}
|
|
416
426
|
point = point.preCond;
|
|
@@ -430,13 +440,13 @@ class Interpreter {
|
|
|
430
440
|
});
|
|
431
441
|
}
|
|
432
442
|
} else {
|
|
433
|
-
const valueIsMapKey = Reflect.has(
|
|
443
|
+
const valueIsMapKey = Reflect.has(data[Keys.Raw], value);
|
|
434
444
|
if (valueIsMapKey && !needCalcWithPrevIf) {
|
|
435
|
-
runWithPulling(() =>
|
|
436
|
-
const { cells } =
|
|
445
|
+
runWithPulling(() => data[value], null);
|
|
446
|
+
const { cells } = data[Keys.Meta];
|
|
437
447
|
signal = cells.get(value);
|
|
438
448
|
} else {
|
|
439
|
-
const fn = new Function("data", `let v;with(data){v=${value}};return v;`).bind(void 0,
|
|
449
|
+
const fn = new Function("data", `let v;with(data){v=${value}};return v;`).bind(void 0, data);
|
|
440
450
|
if (needCalcWithPrevIf) {
|
|
441
451
|
signal = $(() => {
|
|
442
452
|
let point = ifNode.preCond;
|
|
@@ -444,7 +454,7 @@ class Interpreter {
|
|
|
444
454
|
if (point.condition.v) {
|
|
445
455
|
return false;
|
|
446
456
|
}
|
|
447
|
-
if (point.__logicType ===
|
|
457
|
+
if (point.__logicType === FakeType.If) {
|
|
448
458
|
break;
|
|
449
459
|
}
|
|
450
460
|
point = point.preCond;
|
|
@@ -467,8 +477,9 @@ class Interpreter {
|
|
|
467
477
|
}
|
|
468
478
|
this.tokenizer.consume();
|
|
469
479
|
} else {
|
|
480
|
+
this.tokenizer = ifNode.owner.tokenizer;
|
|
470
481
|
this.tokenizer.resume(ifNode.snapshot);
|
|
471
|
-
this.program(ifNode.realParent, ifNode.realBefore);
|
|
482
|
+
this.program(ifNode.realParent, ifNode.owner, ifNode.realBefore);
|
|
472
483
|
}
|
|
473
484
|
} else {
|
|
474
485
|
if (ifNode.isFirstRender) {
|
|
@@ -479,7 +490,7 @@ class Interpreter {
|
|
|
479
490
|
this.tokenizer.skip();
|
|
480
491
|
} else {
|
|
481
492
|
const { realBefore, realAfter, realParent } = ifNode;
|
|
482
|
-
let point = realBefore ? this.nextSib(realBefore) : this.
|
|
493
|
+
let point = realBefore ? this.nextSib(realBefore) : this.firstChild(realParent);
|
|
483
494
|
while (point !== realAfter) {
|
|
484
495
|
const next = this.nextSib(point);
|
|
485
496
|
this.remove(point, realParent, realBefore);
|
|
@@ -531,21 +542,24 @@ class Interpreter {
|
|
|
531
542
|
*/
|
|
532
543
|
attributeList(_node) {
|
|
533
544
|
let key, eq;
|
|
545
|
+
const data = this.getData();
|
|
534
546
|
while (!(this.tokenizer.token.type & TokenType.NewLine)) {
|
|
535
547
|
if (key == null) {
|
|
536
548
|
key = this.tokenizer.token.value;
|
|
537
549
|
} else if (eq == null) {
|
|
538
550
|
eq = "=";
|
|
539
551
|
} else {
|
|
540
|
-
const [hookType, value] = this._hook({});
|
|
552
|
+
const [hookType, value, hookI] = this.tokenizer._hook({});
|
|
553
|
+
const rawVal = Reflect.get(data[Keys.Raw], value);
|
|
554
|
+
const isFn = typeof rawVal === "function";
|
|
541
555
|
if (hookType === "dynamic") {
|
|
542
|
-
const valueIsMapKey = Reflect.has(
|
|
543
|
-
const fn = valueIsMapKey ? value : new Function("data", `let v;with(data){v=${value}};return v;`).bind(void 0,
|
|
544
|
-
this.onePropParsed(_node, key, fn, valueIsMapKey,
|
|
556
|
+
const valueIsMapKey = Reflect.has(data[Keys.Raw], value);
|
|
557
|
+
const fn = isFn ? rawVal : valueIsMapKey ? value : new Function("data", `let v;with(data){v=${value}};return v;`).bind(void 0, data);
|
|
558
|
+
this.onePropParsed(data, _node, key, fn, valueIsMapKey, isFn, hookI);
|
|
545
559
|
} else if (hookType === "static") {
|
|
546
|
-
this.onePropParsed(_node, key, value, false,
|
|
560
|
+
this.onePropParsed(data, _node, key, value, false, isFn, hookI);
|
|
547
561
|
} else {
|
|
548
|
-
this.onePropParsed(_node, key, value, false,
|
|
562
|
+
this.onePropParsed(data, _node, key, value, false, isFn, hookI);
|
|
549
563
|
}
|
|
550
564
|
key = null;
|
|
551
565
|
eq = null;
|
|
@@ -567,7 +581,7 @@ class Interpreter {
|
|
|
567
581
|
nextSib(node) {
|
|
568
582
|
return node.nextSibling;
|
|
569
583
|
}
|
|
570
|
-
|
|
584
|
+
firstChild(node) {
|
|
571
585
|
return node.firstChild;
|
|
572
586
|
}
|
|
573
587
|
_createAnchor() {
|
|
@@ -611,28 +625,35 @@ class Interpreter {
|
|
|
611
625
|
setProp(node, key, value, hookI) {
|
|
612
626
|
node.props[key] = value;
|
|
613
627
|
}
|
|
614
|
-
init(fragments) {
|
|
615
|
-
if (typeof fragments === "string") {
|
|
616
|
-
this.tokenizer.setCode(fragments);
|
|
617
|
-
} else {
|
|
618
|
-
let code = "";
|
|
619
|
-
for (let i = 0; i < fragments.length - 1; i++) {
|
|
620
|
-
const fragment = fragments[i];
|
|
621
|
-
code += fragment + `${this.HookId}${i}`;
|
|
622
|
-
}
|
|
623
|
-
this.tokenizer.setCode(code + fragments[fragments.length - 1]);
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
628
|
}
|
|
627
629
|
|
|
630
|
+
var __defProp = Object.defineProperty;
|
|
631
|
+
var __defProps = Object.defineProperties;
|
|
632
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
633
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
634
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
635
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
636
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
637
|
+
var __spreadValues = (a, b) => {
|
|
638
|
+
for (var prop in b || (b = {}))
|
|
639
|
+
if (__hasOwnProp.call(b, prop))
|
|
640
|
+
__defNormalProp(a, prop, b[prop]);
|
|
641
|
+
if (__getOwnPropSymbols)
|
|
642
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
643
|
+
if (__propIsEnum.call(b, prop))
|
|
644
|
+
__defNormalProp(a, prop, b[prop]);
|
|
645
|
+
}
|
|
646
|
+
return a;
|
|
647
|
+
};
|
|
648
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
628
649
|
const _Tokenizer = class _Tokenizer {
|
|
629
|
-
constructor() {
|
|
650
|
+
constructor(hook, isSubToken) {
|
|
651
|
+
this.hook = hook;
|
|
652
|
+
this.isSubToken = isSubToken;
|
|
630
653
|
/** 缩进大小 默认 2 */
|
|
631
654
|
this.TabSize = 2;
|
|
632
655
|
/** 缩进字符 */
|
|
633
656
|
this.Tab = Array.from({ length: this.TabSize }, () => " ").join("");
|
|
634
|
-
/** 匹配标识符 */
|
|
635
|
-
this.IdExp = /[\d\w\/]/;
|
|
636
657
|
/** 回车后需要判断缩进 */
|
|
637
658
|
this.needIndent = false;
|
|
638
659
|
/** 用于跳过第一个节点前的空白字符串,以及生成基础缩进 */
|
|
@@ -641,6 +662,7 @@ const _Tokenizer = class _Tokenizer {
|
|
|
641
662
|
this.dentStack = [0];
|
|
642
663
|
/** 当前字符 index */
|
|
643
664
|
this.i = 0;
|
|
665
|
+
// TODO: 生产环境不需要这个,导致不必要的内存占用
|
|
644
666
|
this.handledTokens = [];
|
|
645
667
|
/**
|
|
646
668
|
* 有些标识符能产生多个 token
|
|
@@ -651,6 +673,31 @@ const _Tokenizer = class _Tokenizer {
|
|
|
651
673
|
* parent2 <- 产生两个 dedent
|
|
652
674
|
*/
|
|
653
675
|
this.waitingTokens = new Queue();
|
|
676
|
+
/** 模板字符串动态节点的占位符 */
|
|
677
|
+
this.HookId = "_h_o_o_k_";
|
|
678
|
+
/** 模板字符串动态节点索引 */
|
|
679
|
+
this.hookI = 0;
|
|
680
|
+
this._hook = (props) => {
|
|
681
|
+
const value = this.token.value;
|
|
682
|
+
const isDynamicHook = this.token.type & TokenType.InsertionExp;
|
|
683
|
+
const isStaticHook = typeof value === "string" && value.indexOf(this.HookId) === 0;
|
|
684
|
+
const hookType = isDynamicHook ? "dynamic" : isStaticHook ? "static" : void 0;
|
|
685
|
+
if (this.hook && isStaticHook) {
|
|
686
|
+
const hookI = Number(value.slice(this.HookId.length));
|
|
687
|
+
const res = this.hook(__spreadProps(__spreadValues({}, props), {
|
|
688
|
+
HookId: this.HookId,
|
|
689
|
+
i: hookI
|
|
690
|
+
}));
|
|
691
|
+
return [hookType, res, hookI];
|
|
692
|
+
} else if (isDynamicHook) {
|
|
693
|
+
return [hookType, value];
|
|
694
|
+
}
|
|
695
|
+
return [hookType, value];
|
|
696
|
+
};
|
|
697
|
+
if (isSubToken) {
|
|
698
|
+
this.setToken(TokenType.Indent, "");
|
|
699
|
+
this.isFirstToken = true;
|
|
700
|
+
}
|
|
654
701
|
}
|
|
655
702
|
consume() {
|
|
656
703
|
const token = this.token;
|
|
@@ -764,7 +811,7 @@ ${_Tokenizer.EofId}`;
|
|
|
764
811
|
}
|
|
765
812
|
testId(value) {
|
|
766
813
|
if (typeof value !== "string") return false;
|
|
767
|
-
return
|
|
814
|
+
return _Tokenizer.IdExp.test(value);
|
|
768
815
|
}
|
|
769
816
|
nextToken() {
|
|
770
817
|
try {
|
|
@@ -997,13 +1044,25 @@ ${_Tokenizer.EofId}`;
|
|
|
997
1044
|
const yes = this.dentStack.length === 1;
|
|
998
1045
|
if (yes) {
|
|
999
1046
|
if (!this.token) {
|
|
1000
|
-
this.
|
|
1047
|
+
if (this.isSubToken) {
|
|
1048
|
+
this.setToken(TokenType.Dedent, "");
|
|
1049
|
+
} else {
|
|
1050
|
+
this.setToken(TokenType.Identifier, _Tokenizer.EofId);
|
|
1051
|
+
}
|
|
1001
1052
|
} else {
|
|
1002
|
-
this.
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1053
|
+
if (this.isSubToken) {
|
|
1054
|
+
this.waitingTokens.push({
|
|
1055
|
+
type: TokenType.Dedent,
|
|
1056
|
+
typeName: TokenType[TokenType.Dedent],
|
|
1057
|
+
value: ""
|
|
1058
|
+
});
|
|
1059
|
+
} else {
|
|
1060
|
+
this.waitingTokens.push({
|
|
1061
|
+
type: TokenType.Identifier,
|
|
1062
|
+
typeName: TokenType[TokenType.Identifier],
|
|
1063
|
+
value: _Tokenizer.EofId
|
|
1064
|
+
});
|
|
1065
|
+
}
|
|
1007
1066
|
}
|
|
1008
1067
|
}
|
|
1009
1068
|
return yes;
|
|
@@ -1019,6 +1078,10 @@ ${_Tokenizer.EofId}`;
|
|
|
1019
1078
|
value += nextC;
|
|
1020
1079
|
this.next();
|
|
1021
1080
|
}
|
|
1081
|
+
if (value === _Tokenizer.EofId && this.isSubToken) {
|
|
1082
|
+
this.setToken(TokenType.Dedent, "");
|
|
1083
|
+
return;
|
|
1084
|
+
}
|
|
1022
1085
|
let realValue = value === "null" ? null : value === "undefined" ? void 0 : value === "false" ? false : value === "true" ? true : value;
|
|
1023
1086
|
this.setToken(TokenType.Identifier, realValue);
|
|
1024
1087
|
}
|
|
@@ -1058,52 +1121,50 @@ ${_Tokenizer.EofId}`;
|
|
|
1058
1121
|
eof() {
|
|
1059
1122
|
this.setToken(TokenType.Eof, "End Of File");
|
|
1060
1123
|
}
|
|
1124
|
+
init(fragments) {
|
|
1125
|
+
if (typeof fragments === "string") {
|
|
1126
|
+
this.setCode(fragments);
|
|
1127
|
+
} else {
|
|
1128
|
+
let code = "";
|
|
1129
|
+
for (let i = 0; i < fragments.length - 1; i++) {
|
|
1130
|
+
const fragment = fragments[i];
|
|
1131
|
+
code += fragment + `${this.HookId}${i}`;
|
|
1132
|
+
}
|
|
1133
|
+
this.setCode(code + fragments[fragments.length - 1]);
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1061
1136
|
};
|
|
1137
|
+
/** 匹配标识符 */
|
|
1138
|
+
_Tokenizer.IdExp = /[\d\w\/]/;
|
|
1062
1139
|
/** Eof 标识符的值 */
|
|
1063
1140
|
_Tokenizer.EofId = `__EOF__${Date.now()}`;
|
|
1141
|
+
_Tokenizer.DedentId = `__DEDENT__${Date.now()}`;
|
|
1064
1142
|
let Tokenizer = _Tokenizer;
|
|
1065
1143
|
|
|
1066
|
-
var __defProp = Object.defineProperty;
|
|
1067
|
-
var __defProps = Object.defineProperties;
|
|
1068
|
-
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
1069
|
-
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
1070
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
1071
|
-
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
1072
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1073
|
-
var __spreadValues = (a, b) => {
|
|
1074
|
-
for (var prop in b || (b = {}))
|
|
1075
|
-
if (__hasOwnProp.call(b, prop))
|
|
1076
|
-
__defNormalProp(a, prop, b[prop]);
|
|
1077
|
-
if (__getOwnPropSymbols)
|
|
1078
|
-
for (var prop of __getOwnPropSymbols(b)) {
|
|
1079
|
-
if (__propIsEnum.call(b, prop))
|
|
1080
|
-
__defNormalProp(a, prop, b[prop]);
|
|
1081
|
-
}
|
|
1082
|
-
return a;
|
|
1083
|
-
};
|
|
1084
|
-
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
1085
1144
|
function bobe(fragments, ...values) {
|
|
1086
|
-
const ui = function ui2(
|
|
1087
|
-
const tokenizer = new Tokenizer()
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
return values[i];
|
|
1093
|
-
},
|
|
1094
|
-
setProp(node, key, value, hookI) {
|
|
1095
|
-
node.props[key] = value;
|
|
1096
|
-
}
|
|
1097
|
-
}));
|
|
1098
|
-
cmp.init(Array.from(fragments));
|
|
1099
|
-
return cmp.program(root, before);
|
|
1145
|
+
const ui = function ui2(isSub) {
|
|
1146
|
+
const tokenizer = new Tokenizer(({ i }) => {
|
|
1147
|
+
return values[i];
|
|
1148
|
+
}, isSub);
|
|
1149
|
+
tokenizer.init(Array.from(fragments));
|
|
1150
|
+
return tokenizer;
|
|
1100
1151
|
};
|
|
1101
1152
|
return ui;
|
|
1102
1153
|
}
|
|
1103
1154
|
function customRender(option) {
|
|
1104
1155
|
return function render(Ctor, root) {
|
|
1105
1156
|
const store = Ctor.new();
|
|
1106
|
-
|
|
1157
|
+
const tokenizer = store["ui"](false);
|
|
1158
|
+
const terp = new Interpreter(tokenizer);
|
|
1159
|
+
terp.config(option);
|
|
1160
|
+
const componentNode = {
|
|
1161
|
+
__logicType: FakeType.Component,
|
|
1162
|
+
realParent: root,
|
|
1163
|
+
data: store,
|
|
1164
|
+
tokenizer
|
|
1165
|
+
};
|
|
1166
|
+
terp.program(root, componentNode);
|
|
1167
|
+
return [componentNode, store];
|
|
1107
1168
|
};
|
|
1108
1169
|
}
|
|
1109
1170
|
|