bobe 0.0.9 → 0.0.11

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
@@ -1,5 +1,8 @@
1
1
  'use strict';
2
2
 
3
+ var aoye = require('aoye');
4
+ var bobeShared = require('bobe-shared');
5
+
3
6
  var TokenType = /* @__PURE__ */ ((TokenType2) => {
4
7
  TokenType2[TokenType2["NewLine"] = 1] = "NewLine";
5
8
  TokenType2[TokenType2["Indent"] = 2] = "Indent";
@@ -8,6 +11,7 @@ var TokenType = /* @__PURE__ */ ((TokenType2) => {
8
11
  TokenType2[TokenType2["Assign"] = 16] = "Assign";
9
12
  TokenType2[TokenType2["Pipe"] = 32] = "Pipe";
10
13
  TokenType2[TokenType2["Eof"] = 64] = "Eof";
14
+ TokenType2[TokenType2["InsertionExp"] = 128] = "InsertionExp";
11
15
  return TokenType2;
12
16
  })(TokenType || {});
13
17
  var LogicType = /* @__PURE__ */ ((LogicType2) => {
@@ -15,28 +19,37 @@ var LogicType = /* @__PURE__ */ ((LogicType2) => {
15
19
  LogicType2[LogicType2["ElseIf"] = 2] = "ElseIf";
16
20
  LogicType2[LogicType2["Else"] = 4] = "Else";
17
21
  LogicType2[LogicType2["For"] = 8] = "For";
22
+ LogicType2[LogicType2["Component"] = 16] = "Component";
23
+ LogicType2[LogicType2["Fragment"] = 32] = "Fragment";
24
+ LogicType2[LogicType2["Root"] = 64] = "Root";
18
25
  return LogicType2;
19
26
  })(LogicType || {});
27
+ var TerpEvt = /* @__PURE__ */ ((TerpEvt2) => {
28
+ TerpEvt2["AllAttrGot"] = "all-attr-got";
29
+ TerpEvt2["HandledComponentNode"] = "handled-component-node";
30
+ return TerpEvt2;
31
+ })(TerpEvt || {});
20
32
 
21
- var __defProp = Object.defineProperty;
22
- var __defProps = Object.defineProperties;
23
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
24
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
25
- var __hasOwnProp = Object.prototype.hasOwnProperty;
26
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
27
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
28
- var __spreadValues = (a, b) => {
33
+ var __defProp$1 = Object.defineProperty;
34
+ var __defProps$1 = Object.defineProperties;
35
+ var __getOwnPropDescs$1 = Object.getOwnPropertyDescriptors;
36
+ var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols;
37
+ var __hasOwnProp$1 = Object.prototype.hasOwnProperty;
38
+ var __propIsEnum$1 = Object.prototype.propertyIsEnumerable;
39
+ var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
40
+ var __spreadValues$1 = (a, b) => {
29
41
  for (var prop in b || (b = {}))
30
- if (__hasOwnProp.call(b, prop))
31
- __defNormalProp(a, prop, b[prop]);
32
- if (__getOwnPropSymbols)
33
- for (var prop of __getOwnPropSymbols(b)) {
34
- if (__propIsEnum.call(b, prop))
35
- __defNormalProp(a, prop, b[prop]);
42
+ if (__hasOwnProp$1.call(b, prop))
43
+ __defNormalProp$1(a, prop, b[prop]);
44
+ if (__getOwnPropSymbols$1)
45
+ for (var prop of __getOwnPropSymbols$1(b)) {
46
+ if (__propIsEnum$1.call(b, prop))
47
+ __defNormalProp$1(a, prop, b[prop]);
36
48
  }
37
49
  return a;
38
50
  };
39
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
51
+ var __spreadProps$1 = (a, b) => __defProps$1(a, __getOwnPropDescs$1(b));
52
+ const tap = new bobeShared.BaseEvent();
40
53
  class Interpreter {
41
54
  constructor(tokenizer) {
42
55
  this.tokenizer = tokenizer;
@@ -46,107 +59,112 @@ class Interpreter {
46
59
  this.data = {};
47
60
  /** 模板字符串动态节点索引 */
48
61
  this.hookI = 0;
49
- this.stack = [];
50
62
  this._hook = (props) => {
51
63
  const value = this.tokenizer.token.value;
52
- const isHook = typeof value === "string" && value.indexOf(this.HookId) === 0;
53
- if (this.hook && isHook) {
64
+ const isDynamicHook = this.tokenizer.token.type & TokenType.InsertionExp;
65
+ const isStaticHook = typeof value === "string" && value.indexOf(this.HookId) === 0;
66
+ const hookType = isDynamicHook ? "dynamic" : isStaticHook ? "static" : void 0;
67
+ if (this.hook && isStaticHook) {
54
68
  const hookI = Number(value.slice(this.HookId.length));
55
- const res = this.hook(__spreadProps(__spreadValues({}, props), {
69
+ const res = this.hook(__spreadProps$1(__spreadValues$1({}, props), {
56
70
  HookId: this.HookId,
57
71
  i: hookI
58
72
  }));
59
73
  this.hookI++;
60
- return [isHook, res];
74
+ return [hookType, res];
75
+ } else if (isDynamicHook) {
76
+ return [hookType, value];
61
77
  }
62
- return [isHook, value];
78
+ return [hookType, value];
63
79
  };
64
80
  }
65
- program() {
81
+ // /** program 要挂载的父节点位置 */
82
+ // root: any;
83
+ // /** program 挂载的前置节点 */
84
+ // anchor: any;
85
+ program(root, before) {
86
+ const componentNode = {
87
+ __logicType: LogicType.Component,
88
+ realParent: root,
89
+ store: new aoye.Store()
90
+ };
66
91
  this.tokenizer.consume();
92
+ let prevSibling = null;
67
93
  let current;
68
- let prevSibling;
69
- const rootList = [];
94
+ const stack = [{ node: root, prev: prevSibling }];
70
95
  while (1) {
71
96
  if (this.tokenizer.isEof()) {
72
- rootList.push(current);
97
+ this.handleInsert(root, current, prevSibling, componentNode);
73
98
  break;
74
99
  }
75
100
  const token = this.tokenizer.token;
76
101
  if (token.type & TokenType.Indent) {
77
102
  this.tokenizer.consume();
78
- this.stack.push({
79
- prevSibling,
80
- node: current
103
+ stack.push({
104
+ node: current,
105
+ prev: prevSibling
81
106
  });
107
+ current = this.declaration({ stack, prevSibling });
82
108
  prevSibling = null;
83
- current = this.declaration();
84
109
  continue;
85
110
  }
86
111
  if (current) {
87
- if (this.stack.length) {
88
- const parent = this.stack[this.stack.length - 1].node;
89
- this.insert(parent, current, prevSibling);
112
+ if (stack.length > 1) {
113
+ const { node: parent } = stack[stack.length - 1];
114
+ this.handleInsert(parent, current, prevSibling);
90
115
  } else {
91
- rootList.push(current);
116
+ if (!prevSibling) {
117
+ prevSibling = before;
118
+ }
119
+ this.handleInsert(root, current, prevSibling, componentNode);
92
120
  }
93
121
  }
94
122
  if (this.tokenizer.token.type & TokenType.Dedent) {
95
123
  this.tokenizer.consume();
96
- const { node: parent, prevSibling: prevParent } = this.stack.pop();
97
- prevSibling = prevParent;
124
+ const { node: parent, prev } = stack.pop();
125
+ prevSibling = prev;
98
126
  current = parent;
99
127
  } else {
100
128
  prevSibling = current;
101
- current = this.declaration();
129
+ current = this.declaration({ stack, prevSibling });
102
130
  }
103
131
  }
104
- return rootList;
132
+ componentNode.lastInserted = this.lastInserted;
133
+ this.lastInserted = null;
134
+ return componentNode;
105
135
  }
106
- /**
107
- * @deprecated
108
- * 节点列表:
109
- * 可以是一个节点,也可以跟随更多节点
110
- * <nodeList> ::= <node> <nodeList> <EOF|Dedent>
111
- * |
136
+ /** 处理
137
+ * 是逻辑 是普通
138
+ * 父节点 将子节点加入 directList 调用 insert 方法挨个插入子节点
139
+ * 子节点 仅插入到父逻辑节点 将本节点插入父节点
140
+ * 理论上父节点不能是一个 逻辑节点,遇到if Terp 会重新执行 program 这种情况下,会指定 root 为真实 dom
112
141
  */
113
- nodeList(parent) {
114
- let _node;
115
- let prevSibling;
116
- let prevItem;
117
- while (1) {
118
- if (this.tokenizer.isEof()) {
119
- return;
120
- }
121
- if (this.tokenizer.token.type & TokenType.Dedent) {
122
- this.tokenizer.consume();
123
- return;
124
- }
125
- _node = this.node();
126
- const insert = parent.__logicType ? this.defaultInsert : this.insert.bind(this);
127
- parent.__logicType ? this.defaultRemove : this.remove.bind(this);
128
- if (!_node.__logicType) {
129
- const realPrev = this.getPrevRealSibling(prevSibling);
130
- const currItem = insert(parent, _node, realPrev, prevItem);
131
- prevItem = currItem;
132
- prevSibling = _node;
133
- continue;
142
+ handleInsert(parent, child, prev, parentComponent) {
143
+ if (!child.__logicType) {
144
+ if (!prev || !prev.__logicType) {
145
+ this.insertAfter(parent, child, prev);
146
+ } else {
147
+ const before = prev.lastInserted;
148
+ this.insertAfter(parent, child, before);
149
+ prev.realAfter = child;
134
150
  }
135
- if (prevSibling) {
136
- _node.anchor = prevSibling;
137
- } else if (parent.__logicType) {
138
- _node.anchor = parent;
139
- } else ;
140
- if (_node.child && _node.condition()) {
141
- let item = _node.child;
142
- while (item != null) {
143
- const { value: child } = item;
144
- const realPrev = this.getPrevRealSibling(prevSibling);
145
- const currItem = insert(parent, child, realPrev, prevItem);
146
- item = item.next;
147
- prevItem = currItem;
148
- prevSibling = child;
149
- }
151
+ } else {
152
+ const childCmp = child;
153
+ childCmp.realParent = parent;
154
+ if (!prev) {
155
+ const anchor = this.createAnchor();
156
+ this.insertAfter(parent, anchor, prev);
157
+ this.insertAfter(parent, child, anchor);
158
+ childCmp.realBefore = anchor;
159
+ } else if (prev.__logicType) {
160
+ const before = prev.lastInserted;
161
+ const anchor = this.createAnchor();
162
+ this.insertAfter(parent, anchor, before);
163
+ this.insertAfter(parent, child, anchor);
164
+ childCmp.realBefore = anchor;
165
+ prev.realAfter = anchor;
166
+ } else {
167
+ childCmp.realBefore = prev;
150
168
  }
151
169
  }
152
170
  }
@@ -163,54 +181,111 @@ class Interpreter {
163
181
  point = point.anchor;
164
182
  }
165
183
  }
166
- /**
167
- * 单个节点:
168
- * 由声明部分和(可选的)子节点块组成
169
- * <node> ::= <declaration> <childrenBlockOpt>
170
- * */
171
- node() {
172
- const _declaration = this.declaration();
173
- if (_declaration.__logicType & LogicType.If && !_declaration.condition()) {
174
- return _declaration;
175
- }
176
- this.childrenBlockOpt(_declaration);
177
- return _declaration;
178
- }
179
184
  /**
180
185
  * 声明部分:
181
186
  * 包含首行定义和(可选的)多行属性扩展
182
187
  * <declaration> ::= <tagName=token> <headerLine> <extensionLines>
183
188
  * */
184
- declaration() {
185
- const [isHook, value] = this._hook({});
189
+ declaration(ctx) {
190
+ const [hookType, value] = this._hook({});
186
191
  let _node;
187
- if (isHook) {
188
- const { tree, data } = value();
189
- _node = tree;
190
- } else if (value === "if") {
192
+ if (value === "if") {
191
193
  return this.ifDeclaration();
194
+ } else if (hookType) {
195
+ if (hookType === "static") {
196
+ if (typeof value === "function" && value.prototype instanceof aoye.Store) {
197
+ _node = this.componentDeclaration(value, ctx);
198
+ } else if (typeof value === "function") {
199
+ _node = this.fragmentDeclaration(value);
200
+ } else {
201
+ throw new SyntaxError(`declaration \u4E0D\u652F\u6301 ${value} \u7C7B\u578B\u7684\u9759\u6001\u63D2\u503C`);
202
+ }
203
+ } else {
204
+ Boolean(this.data[aoye.Keys.Raw][value]);
205
+ new Function("data", `let v;with(data){v=(${value})};return v`);
206
+ _node = this.createNode(value);
207
+ }
192
208
  } else {
193
209
  _node = this.createNode(value);
194
210
  }
195
211
  this.tokenizer.consume();
196
212
  this.headerLine(_node);
197
213
  this.extensionLines(_node);
214
+ if (_node.__logicType === LogicType.Component) {
215
+ tap.once(TerpEvt.HandledComponentNode, (node) => _node = node);
216
+ tap.emit(TerpEvt.AllAttrGot);
217
+ }
198
218
  return _node;
199
219
  }
220
+ // TODO: 指定挂载位置
221
+ fragmentDeclaration(renderFragment) {
222
+ const fragmentNode = {
223
+ __logicType: LogicType.Fragment,
224
+ realParent: null
225
+ };
226
+ renderFragment.call(this.data, this.opt, { data: this.data, root: "", anchor: "" });
227
+ return fragmentNode;
228
+ }
229
+ /**
230
+ * key 元素,组件的 key
231
+ * value
232
+ * 1. 静态类型值
233
+ * 2. 插值计算 函数,可以考虑 使用 effect 或 computed 做处理
234
+ *
235
+ * mapKey 映射, 对应子组件的属性
236
+ * */
237
+ onePropParsed(node, key, value, valueIsMapKey, hookI) {
238
+ if (typeof value === "function") {
239
+ aoye.effect(() => {
240
+ const res = value();
241
+ this.setProp(node, key, res, hookI);
242
+ });
243
+ } else if (valueIsMapKey) {
244
+ aoye.effect(() => {
245
+ const res = this.data[value];
246
+ this.setProp(node, key, res, hookI);
247
+ });
248
+ } else {
249
+ this.setProp(node, key, value, hookI);
250
+ }
251
+ }
252
+ componentDeclaration(Component, ctx) {
253
+ const child = Component.new();
254
+ const prevOnePropParsed = this.onePropParsed;
255
+ this.onePropParsed = (node, key, value, valueIsMapKey, hookI) => {
256
+ if (valueIsMapKey) {
257
+ aoye.shareSignal(this.data, value, child, key);
258
+ } else if (typeof value === "function") {
259
+ const meta = child[aoye.Keys.Meta];
260
+ const cells = meta.cells;
261
+ const computed = aoye.$(value);
262
+ cells.set(key, computed);
263
+ } else {
264
+ child[aoye.Keys.Raw][key] = value;
265
+ }
266
+ };
267
+ tap.once(TerpEvt.AllAttrGot, () => {
268
+ const parent = ctx.stack[ctx.stack.length - 1].node;
269
+ const prev = ctx.prevSibling;
270
+ this.onePropParsed = prevOnePropParsed;
271
+ const componentNode = child["ui"](this.opt, { data: child }, parent, prev);
272
+ tap.emit(TerpEvt.HandledComponentNode, componentNode);
273
+ });
274
+ return { __logicType: LogicType.Component };
275
+ }
200
276
  ifDeclaration() {
201
277
  this.tokenizer.consume();
202
278
  const [isHook, value] = this._hook({});
203
279
  const ifNode = {
204
280
  __logicType: LogicType.If,
205
281
  condition: value,
206
- directList: [],
207
- realList: [],
282
+ realParent: null,
208
283
  snapshot: this.tokenizer.snapshot(),
209
284
  isFirstRender: true,
210
285
  watcher: null,
211
286
  anchor: null
212
287
  };
213
- ifNode.watcher = this.effect(
288
+ ifNode.watcher = aoye.effect(
214
289
  ({ val }) => {
215
290
  if (val) {
216
291
  this.tokenizer.consume();
@@ -255,130 +330,84 @@ class Interpreter {
255
330
  * <attributeList> ::= <attribute> <attributeList>
256
331
  * | ε
257
332
  *
258
- * <attribute> ::= <key> <=> <value or dataKey> <=> <value>
259
- *
333
+ * <attribute> ::= <key> = <value>
334
+ * 1. 普通节点 执行 setProps 🪝
335
+ * 2. 组件节点 收集映射关系,或通过 effect 直接设值
260
336
  */
261
337
  attributeList(_node) {
262
- let values = [];
263
- let prevToken = void 0;
264
- while (1) {
265
- if ((prevToken == null ? void 0 : prevToken.type) === TokenType.Identifier && this.tokenizer.token.type !== TokenType.Assign) {
266
- const [v1, v2, v3] = values;
267
- const key = v1;
268
- let dataKey, defaultVal;
269
- if (v3 !== void 0) {
270
- defaultVal = v3;
271
- dataKey = v2;
272
- } else if (v2 !== void 0) {
273
- if (typeof v2 === "string" && v2[0] === "$" && v2[1] !== "{") {
274
- dataKey = v2.slice(1);
275
- } else {
276
- defaultVal = v2;
277
- }
338
+ let key, eq;
339
+ while (!(this.tokenizer.token.type & TokenType.NewLine)) {
340
+ if (key == null) {
341
+ key = this.tokenizer.token.value;
342
+ } else if (eq == null) {
343
+ eq = "=";
344
+ } else {
345
+ const [hookType, value] = this._hook({});
346
+ if (hookType === "dynamic") {
347
+ const valueIsMapKey = Reflect.has(this.data[aoye.Keys.Raw], value);
348
+ const fn = valueIsMapKey ? value : new Function("data", `let v;with(data){v=${value}};return v;`).bind(void 0, this.data);
349
+ this.onePropParsed(_node, key, fn, valueIsMapKey, this.hookI);
350
+ } else if (hookType === "static") {
351
+ this.onePropParsed(_node, key, value, false, this.hookI);
278
352
  } else {
279
- dataKey = key;
353
+ this.onePropParsed(_node, key, value, false, this.hookI);
280
354
  }
281
- let val = defaultVal;
282
- if (dataKey) {
283
- val = this.setDataProp(this.data, dataKey, defaultVal);
284
- }
285
- this.setProp(_node, key, val, this.hookI - 1);
286
- const [isHook, value] = this._hook({});
287
- values = [value];
288
- } else if (this.tokenizer.token.type !== TokenType.Assign) {
289
- const [isHook, value] = this._hook({});
290
- values.push(value);
291
- }
292
- if (!(this.tokenizer.token.type & (TokenType.Identifier | TokenType.Assign))) {
293
- break;
355
+ key = null;
356
+ eq = null;
294
357
  }
295
- prevToken = this.tokenizer.consume();
296
- }
297
- }
298
- /** 子节点块:
299
- * 必须被缩进包裹
300
- * <childrenBlockOpt> ::= INDENT <nodeList>
301
- * | ε /* 空(表示叶子节点,没有孩子)
302
- * */
303
- childrenBlockOpt(parent) {
304
- if (!(this.tokenizer.token.type & TokenType.Indent)) {
305
- return [];
358
+ this.tokenizer.consume();
306
359
  }
307
- this.tokenizer.consume();
308
- const list = this.nodeList(parent);
309
- return list;
310
360
  }
311
361
  config(opt) {
312
362
  Object.assign(this, opt);
313
- }
314
- createData(data) {
315
- return data;
316
- }
317
- setDataProp(data, key, value) {
318
- return data[key] = value;
319
- }
320
- setChildren(node, children) {
321
- node.children = children;
363
+ this.opt = opt;
322
364
  }
323
365
  createNode(name) {
324
366
  return {
325
367
  name,
326
- props: {}
368
+ props: {},
369
+ nextSibling: null
327
370
  };
328
371
  }
329
- createRoot() {
330
- return this.createNode("root");
372
+ nextSib(node) {
373
+ return node.nextSibling;
331
374
  }
332
- insert(parent, node, prevSibling, prevItem) {
333
- return this.defaultInsert(parent, node, prevSibling, prevItem);
334
- }
335
- defaultInsert(parent, node, prevSibling, prevItem) {
336
- if (!parent.child) {
337
- return parent.child = parent.lastChild = {
338
- value: node,
339
- next: null
340
- };
341
- }
342
- const nextItem = prevItem.next;
343
- const item = {
344
- value: node,
345
- next: nextItem
375
+ createAnchor() {
376
+ return {
377
+ name: "anchor",
378
+ nextSibling: null
346
379
  };
347
- prevItem.next = item;
348
- if (!nextItem) {
349
- parent.lastChild = item;
380
+ }
381
+ insertAfter(parent, node, prev) {
382
+ this.lastInserted = node;
383
+ return this.defaultInsert(parent, node, prev);
384
+ }
385
+ defaultInsert(parent, node, prev) {
386
+ if (prev) {
387
+ const next = prev.nextSibling;
388
+ prev.nextSibling = node;
389
+ node.nextSibling = next;
390
+ } else {
391
+ parent.firstChild = node;
350
392
  }
351
- return item;
352
393
  }
353
- remove(parent, node, prevSibling, prevItem) {
354
- return this.defaultRemove(parent, node, prevSibling, prevItem);
394
+ remove(parent, node, prevSibling) {
395
+ return this.defaultRemove(parent, node, prevSibling);
355
396
  }
356
397
  // TODO: 默认改成 prevItem
357
- defaultRemove(parent, node, prevSibling, prevItem) {
358
- const currItem = prevItem.next;
359
- const nextItem = currItem.next;
360
- if (prevItem) {
361
- if (nextItem) {
362
- prevItem.next = nextItem;
363
- } else {
364
- prevItem.next = null;
365
- parent.lastChild = prevItem;
366
- }
367
- } else {
368
- if (nextItem) {
369
- parent.child = nextItem;
370
- } else {
371
- parent.child = null;
372
- parent.lastChild = null;
373
- }
398
+ defaultRemove(parent, node, prevSibling) {
399
+ const next = node.nextSibling;
400
+ if (prevSibling) {
401
+ prevSibling.nextSibling = next;
402
+ }
403
+ if (parent.firstChild === node) {
404
+ parent.firstChild = next;
374
405
  }
375
- currItem.next = null;
376
406
  }
377
407
  setProp(node, key, value, hookI) {
378
408
  node.props[key] = value;
379
409
  }
380
410
  init(fragments) {
381
- this.data = this.createData(this.data);
382
411
  if (typeof fragments === "string") {
383
412
  this.tokenizer.setCode(fragments);
384
413
  } else {
@@ -392,5 +421,476 @@ class Interpreter {
392
421
  }
393
422
  }
394
423
 
395
- exports.Interpreter = Interpreter;
424
+ const _Tokenizer = class _Tokenizer {
425
+ constructor() {
426
+ /** 缩进大小 默认 2 */
427
+ this.TabSize = 2;
428
+ /** 缩进字符 */
429
+ this.Tab = Array.from({ length: this.TabSize }, () => " ").join("");
430
+ /** 匹配标识符 */
431
+ this.IdExp = /[\d\w\/]/;
432
+ /** 回车后需要判断缩进 */
433
+ this.needIndent = false;
434
+ /** 用于跳过第一个节点前的空白字符串,以及生成基础缩进 */
435
+ this.isFirstToken = true;
436
+ /** 记录历史缩进的长度,相对于行首 */
437
+ this.dentStack = [0];
438
+ /** 当前字符 index */
439
+ this.i = 0;
440
+ this.handledTokens = [];
441
+ /**
442
+ * 有些标识符能产生多个 token
443
+ * 例如 dedent
444
+ * parent1
445
+ * child
446
+ * subChild
447
+ * parent2 <- 产生两个 dedent
448
+ */
449
+ this.waitingTokens = new bobeShared.Queue();
450
+ }
451
+ consume() {
452
+ const token = this.token;
453
+ this.nextToken();
454
+ return token;
455
+ }
456
+ // /** 恢复至某一个现场,进行 token 重算 */
457
+ resume(_snapshot) {
458
+ this.token = void 0;
459
+ this.needIndent = false;
460
+ this.isFirstToken = true;
461
+ this.dentStack = [0];
462
+ Object.assign(this, _snapshot);
463
+ }
464
+ snapshot() {
465
+ return {
466
+ i: this.i,
467
+ waitingTokens: this.waitingTokens.clone()
468
+ };
469
+ }
470
+ skip() {
471
+ const dentLen = this.dentStack[this.dentStack.length - 1];
472
+ let needIndent = false;
473
+ let skipFragment = ``;
474
+ this.token = void 0;
475
+ while (1) {
476
+ const char = this.char;
477
+ if (char === "\n") {
478
+ needIndent = true;
479
+ skipFragment += char;
480
+ this.next();
481
+ continue;
482
+ }
483
+ if (!needIndent) {
484
+ skipFragment += char;
485
+ this.next();
486
+ continue;
487
+ }
488
+ needIndent = false;
489
+ const { value, isEmptyLine } = this.getDentValue();
490
+ const currLen = value.length;
491
+ if (isEmptyLine) continue;
492
+ if (value.length > dentLen) {
493
+ skipFragment += value;
494
+ } else {
495
+ for (let i = this.dentStack.length - 1; i >= 0; i--) {
496
+ const expLen = this.dentStack[i];
497
+ if (currLen === expLen) break;
498
+ if (currLen > expLen) {
499
+ throw SyntaxError(`\u7F29\u8FDB\u9519\u8BEF\uFF0C\u7F29\u8FDB\u957F\u5EA6\u4E0D\u5339\u914D`);
500
+ }
501
+ this.dentStack.pop();
502
+ if (!this.token) {
503
+ this.setToken(TokenType.Dedent, String(expLen));
504
+ } else {
505
+ this.waitingTokens.push({
506
+ type: TokenType.Dedent,
507
+ typeName: TokenType[TokenType.Dedent],
508
+ value: String(expLen)
509
+ });
510
+ }
511
+ }
512
+ break;
513
+ }
514
+ }
515
+ if (!this.token) {
516
+ this.nextToken();
517
+ }
518
+ return skipFragment;
519
+ }
520
+ setCode(code) {
521
+ this.code = "\n" + code.trimEnd() + `
522
+ ${_Tokenizer.EofId}`;
523
+ }
524
+ tokenize() {
525
+ var _a, _b;
526
+ do {
527
+ this.nextToken();
528
+ console.log("token:", TokenType[(_a = this.token) == null ? void 0 : _a.type], JSON.stringify(((_b = this.token) == null ? void 0 : _b.value) || ""));
529
+ } while (!this.isEof());
530
+ }
531
+ isEof() {
532
+ if (!this.token) return false;
533
+ return this.token.type & TokenType.Identifier && this.token.value === _Tokenizer.EofId;
534
+ }
535
+ get char() {
536
+ return this.code[this.i];
537
+ }
538
+ get prev() {
539
+ return this.code[this.i - 1];
540
+ }
541
+ get after() {
542
+ return this.code[this.i + 1];
543
+ }
544
+ next() {
545
+ const prev = this.code[this.i];
546
+ this.i++;
547
+ const curr = this.code[this.i];
548
+ return [prev, curr];
549
+ }
550
+ setToken(type, value) {
551
+ this.token = {
552
+ type,
553
+ typeName: TokenType[type],
554
+ value
555
+ };
556
+ this.isFirstToken = false;
557
+ }
558
+ testId(value) {
559
+ if (typeof value !== "string") return false;
560
+ return this.IdExp.test(value);
561
+ }
562
+ nextToken() {
563
+ try {
564
+ if (this.isEof()) {
565
+ return this.token;
566
+ }
567
+ this.token = void 0;
568
+ if (this.waitingTokens.len) {
569
+ const item = this.waitingTokens.shift();
570
+ this.setToken(item.type, item.value);
571
+ return this.token;
572
+ }
573
+ outer: while (1) {
574
+ if (this.needIndent) {
575
+ this.dent();
576
+ } else {
577
+ let { char } = this;
578
+ switch (char) {
579
+ case " ":
580
+ case " ":
581
+ break;
582
+ // 找后续所有 newLine
583
+ case "\n":
584
+ this.newLine();
585
+ this.needIndent = true;
586
+ break;
587
+ case "=":
588
+ this.assignment();
589
+ break;
590
+ case "|":
591
+ this.pipe();
592
+ break;
593
+ case "'":
594
+ case '"':
595
+ this.str(char);
596
+ break;
597
+ case "{":
598
+ this.brace();
599
+ break;
600
+ case "$":
601
+ const handled = this.dynamic(char);
602
+ if (handled) break;
603
+ default:
604
+ if (bobeShared.isNum(char)) {
605
+ this.number(char);
606
+ break;
607
+ }
608
+ if (this.testId(char)) {
609
+ this.identifier(char);
610
+ }
611
+ break;
612
+ }
613
+ this.next();
614
+ }
615
+ if (this.token) {
616
+ break;
617
+ }
618
+ }
619
+ return this.token;
620
+ } catch (error) {
621
+ console.error(error);
622
+ } finally {
623
+ this.handledTokens.push(this.token);
624
+ }
625
+ }
626
+ assignment() {
627
+ this.setToken(TokenType.Assign, "=");
628
+ }
629
+ pipe() {
630
+ this.setToken(TokenType.Pipe, "|");
631
+ }
632
+ dynamic(char) {
633
+ let nextC = this.after;
634
+ if (nextC !== "{") {
635
+ return false;
636
+ }
637
+ this.next();
638
+ let value = "${";
639
+ let innerBrace = 0;
640
+ while (1) {
641
+ nextC = this.after;
642
+ value += nextC;
643
+ this.next();
644
+ if (nextC === "{") {
645
+ innerBrace++;
646
+ }
647
+ if (nextC === "}") {
648
+ if (!innerBrace) {
649
+ break;
650
+ }
651
+ innerBrace--;
652
+ }
653
+ }
654
+ this.setToken(TokenType.Identifier, value);
655
+ return true;
656
+ }
657
+ brace() {
658
+ let inComment, inString, count = 0, value = "", backslashCount = 0;
659
+ while (1) {
660
+ const char = this.char;
661
+ const nextChar = this.after;
662
+ if (inComment === "single" && char === "\n") {
663
+ inComment = null;
664
+ } else if (inComment === "multi" && char === "*" && nextChar === "/") {
665
+ inComment = null;
666
+ value += this.next()[0];
667
+ } else if (inString) {
668
+ if (char === inString && backslashCount % 2 === 0) {
669
+ inString = null;
670
+ }
671
+ backslashCount = char === "\\" ? backslashCount + 1 : 0;
672
+ } else {
673
+ if (char === "/" && nextChar === "/") {
674
+ inComment = "single";
675
+ value += this.next()[0];
676
+ } else if (char === "/" && nextChar === "*") {
677
+ inComment = "multi";
678
+ value += this.next()[0];
679
+ } else if (char === "'" || char === '"' || char === "`") {
680
+ inString = char;
681
+ } else if (char === "{") {
682
+ count++;
683
+ } else if (char === "}") {
684
+ count--;
685
+ }
686
+ }
687
+ if (count === 0 && inString == null && inComment == null) {
688
+ this.setToken(TokenType.InsertionExp, value.slice(1));
689
+ return;
690
+ }
691
+ value += this.next()[0];
692
+ }
693
+ }
694
+ newLine() {
695
+ let value = "\n";
696
+ let nextC;
697
+ while (1) {
698
+ nextC = this.after;
699
+ if (nextC !== "\n") {
700
+ break;
701
+ }
702
+ value += nextC;
703
+ this.next();
704
+ }
705
+ if (this.isFirstToken) {
706
+ return;
707
+ }
708
+ this.setToken(TokenType.NewLine, value);
709
+ }
710
+ getDentValue() {
711
+ let value = "";
712
+ let nextC;
713
+ let isEmptyLine = false;
714
+ while (1) {
715
+ const nextChar = this.char;
716
+ switch (nextChar) {
717
+ case " ":
718
+ nextC = this.Tab;
719
+ break;
720
+ case " ":
721
+ nextC = " ";
722
+ break;
723
+ case "\n":
724
+ nextC = "\n";
725
+ break;
726
+ default:
727
+ nextC = "";
728
+ break;
729
+ }
730
+ if (nextC === "\n") {
731
+ isEmptyLine = true;
732
+ break;
733
+ }
734
+ if (!nextC) {
735
+ break;
736
+ }
737
+ value += nextC;
738
+ this.next();
739
+ }
740
+ return {
741
+ value,
742
+ isEmptyLine
743
+ };
744
+ }
745
+ dent() {
746
+ const { value, isEmptyLine } = this.getDentValue();
747
+ if (isEmptyLine) {
748
+ this.needIndent = true;
749
+ return;
750
+ }
751
+ this.needIndent = false;
752
+ if (this.isFirstToken) {
753
+ this.dentStack[0] = value.length;
754
+ return;
755
+ }
756
+ let currLen = value.length;
757
+ const indentHasLen = currLen > 0;
758
+ const prevLen = this.dentStack[this.dentStack.length - 1];
759
+ if (currLen > prevLen) {
760
+ this.dentStack.push(currLen);
761
+ this.setToken(TokenType.Indent, String(currLen));
762
+ return indentHasLen;
763
+ }
764
+ if (currLen < prevLen) {
765
+ for (let i = this.dentStack.length - 2; i >= 0; i--) {
766
+ const expLen = this.dentStack[i];
767
+ const prevExpLen = this.dentStack[i + 1];
768
+ if (currLen > expLen && currLen < prevExpLen) {
769
+ throw SyntaxError("\u7F29\u8FDB\u5927\u5C0F\u4E0D\u7EDF\u4E00");
770
+ }
771
+ this.dentStack.pop();
772
+ if (!this.token) {
773
+ this.setToken(TokenType.Dedent, String(expLen));
774
+ } else {
775
+ this.waitingTokens.push({
776
+ type: TokenType.Dedent,
777
+ typeName: TokenType[TokenType.Dedent],
778
+ value: String(expLen)
779
+ });
780
+ }
781
+ if (currLen === expLen) {
782
+ break;
783
+ }
784
+ }
785
+ return indentHasLen;
786
+ }
787
+ return indentHasLen;
788
+ }
789
+ identifier(char) {
790
+ let value = char;
791
+ let nextC;
792
+ while (1) {
793
+ nextC = this.after;
794
+ if (!this.testId(nextC)) {
795
+ break;
796
+ }
797
+ value += nextC;
798
+ this.next();
799
+ }
800
+ let realValue = value === "null" ? null : value === "undefined" ? void 0 : value === "false" ? false : value === "true" ? true : value;
801
+ this.setToken(TokenType.Identifier, realValue);
802
+ }
803
+ str(char) {
804
+ let value = '"';
805
+ let nextC;
806
+ let continuousBackslashCount = 0;
807
+ while (1) {
808
+ nextC = this.after;
809
+ value += nextC;
810
+ const memoCount = continuousBackslashCount;
811
+ if (nextC === "\\") {
812
+ continuousBackslashCount++;
813
+ } else {
814
+ continuousBackslashCount = 0;
815
+ }
816
+ this.next();
817
+ if (nextC === char && memoCount % 2 === 0) {
818
+ break;
819
+ }
820
+ }
821
+ this.setToken(TokenType.Identifier, JSON.parse(value.slice(0, -1) + '"'));
822
+ }
823
+ number(char) {
824
+ let value = char;
825
+ let nextC;
826
+ while (1) {
827
+ nextC = this.after;
828
+ if (!bobeShared.isNum(nextC)) {
829
+ break;
830
+ }
831
+ value += nextC;
832
+ this.next();
833
+ }
834
+ this.setToken(TokenType.Identifier, Number(value));
835
+ }
836
+ eof() {
837
+ this.setToken(TokenType.Eof, "End Of File");
838
+ }
839
+ };
840
+ /** Eof 标识符的值 */
841
+ _Tokenizer.EofId = `__EOF__${Date.now()}`;
842
+ let Tokenizer = _Tokenizer;
843
+
844
+ var __defProp = Object.defineProperty;
845
+ var __defProps = Object.defineProperties;
846
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
847
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
848
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
849
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
850
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
851
+ var __spreadValues = (a, b) => {
852
+ for (var prop in b || (b = {}))
853
+ if (__hasOwnProp.call(b, prop))
854
+ __defNormalProp(a, prop, b[prop]);
855
+ if (__getOwnPropSymbols)
856
+ for (var prop of __getOwnPropSymbols(b)) {
857
+ if (__propIsEnum.call(b, prop))
858
+ __defNormalProp(a, prop, b[prop]);
859
+ }
860
+ return a;
861
+ };
862
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
863
+ function bobe(fragments, ...values) {
864
+ const ui = function ui2(options, valueOpt, root, before) {
865
+ const tokenizer = new Tokenizer();
866
+ const cmp = new Interpreter(tokenizer);
867
+ Object.assign(cmp, valueOpt);
868
+ cmp.config(__spreadProps(__spreadValues({}, options), {
869
+ hook({ i }) {
870
+ return values[i];
871
+ },
872
+ setProp(node, key, value, hookI) {
873
+ node.props[key] = value;
874
+ }
875
+ }));
876
+ cmp.init(Array.from(fragments));
877
+ return cmp.program(root, before);
878
+ };
879
+ return ui;
880
+ }
881
+ function customRender(option) {
882
+ return function render(Ctor, root) {
883
+ const store = Ctor.new();
884
+ return [store["ui"](option, { data: store }, root), store];
885
+ };
886
+ }
887
+
888
+ exports.bobe = bobe;
889
+ exports.customRender = customRender;
890
+ Object.keys(aoye).forEach(function (k) {
891
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
892
+ enumerable: true,
893
+ get: function () { return aoye[k]; }
894
+ });
895
+ });
396
896
  //# sourceMappingURL=bobe.cjs.js.map