bobe 0.0.10 → 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 CHANGED
@@ -22,35 +22,116 @@ var LogicType = /* @__PURE__ */ ((LogicType2) => {
22
22
  LogicType2[LogicType2["Component"] = 16] = "Component";
23
23
  LogicType2[LogicType2["Fragment"] = 32] = "Fragment";
24
24
  LogicType2[LogicType2["Root"] = 64] = "Root";
25
+ LogicType2[LogicType2["Real"] = 128] = "Real";
25
26
  return LogicType2;
26
27
  })(LogicType || {});
28
+ const Logical = 1 /* If */ | 2 /* ElseIf */ | 4 /* Else */ | 8 /* For */;
29
+ var NodeType = /* @__PURE__ */ ((NodeType2) => {
30
+ NodeType2[NodeType2["Logic"] = Logical] = "Logic";
31
+ NodeType2[NodeType2["Real"] = 128 /* Real */] = "Real";
32
+ NodeType2[NodeType2["Component"] = 16 /* Component */] = "Component";
33
+ return NodeType2;
34
+ })(NodeType || {});
27
35
  var TerpEvt = /* @__PURE__ */ ((TerpEvt2) => {
28
36
  TerpEvt2["AllAttrGot"] = "all-attr-got";
29
37
  TerpEvt2["HandledComponentNode"] = "handled-component-node";
30
38
  return TerpEvt2;
31
39
  })(TerpEvt || {});
40
+ const IsAnchor = /* @__PURE__ */ Symbol("is-anchor");
32
41
 
33
- var __defProp = Object.defineProperty;
34
- var __defProps = Object.defineProperties;
35
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
36
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
37
- var __hasOwnProp = Object.prototype.hasOwnProperty;
38
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
39
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
40
- var __spreadValues = (a, b) => {
42
+ class TypedStack {
43
+ constructor() {
44
+ this.top = null;
45
+ // 存储每种类型最近一次出现的包装单元引用
46
+ // 使用 Record 来动态支持不同的类型标签
47
+ this.lastNodes = {};
48
+ this.length = 0;
49
+ }
50
+ /**
51
+ * @param rawNode 原始节点数据
52
+ * @param type 节点类型
53
+ */
54
+ push(rawNode, type) {
55
+ var _a;
56
+ const newNode = {
57
+ data: rawNode,
58
+ type,
59
+ prev: this.top,
60
+ prevSameType: (_a = this.lastNodes[type]) != null ? _a : null
61
+ };
62
+ this.top = newNode;
63
+ this.length++;
64
+ this.lastNodes[type] = newNode;
65
+ }
66
+ /**
67
+ * 出栈操作
68
+ * @returns 原始节点数据或 null
69
+ */
70
+ pop() {
71
+ if (!this.top) return null;
72
+ const popped = this.top;
73
+ this.lastNodes[popped.type] = popped.prevSameType;
74
+ this.top = popped.prev;
75
+ this.length--;
76
+ return popped.data;
77
+ }
78
+ /**
79
+ * O(1) 获取栈顶节点的前一个同类型节点
80
+ */
81
+ getPrevSameType() {
82
+ if (!this.top || !this.top.prevSameType) {
83
+ return null;
84
+ }
85
+ return this.top.prevSameType.data;
86
+ }
87
+ findPrevSameType(cb) {
88
+ if (!this.top) {
89
+ return null;
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;
99
+ }
100
+ /**
101
+ * 获取当前栈顶的类型
102
+ */
103
+ get peekType() {
104
+ return this.top ? this.top.type : null;
105
+ }
106
+ /**
107
+ * 获取栈顶元素
108
+ */
109
+ peek() {
110
+ return this.top.data;
111
+ }
112
+ }
113
+
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) => {
41
122
  for (var prop in b || (b = {}))
42
- if (__hasOwnProp.call(b, prop))
43
- __defNormalProp(a, prop, b[prop]);
44
- if (__getOwnPropSymbols)
45
- for (var prop of __getOwnPropSymbols(b)) {
46
- if (__propIsEnum.call(b, prop))
47
- __defNormalProp(a, prop, b[prop]);
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]);
48
129
  }
49
130
  return a;
50
131
  };
51
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
132
+ var __spreadProps$1 = (a, b) => __defProps$1(a, __getOwnPropDescs$1(b));
52
133
  const tap = new bobeShared.BaseEvent();
