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