53
- class Terp {
134
+ class Interpreter {
54
135
  constructor(tokenizer) {
55
136
  this.tokenizer = tokenizer;
56
137
  /** 模板字符串动态节点的占位符 */
@@ -59,7 +140,6 @@ class Terp {
59
140
  this.data = {};
60
141
  /** 模板字符串动态节点索引 */
61
142
  this.hookI = 0;
62
- this.stack = [];
63
143
  this._hook = (props) => {
64
144
  const value = this.tokenizer.token.value;
65
145
  const isDynamicHook = this.tokenizer.token.type & TokenType.InsertionExp;
@@ -67,7 +147,7 @@ class Terp {
67
147
  const hookType = isDynamicHook ? "dynamic" : isStaticHook ? "static" : void 0;
68
148
  if (this.hook && isStaticHook) {
69
149
  const hookI = Number(value.slice(this.HookId.length));
70
- const res = this.hook(__spreadProps(__spreadValues({}, props), {
150
+ const res = this.hook(__spreadProps$1(__spreadValues$1({}, props), {
71
151
  HookId: this.HookId,
72
152
  i: hookI
73
153
  }));
@@ -79,123 +159,115 @@ class Terp {
79
159
  return [hookType, value];
80
160
  };
81
161
  }
82
- // /** program 要挂载的父节点位置 */
83
- // root: any;
84
- // /** program 挂载的前置节点 */
85
- // anchor: any;
86
- program() {
87
- const root = {
162
+ isLogicNode(node) {
163
+ return node && node.__logicType & Logical;
164
+ }
165
+ program(root, before) {
166
+ var _a;
167
+ const componentNode = {
88
168
  __logicType: LogicType.Component,
89
- store: this.data,
90
- realList: [],
91
- directList: []
169
+ realParent: root,
170
+ store: new aoye.Store()
92
171
  };
93
172
  this.tokenizer.consume();
94
- let current;
95
- let prevSibling;
96
- this.stack = [{ node: root, prevSibling }];
173
+ const stack = new TypedStack();
174
+ stack.push({ node: root, prev: null }, NodeType.Real);
175
+ const ctx = {
176
+ realParent: root,
177
+ prevSibling: before,
178
+ current: null,
179
+ stack,
180
+ before
181
+ };
182
+ const rootPulling = aoye.getPulling();
97
183
  while (1) {
98
184
  if (this.tokenizer.isEof()) {
99
- this.handleInsert(root, current, root.realList[root.realList.length - 1]);
185
+ if (!ctx.prevSibling) ctx.prevSibling = before;
186
+ this.handleInsert(root, ctx.current, ctx.prevSibling, componentNode);
100
187
  break;
101
188
  }
102
189
  const token = this.tokenizer.token;
103
190
  if (token.type & TokenType.Indent) {
104
191
  this.tokenizer.consume();
105
- this.stack.push({
106
- prevSibling,
107
- node: current
108
- });
109
- prevSibling = null;
110
- current = this.declaration();
192
+ const isLogicNode = this.isLogicNode(ctx.current);
193
+ stack.push(
194
+ {
195
+ node: ctx.current,
196
+ prev: ctx.prevSibling
197
+ },
198
+ ctx.current.__logicType ? isLogicNode ? NodeType.Logic : NodeType.Component : NodeType.Real
199
+ );
200
+ if (ctx.current.__logicType) {
201
+ if (isLogicNode) {
202
+ aoye.setPulling(ctx.current.effect.ins);
203
+ }
204
+ } else {
205
+ ctx.realParent = ctx.current;
206
+ ctx.prevSibling = null;
207
+ }
208
+ ctx.current = this.declaration(ctx);
111
209
  continue;
112
210
  }
113
- if (current) {
114
- if (this.stack.length > 1) {
115
- const parent = this.stack[this.stack.length - 1].node;
116
- this.handleInsert(parent, current, prevSibling);
117
- } else {
118
- this.handleInsert(root, current, prevSibling);
211
+ if (ctx.current) {
212
+ if (stack.length === 1 && !ctx.prevSibling) {
213
+ ctx.prevSibling = before;
119
214
  }
215
+ this.handleInsert(ctx.realParent, ctx.current, ctx.prevSibling);
120
216
  }
121
217
  if (this.tokenizer.token.type & TokenType.Dedent) {
122
218
  this.tokenizer.consume();
123
- const { node: parent, prevSibling: prevParent } = this.stack.pop();
124
- prevSibling = prevParent;
125
- current = parent;
219
+ const { node: parent, prev } = stack.peek();
220
+ if (!parent.__logicType) {
221
+ const prevSameType = stack.getPrevSameType();
222
+ ctx.realParent = prevSameType == null ? void 0 : prevSameType.node;
223
+ } else {
224
+ if (this.isLogicNode(parent)) {
225
+ const parentLogic = (_a = stack.getPrevSameType()) == null ? void 0 : _a.node;
226
+ if (parentLogic) {
227
+ aoye.setPulling(parentLogic.effect.ins);
228
+ } else {
229
+ aoye.setPulling(rootPulling);
230
+ }
231
+ }
232
+ }
233
+ stack.pop();
234
+ ctx.prevSibling = prev;
235
+ ctx.current = parent;
126
236
  } else {
127
- prevSibling = current;
128
- current = this.declaration();
237
+ ctx.prevSibling = ctx.current || ctx.prevSibling;
238
+ ctx.current = this.declaration(ctx);
129
239
  }
130
240
  }
131
- return root;
241
+ return componentNode;
242
+ }
243
+ insertAfterAnchor(ctx) {
244
+ const { realParent, prevSibling, stack, before } = ctx;
245
+ const afterAnchor = this.createAnchor();
246
+ ctx.prevSibling = stack.length === 1 && !prevSibling ? before : prevSibling;
247
+ this.handleInsert(realParent, afterAnchor, prevSibling);
248
+ return afterAnchor;
132
249
  }
133
250
  /** 处理
134
- * 是逻辑 是普通
135
- * 父节点 将子节点们插入到 realList 调用 insert 方法挨个插入子节点
136
- * 子节点 将其下 realList 插入到父节点 将本节点插入父节点
251
+ * 是逻辑 是普通
252
+ * 父节点 将子节点加入 directList 调用 insert 方法挨个插入子节点
253
+ * 子节点 仅插入到父逻辑节点 将本节点插入父节点
254
+ * 理论上父节点不能是一个 逻辑节点,遇到if 时 Terp 会重新执行 program 这种情况下,会指定 root 为真实 dom
137
255
  */
138
- handleInsert(parent, child, prevSibling) {
139
- let insertFn = this.insert.bind(this);
140
- if (parent.__logicType) {
141
- insertFn = (parent2, child2, prevSibling2) => {
142
- parent2.realList.splice(parent2.realList.indexOf(prevSibling2) + 1, 0, child2);
143
- };
144
- }
145
- if (child.__logicType) {
146
- const realList = child.realList;
147
- for (let i = realList.length; i--; ) {
148
- const item = realList[i];
149
- insertFn(parent, item, prevSibling);
256
+ handleInsert(parent, child, prev, parentComponent) {
257
+ if (!child.__logicType) {
258
+ if (!prev || !prev.__logicType) {
259
+ this.insertAfter(parent, child, prev);
260
+ } else {
261
+ const before = prev.realAfter;
262
+ this.insertAfter(parent, child, before);
150
263
  }
151
264
  } else {
152
- insertFn(parent, child, prevSibling);
153
- }
154
- }
155
- /**
156
- * @deprecated
157
- * 节点列表:
158
- * 可以是一个节点,也可以跟随更多节点
159
- * <nodeList> ::= <node> <nodeList> <EOF|Dedent>
160
- * |
161
- */
162
- nodeList(parent) {
163
- let _node;
164
- let prevSibling;
165
- let prevItem;
166
- while (1) {
167
- if (this.tokenizer.isEof()) {
168
- return;
169
- }
170
- if (this.tokenizer.token.type & TokenType.Dedent) {
171
- this.tokenizer.consume();
172
- return;
173
- }
174
- _node = this.node();
175
- const insert = parent.__logicType ? this.defaultInsert : this.insert.bind(this);
176
- parent.__logicType ? this.defaultRemove : this.remove.bind(this);
177
- if (!_node.__logicType) {
178
- const realPrev = this.getPrevRealSibling(prevSibling);
179
- const currItem = insert(parent, _node, realPrev, prevItem);
180
- prevItem = currItem;
181
- prevSibling = _node;
182
- continue;
183
- }
184
- if (prevSibling) {
185
- _node.anchor = prevSibling;
186
- } else if (parent.__logicType) {
187
- _node.anchor = parent;
188
- } else ;
189
- if (_node.child && _node.condition()) {
190
- let item = _node.child;
191
- while (item != null) {
192
- const { value: child } = item;
193
- const realPrev = this.getPrevRealSibling(prevSibling);
194
- const currItem = insert(parent, child, realPrev, prevItem);
195
- item = item.next;
196
- prevItem = currItem;
197
- prevSibling = child;
198
- }
265
+ const childCmp = child;
266
+ childCmp.realParent = parent;
267
+ if (prev.__logicType) {
268
+ childCmp.realBefore = prev.realAfter;
269
+ } else {
270
+ childCmp.realBefore = prev;
199
271
  }
200
272
  }
201
273
  }
@@ -212,33 +284,20 @@ class Terp {
212
284
  point = point.anchor;
213
285
  }
214
286
  }
215
- /**
216
- * 单个节点:
217
- * 由声明部分和(可选的)子节点块组成
218
- * <node> ::= <declaration> <childrenBlockOpt>
219
- * */
220
- node() {
221
- const _declaration = this.declaration();
222
- if (_declaration.__logicType & LogicType.If && !_declaration.condition()) {
223
- return _declaration;
224
- }
225
- this.childrenBlockOpt(_declaration);
226
- return _declaration;
227
- }
228
287
  /**
229
288
  * 声明部分:
230
289
  * 包含首行定义和(可选的)多行属性扩展
231
290
  * <declaration> ::= <tagName=token> <headerLine> <extensionLines>
232
291
  * */
233
- declaration() {
292
+ declaration(ctx) {
234
293
  const [hookType, value] = this._hook({});
235
294
  let _node;
236
295
  if (value === "if") {
237
- return this.ifDeclaration();
296
+ return this.ifDeclaration(ctx);
238
297
  } else if (hookType) {
239
298
  if (hookType === "static") {
240
299
  if (typeof value === "function" && value.prototype instanceof aoye.Store) {
241
- _node = this.componentDeclaration(value);
300
+ _node = this.componentDeclaration(value, ctx);
242
301
  } else if (typeof value === "function") {
243
302
  _node = this.fragmentDeclaration(value);
244
303
  } else {
@@ -265,8 +324,7 @@ class Terp {
265
324
  fragmentDeclaration(renderFragment) {
266
325
  const fragmentNode = {
267
326
  __logicType: LogicType.Fragment,
268
- directList: [],
269
- realList: []
327
+ realParent: null
270
328
  };
271
329
  renderFragment.call(this.data, this.opt, { data: this.data, root: "", anchor: "" });
272
330
  return fragmentNode;
@@ -294,7 +352,7 @@ class Terp {
294
352
  this.setProp(node, key, value, hookI);
295
353
  }
296
354
  }
297
- componentDeclaration(Component) {
355
+ componentDeclaration(Component, ctx) {
298
356
  const child = Component.new();
299
357
  const prevOnePropParsed = this.onePropParsed;
300
358
  this.onePropParsed = (node, key, value, valueIsMapKey, hookI) => {
@@ -309,36 +367,66 @@ class Terp {
309
367
  child[aoye.Keys.Raw][key] = value;
310
368
  }
311
369
  };
370
+ const afterAnchor = this.insertAfterAnchor(ctx);
312
371
  tap.once(TerpEvt.AllAttrGot, () => {
372
+ const parent = ctx.realParent;
373
+ const prev = ctx.prevSibling;
313
374
  this.onePropParsed = prevOnePropParsed;
314
- const root = child["ui"](this.opt, { data: child });
315
- tap.emit(TerpEvt.HandledComponentNode, root);
375
+ const componentNode = child["ui"](this.opt, { data: child }, parent, prev);
376
+ componentNode.realAfter = afterAnchor;
377
+ tap.emit(TerpEvt.HandledComponentNode, componentNode);
316
378
  });
317
379
  return { __logicType: LogicType.Component };
318
380
  }
319
- ifDeclaration() {
381
+ ifDeclaration(ctx) {
320
382
  this.tokenizer.consume();
321
- const [isHook, value] = this._hook({});
383
+ const [hookType, value] = this._hook({});
322
384
  const ifNode = {
323
385
  __logicType: LogicType.If,
324
- condition: value,
325
- directList: [],
326
- realList: [],
327
386
  snapshot: this.tokenizer.snapshot(),
387
+ condition: null,
388
+ realParent: null,
328
389
  isFirstRender: true,
329
- watcher: null,
330
- anchor: null
390
+ effect: null
331
391
  };
332
- ifNode.watcher = aoye.effect(
392
+ const valueIsMapKey = Reflect.has(this.data[aoye.Keys.Raw], value);
393
+ let signal;
394
+ if (valueIsMapKey) {
395
+ aoye.runWithPulling(() => this.data[value], null);
396
+ const { cells } = this.data[aoye.Keys.Meta];
397
+ signal = cells.get(value);
398
+ } else {
399
+ const fn = new Function("data", `let v;with(data){v=${value}};return v;`).bind(void 0, this.data);
400
+ signal = aoye.$(fn);
401
+ }
402
+ ifNode.condition = signal;
403
+ ifNode.realAfter = this.insertAfterAnchor(ctx);
404
+ ifNode.effect = aoye.effect(
333
405
  ({ val }) => {
334
406
  if (val) {
335
- this.tokenizer.consume();
336
- this.tokenizer.consume();
407
+ if (ifNode.isFirstRender) {
408
+ this.tokenizer.consume();
409
+ this.tokenizer.consume();
410
+ } else {
411
+ this.tokenizer.resume(ifNode.snapshot);
412
+ this.program(ifNode.realParent, ifNode.realBefore);
413
+ }
337
414
  } else {
338
- this.tokenizer.skip();
415
+ if (ifNode.isFirstRender) {
416
+ this.tokenizer.skip();
417
+ } else {
418
+ const { realBefore, realAfter, realParent } = ifNode;
419
+ let point = this.nextSib(realBefore);
420
+ while (point !== realAfter) {
421
+ const next = this.nextSib(point);
422
+ this.remove(point, realParent, realBefore);
423
+ point = next;
424
+ }
425
+ }
339
426
  }
427
+ ifNode.isFirstRender = false;
340
428
  },
341
- [value]
429
+ [signal]
342
430
  );
343
431
  return ifNode;
344
432
  }
@@ -402,19 +490,6 @@ class Terp {
402
490
  this.tokenizer.consume();
403
491
  }
404
492
  }
405
- /** 子节点块:
406
- * 必须被缩进包裹
407
- * <childrenBlockOpt> ::= INDENT <nodeList>
408
- * | ε /* 空(表示叶子节点,没有孩子)
409
- * */
410
- childrenBlockOpt(parent) {
411
- if (!(this.tokenizer.token.type & TokenType.Indent)) {
412
- return [];
413
- }
414
- this.tokenizer.consume();
415
- const list = this.nodeList(parent);
416
- return list;
417
- }
418
493
  config(opt) {
419
494
  Object.assign(this, opt);
420
495
  this.opt = opt;
@@ -422,28 +497,47 @@ class Terp {
422
497
  createNode(name) {
423
498
  return {
424
499
  name,
425
- props: {}
500
+ props: {},
501
+ nextSibling: null
426
502
  };
427
503
  }
428
- insert(parent, node, prevSibling, prevItem) {
429
- return this.defaultInsert(parent, node, prevSibling, prevItem);
504
+ nextSib(node) {
505
+ return node.nextSibling;
430
506
  }
431
- defaultInsert(parent, node, prevSibling, prevItem) {
432
- if (prevSibling) {
433
- const children = parent.children;
434
- const insertI = children.findIndex((item) => item === prevSibling);
435
- children.splice(insertI + 1, 0, node);
507
+ _createAnchor() {
508
+ const anchor = this.createAnchor();
509
+ anchor[IsAnchor] = true;
510
+ return anchor;
511
+ }
512
+ createAnchor() {
513
+ return {
514
+ name: "anchor",
515
+ nextSibling: null
516
+ };
517
+ }
518
+ insertAfter(parent, node, prev) {
519
+ return this.defaultInsert(parent, node, prev);
520
+ }
521
+ defaultInsert(parent, node, prev) {
522
+ if (prev) {
523
+ const next = prev.nextSibling;
524
+ prev.nextSibling = node;
525
+ node.nextSibling = next;
436
526
  } else {
437
- parent.children = [node];
527
+ parent.firstChild = node;
438
528
  }
439
529
  }
440
- remove(parent, node, prevSibling, prevItem) {
441
- return this.defaultRemove(parent, node, prevSibling, prevItem);
530
+ remove(node, parent, prev) {
531
+ return this.defaultRemove(node, parent, prev);
442
532
  }
443
533
  // TODO: 默认改成 prevItem
444
- defaultRemove(parent, node, prevSibling, prevItem) {
445
- if (parent.children) {
446
- parent.children.splice(parent.children.indexOf(node), 1);
534
+ defaultRemove(node, parent, prevSibling) {
535
+ const next = node.nextSibling;
536
+ if (prevSibling) {
537
+ prevSibling.nextSibling = next;
538
+ }
539
+ if (parent.firstChild === node) {
540
+ parent.firstChild = next;
447
541
  }
448
542
  }
449
543
  setProp(node, key, value, hookI) {
@@ -463,5 +557,494 @@ class Terp {
463
557
  }
464
558
  }
465
559
 
466
- exports.Terp = Terp;
560
+ const _Tokenizer = class _Tokenizer {
561
+ constructor() {
562
+ /** 缩进大小 默认 2 */
563
+ this.TabSize = 2;
564
+ /** 缩进字符 */
565
+ this.Tab = Array.from({ length: this.TabSize }, () => " ").join("");
566
+ /** 匹配标识符 */
567
+ this.IdExp = /[\d\w\/]/;
568
+ /** 回车后需要判断缩进 */
569
+ this.needIndent = false;
570
+ /** 用于跳过第一个节点前的空白字符串,以及生成基础缩进 */
571
+ this.isFirstToken = true;
572
+ /** 记录历史缩进的长度,相对于行首 */
573
+ this.dentStack = [0];
574
+ /** 当前字符 index */
575
+ this.i = 0;
576
+ this.handledTokens = [];
577
+ /**
578
+ * 有些标识符能产生多个 token
579
+ * 例如 dedent
580
+ * parent1
581
+ * child
582
+ * subChild
583
+ * parent2 <- 产生两个 dedent
584
+ */
585
+ this.waitingTokens = new bobeShared.Queue();
586
+ }
587
+ consume() {
588
+ const token = this.token;
589
+ this.nextToken();
590
+ return token;
591
+ }
592
+ // /** 恢复至某一个现场,进行 token 重算 */
593
+ resume(_snapshot) {
594
+ this.token = void 0;
595
+ this.needIndent = false;
596
+ this.isFirstToken = true;
597
+ this.dentStack = [0];
598
+ Object.assign(this, _snapshot);
599
+ }
600
+ snapshot() {
601
+ return {
602
+ i: this.i,
603
+ waitingTokens: this.waitingTokens.clone()
604
+ };
605
+ }
606
+ skip() {
607
+ const logicDentLen = this.dentStack[this.dentStack.length - 1];
608
+ let needIndent = false;
609
+ let skipFragment = ``;
610
+ this.token = void 0;
611
+ while (1) {
612
+ const char = this.char;
613
+ if (char === "\n") {
614
+ needIndent = true;
615
+ skipFragment += char;
616
+ this.next();
617
+ continue;
618
+ }
619
+ if (!needIndent) {
620
+ skipFragment += char;
621
+ this.next();
622
+ continue;
623
+ }
624
+ needIndent = false;
625
+ const { value, isEmptyLine } = this.getDentValue();
626
+ const currLen = value.length;
627
+ if (isEmptyLine) continue;
628
+ if (currLen > logicDentLen) {
629
+ skipFragment += value;
630
+ } else {
631
+ for (let i = this.dentStack.length - 1; i >= 0; i--) {
632
+ const expLen = this.dentStack[i];
633
+ if (currLen === expLen) break;
634
+ if (currLen > expLen) {
635
+ throw SyntaxError(`\u7F29\u8FDB\u9519\u8BEF\uFF0C\u7F29\u8FDB\u957F\u5EA6\u4E0D\u5339\u914D`);
636
+ }
637
+ if (this.shorterThanBaseDentEof()) {
638
+ break;
639
+ }
640
+ this.dentStack.pop();
641
+ if (!this.token) {
642
+ this.setToken(TokenType.Dedent, String(expLen));
643
+ } else {
644
+ this.waitingTokens.push({
645
+ type: TokenType.Dedent,
646
+ typeName: TokenType[TokenType.Dedent],
647
+ value: String(expLen)
648
+ });
649
+ }
650
+ }
651
+ break;
652
+ }
653
+ }
654
+ if (!this.token) {
655
+ this.nextToken();
656
+ }
657
+ return skipFragment;
658
+ }
659
+ setCode(code) {
660
+ this.code = "\n" + code.trimEnd() + `
661
+ ${_Tokenizer.EofId}`;
662
+ }
663
+ tokenize() {
664
+ var _a, _b;
665
+ do {
666
+ this.nextToken();
667
+ console.log("token:", TokenType[(_a = this.token) == null ? void 0 : _a.type], JSON.stringify(((_b = this.token) == null ? void 0 : _b.value) || ""));
668
+ } while (!this.isEof());
669
+ }
670
+ isEof() {
671
+ if (!this.token) return false;
672
+ return this.token.type & TokenType.Identifier && this.token.value === _Tokenizer.EofId;
673
+ }
674
+ get char() {
675
+ return this.code[this.i];
676
+ }
677
+ get prev() {
678
+ return this.code[this.i - 1];
679
+ }
680
+ get after() {
681
+ return this.code[this.i + 1];
682
+ }
683
+ next() {
684
+ const prev = this.code[this.i];
685
+ this.i++;
686
+ const curr = this.code[this.i];
687
+ return [prev, curr];
688
+ }
689
+ setToken(type, value) {
690
+ this.token = {
691
+ type,
692
+ typeName: TokenType[type],
693
+ value
694
+ };
695
+ this.isFirstToken = false;
696
+ }
697
+ testId(value) {
698
+ if (typeof value !== "string") return false;
699
+ return this.IdExp.test(value);
700
+ }
701
+ nextToken() {
702
+ try {
703
+ if (this.isEof()) {
704
+ return this.token;
705
+ }
706
+ this.token = void 0;
707
+ if (this.waitingTokens.len) {
708
+ const item = this.waitingTokens.shift();
709
+ this.setToken(item.type, item.value);
710
+ return this.token;
711
+ }
712
+ outer: while (1) {
713
+ if (this.needIndent) {
714
+ this.dent();
715
+ } else {
716
+ let { char } = this;
717
+ switch (char) {
718
+ case " ":
719
+ case " ":
720
+ break;
721
+ // 找后续所有 newLine
722
+ case "\n":
723
+ this.newLine();
724
+ this.needIndent = true;
725
+ break;
726
+ case "=":
727
+ this.assignment();
728
+ break;
729
+ case "|":
730
+ this.pipe();
731
+ break;
732
+ case "'":
733
+ case '"':
734
+ this.str(char);
735
+ break;
736
+ case "{":
737
+ this.brace();
738
+ break;
739
+ case "$":
740
+ const handled = this.dynamic(char);
741
+ if (handled) break;
742
+ default:
743
+ if (bobeShared.isNum(char)) {
744
+ this.number(char);
745
+ break;
746
+ }
747
+ if (this.testId(char)) {
748
+ this.identifier(char);
749
+ }
750
+ break;
751
+ }
752
+ this.next();
753
+ }
754
+ if (this.token) {
755
+ break;
756
+ }
757
+ }
758
+ return this.token;
759
+ } catch (error) {
760
+ console.error(error);
761
+ } finally {
762
+ this.handledTokens.push(this.token);
763
+ }
764
+ }
765
+ assignment() {
766
+ this.setToken(TokenType.Assign, "=");
767
+ }
768
+ pipe() {
769
+ this.setToken(TokenType.Pipe, "|");
770
+ }
771
+ dynamic(char) {
772
+ let nextC = this.after;
773
+ if (nextC !== "{") {
774
+ return false;
775
+ }
776
+ this.next();
777
+ let value = "${";
778
+ let innerBrace = 0;
779
+ while (1) {
780
+ nextC = this.after;
781
+ value += nextC;
782
+ this.next();
783
+ if (nextC === "{") {
784
+ innerBrace++;
785
+ }
786
+ if (nextC === "}") {
787
+ if (!innerBrace) {
788
+ break;
789
+ }
790
+ innerBrace--;
791
+ }
792
+ }
793
+ this.setToken(TokenType.Identifier, value);
794
+ return true;
795
+ }
796
+ brace() {
797
+ let inComment, inString, count = 0, value = "", backslashCount = 0;
798
+ while (1) {
799
+ const char = this.char;
800
+ const nextChar = this.after;
801
+ if (inComment === "single" && char === "\n") {
802
+ inComment = null;
803
+ } else if (inComment === "multi" && char === "*" && nextChar === "/") {
804
+ inComment = null;
805
+ value += this.next()[0];
806
+ } else if (inString) {
807
+ if (char === inString && backslashCount % 2 === 0) {
808
+ inString = null;
809
+ }
810
+ backslashCount = char === "\\" ? backslashCount + 1 : 0;
811
+ } else {
812
+ if (char === "/" && nextChar === "/") {
813
+ inComment = "single";
814
+ value += this.next()[0];
815
+ } else if (char === "/" && nextChar === "*") {
816
+ inComment = "multi";
817
+ value += this.next()[0];
818
+ } else if (char === "'" || char === '"' || char === "`") {
819
+ inString = char;
820
+ } else if (char === "{") {
821
+ count++;
822
+ } else if (char === "}") {
823
+ count--;
824
+ }
825
+ }
826
+ if (count === 0 && inString == null && inComment == null) {
827
+ this.setToken(TokenType.InsertionExp, value.slice(1));
828
+ return;
829
+ }
830
+ value += this.next()[0];
831
+ }
832
+ }
833
+ newLine() {
834
+ let value = "\n";
835
+ let nextC;
836
+ while (1) {
837
+ nextC = this.after;
838
+ if (nextC !== "\n") {
839
+ break;
840
+ }
841
+ value += nextC;
842
+ this.next();
843
+ }
844
+ if (this.isFirstToken) {
845
+ return;
846
+ }
847
+ this.setToken(TokenType.NewLine, value);
848
+ }
849
+ getDentValue() {
850
+ let value = "";
851
+ let nextC;
852
+ let isEmptyLine = false;
853
+ while (1) {
854
+ const nextChar = this.char;
855
+ switch (nextChar) {
856
+ case " ":
857
+ nextC = this.Tab;
858
+ break;
859
+ case " ":
860
+ nextC = " ";
861
+ break;
862
+ case "\n":
863
+ nextC = "\n";
864
+ break;
865
+ default:
866
+ nextC = "";
867
+ break;
868
+ }
869
+ if (nextC === "\n") {
870
+ isEmptyLine = true;
871
+ break;
872
+ }
873
+ if (!nextC) {
874
+ break;
875
+ }
876
+ value += nextC;
877
+ this.next();
878
+ }
879
+ return {
880
+ value,
881
+ isEmptyLine
882
+ };
883
+ }
884
+ dent() {
885
+ const { value, isEmptyLine } = this.getDentValue();
886
+ if (isEmptyLine) {
887
+ this.needIndent = true;
888
+ return;
889
+ }
890
+ this.needIndent = false;
891
+ if (this.isFirstToken) {
892
+ this.dentStack[0] = value.length;
893
+ return;
894
+ }
895
+ let currLen = value.length;
896
+ const indentHasLen = currLen > 0;
897
+ const prevLen = this.dentStack[this.dentStack.length - 1];
898
+ if (currLen > prevLen) {
899
+ this.dentStack.push(currLen);
900
+ this.setToken(TokenType.Indent, String(currLen));
901
+ return indentHasLen;
902
+ }
903
+ if (currLen < prevLen) {
904
+ for (let i = this.dentStack.length; i--; ) {
905
+ const expLen = this.dentStack[i];
906
+ if (currLen === expLen) break;
907
+ if (currLen > expLen) {
908
+ throw SyntaxError("\u7F29\u8FDB\u5927\u5C0F\u4E0D\u7EDF\u4E00");
909
+ }
910
+ if (this.shorterThanBaseDentEof()) {
911
+ return;
912
+ }
913
+ this.dentStack.pop();
914
+ if (!this.token) {
915
+ this.setToken(TokenType.Dedent, String(expLen));
916
+ } else {
917
+ this.waitingTokens.push({
918
+ type: TokenType.Dedent,
919
+ typeName: TokenType[TokenType.Dedent],
920
+ value: String(expLen)
921
+ });
922
+ }
923
+ }
924
+ return indentHasLen;
925
+ }
926
+ return indentHasLen;
927
+ }
928
+ shorterThanBaseDentEof() {
929
+ const yes = this.dentStack.length === 1;
930
+ if (yes) {
931
+ if (!this.token) {
932
+ this.setToken(TokenType.Identifier, _Tokenizer.EofId);
933
+ } else {
934
+ this.waitingTokens.push({
935
+ type: TokenType.Identifier,
936
+ typeName: TokenType[TokenType.Identifier],
937
+ value: _Tokenizer.EofId
938
+ });
939
+ }
940
+ }
941
+ return yes;
942
+ }
943
+ identifier(char) {
944
+ let value = char;
945
+ let nextC;
946
+ while (1) {
947
+ nextC = this.after;
948
+ if (!this.testId(nextC)) {
949
+ break;
950
+ }
951
+ value += nextC;
952
+ this.next();
953
+ }
954
+ let realValue = value === "null" ? null : value === "undefined" ? void 0 : value === "false" ? false : value === "true" ? true : value;
955
+ this.setToken(TokenType.Identifier, realValue);
956
+ }
957
+ str(char) {
958
+ let value = '"';
959
+ let nextC;
960
+ let continuousBackslashCount = 0;
961
+ while (1) {
962
+ nextC = this.after;
963
+ value += nextC;
964
+ const memoCount = continuousBackslashCount;
965
+ if (nextC === "\\") {
966
+ continuousBackslashCount++;
967
+ } else {
968
+ continuousBackslashCount = 0;
969
+ }
970
+ this.next();
971
+ if (nextC === char && memoCount % 2 === 0) {
972
+ break;
973
+ }
974
+ }
975
+ this.setToken(TokenType.Identifier, JSON.parse(value.slice(0, -1) + '"'));
976
+ }
977
+ number(char) {
978
+ let value = char;
979
+ let nextC;
980
+ while (1) {
981
+ nextC = this.after;
982
+ if (!bobeShared.isNum(nextC)) {
983
+ break;
984
+ }
985
+ value += nextC;
986
+ this.next();
987
+ }
988
+ this.setToken(TokenType.Identifier, Number(value));
989
+ }
990
+ eof() {
991
+ this.setToken(TokenType.Eof, "End Of File");
992
+ }
993
+ };
994
+ /** Eof 标识符的值 */
995
+ _Tokenizer.EofId = `__EOF__${Date.now()}`;
996
+ let Tokenizer = _Tokenizer;
997
+
998
+ var __defProp = Object.defineProperty;
999
+ var __defProps = Object.defineProperties;
1000
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
1001
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
1002
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
1003
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
1004
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1005
+ var __spreadValues = (a, b) => {
1006
+ for (var prop in b || (b = {}))
1007
+ if (__hasOwnProp.call(b, prop))
1008
+ __defNormalProp(a, prop, b[prop]);
1009
+ if (__getOwnPropSymbols)
1010
+ for (var prop of __getOwnPropSymbols(b)) {
1011
+ if (__propIsEnum.call(b, prop))
1012
+ __defNormalProp(a, prop, b[prop]);
1013
+ }
1014
+ return a;
1015
+ };
1016
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
1017
+ function bobe(fragments, ...values) {
1018
+ const ui = function ui2(options, valueOpt, root, before) {
1019
+ const tokenizer = new Tokenizer();
1020
+ const cmp = new Interpreter(tokenizer);
1021
+ Object.assign(cmp, valueOpt);
1022
+ cmp.config(__spreadProps(__spreadValues({}, options), {
1023
+ hook({ i }) {
1024
+ return values[i];
1025
+ },
1026
+ setProp(node, key, value, hookI) {
1027
+ node.props[key] = value;
1028
+ }
1029
+ }));
1030
+ cmp.init(Array.from(fragments));
1031
+ return cmp.program(root, before);
1032
+ };
1033
+ return ui;
1034
+ }
1035
+ function customRender(option) {
1036
+ return function render(Ctor, root) {
1037
+ const store = Ctor.new();
1038
+ return [store["ui"](option, { data: store }, root), store];
1039
+ };
1040
+ }
1041
+
1042
+ exports.bobe = bobe;
1043
+ exports.customRender = customRender;
1044
+ Object.keys(aoye).forEach(function (k) {
1045
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
1046
+ enumerable: true,
1047
+ get: function () { return aoye[k]; }
1048
+ });
1049
+ });
467
1050
  //# sourceMappingURL=bobe.cjs.js.map