bobe 0.0.19 → 0.0.21

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/index.umd.js CHANGED
@@ -13,6 +13,7 @@
13
13
  TokenType2[TokenType2["Pipe"] = 32] = "Pipe";
14
14
  TokenType2[TokenType2["Eof"] = 64] = "Eof";
15
15
  TokenType2[TokenType2["InsertionExp"] = 128] = "InsertionExp";
16
+ TokenType2[TokenType2["Semicolon"] = 256] = "Semicolon";
16
17
  return TokenType2;
17
18
  })(TokenType || {});
18
19
  var FakeType = /* @__PURE__ */ ((FakeType2) => {
@@ -36,7 +37,6 @@
36
37
  NodeSort2[NodeSort2["TokenizerSwitcher"] = 16] = "TokenizerSwitcher";
37
38
  return NodeSort2;
38
39
  })(NodeSort || {});
39
- const IsAnchor = /* @__PURE__ */ Symbol("is-anchor");
40
40
 
41
41
  class MultiTypeStack {
42
42
  constructor() {
@@ -131,17 +131,33 @@
131
131
  // }
132
132
  }
133
133
 
134
+ var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols;
135
+ var __hasOwnProp$1 = Object.prototype.hasOwnProperty;
136
+ var __propIsEnum$1 = Object.prototype.propertyIsEnumerable;
137
+ var __objRest = (source, exclude) => {
138
+ var target = {};
139
+ for (var prop in source)
140
+ if (__hasOwnProp$1.call(source, prop) && exclude.indexOf(prop) < 0)
141
+ target[prop] = source[prop];
142
+ if (source != null && __getOwnPropSymbols$1)
143
+ for (var prop of __getOwnPropSymbols$1(source)) {
144
+ if (exclude.indexOf(prop) < 0 && __propIsEnum$1.call(source, prop))
145
+ target[prop] = source[prop];
146
+ }
147
+ return target;
148
+ };
134
149
  new bobeShared.BaseEvent();
135
150
  class Interpreter {
136
151
  constructor(tokenizer) {
137
152
  this.tokenizer = tokenizer;
138
153
  this.rootComponent = null;
154
+ this.forItemId = 0;
139
155
  this.oneRealPropParsed = this.onePropParsed.bind(this);
140
156
  }
141
157
  isLogicNode(node) {
142
158
  return node && node.__logicType & LogicalBit;
143
159
  }
144
- program(root, componentNode, before) {
160
+ program(root, componentNode, before, ctxProvider) {
145
161
  var _a, _b;
146
162
  this.rootComponent = componentNode;
147
163
  this.tokenizer.nextToken();
@@ -151,6 +167,12 @@
151
167
  { node: componentNode, prev: null },
152
168
  NodeSort.Component | NodeSort.CtxProvider | NodeSort.TokenizerSwitcher
153
169
  );
170
+ if (ctxProvider) {
171
+ stack.push(
172
+ { node: ctxProvider, prev: null },
173
+ (ctxProvider.__logicType & LogicalBit ? NodeSort.Logic : 0) | NodeSort.CtxProvider
174
+ );
175
+ }
154
176
  const ctx = this.ctx = {
155
177
  realParent: root,
156
178
  prevSibling: before,
@@ -214,6 +236,21 @@
214
236
  const switcher = (_b = stack.peekByType(NodeSort.TokenizerSwitcher)) == null ? void 0 : _b.node;
215
237
  this.tokenizer = switcher.tokenizer;
216
238
  }
239
+ if (parent.__logicType === FakeType.ForItem) {
240
+ const { forNode } = parent;
241
+ const { i, arr, snapshot } = forNode;
242
+ if (i + 1 < arr.length) {
243
+ this.tokenizer.resume(snapshot);
244
+ this.tokenizer.nextToken();
245
+ this.tokenizer.nextToken();
246
+ ctx.prevSibling = parent;
247
+ ctx.current = forNode.children[++forNode.i];
248
+ continue;
249
+ }
250
+ ctx.prevSibling = forNode.prevSibling;
251
+ ctx.current = forNode;
252
+ continue;
253
+ }
217
254
  }
218
255
  ctx.prevSibling = prev;
219
256
  ctx.current = parent;
@@ -224,15 +261,10 @@
224
261
  }
225
262
  return componentNode;
226
263
  }
227
- switcherIsRootComponent() {
228
- var _a;
229
- const currentSwitcher = (_a = this.ctx.stack.peekByType(NodeSort.TokenizerSwitcher)) == null ? void 0 : _a.node;
230
- return currentSwitcher === this.rootComponent;
231
- }
232
- insertAfterAnchor(ctx) {
233
- const { realParent, prevSibling, stack, before } = ctx;
234
- const afterAnchor = this.createAnchor();
235
- ctx.prevSibling = stack.length === 2 && !prevSibling ? before : prevSibling;
264
+ insertAfterAnchor(name = "anchor") {
265
+ const { realParent, prevSibling, stack, before } = this.ctx;
266
+ const afterAnchor = this.createAnchor(name);
267
+ this.ctx.prevSibling = stack.length === 2 && !prevSibling ? before : prevSibling;
236
268
  this.handleInsert(realParent, afterAnchor, prevSibling);
237
269
  return afterAnchor;
238
270
  }
@@ -254,7 +286,7 @@
254
286
  const childCmp = child;
255
287
  childCmp.realParent = parent;
256
288
  if (prev == null ? void 0 : prev.__logicType) {
257
- childCmp.realBefore = prev.realAfter;
289
+ childCmp.realBefore = prev.forNode ? prev.forNode.realAfter : prev.realAfter;
258
290
  } else {
259
291
  childCmp.realBefore = prev;
260
292
  }
@@ -283,7 +315,10 @@
283
315
  let _node;
284
316
  if (value === "if" || value === "else" || value === "fail") {
285
317
  return this.condDeclaration(ctx);
318
+ } else if (value === "for") {
319
+ return this.forDeclaration();
286
320
  } else if (hookType) {
321
+ const data = this.getData();
287
322
  if (hookType === "static") {
288
323
  if (typeof value === "function") {
289
324
  _node = this.componentOrFragmentDeclaration(value, ctx);
@@ -291,7 +326,15 @@
291
326
  throw new SyntaxError(`declaration \u4E0D\u652F\u6301 ${value} \u7C7B\u578B\u7684\u9759\u6001\u63D2\u503C`);
292
327
  }
293
328
  } else {
294
- _node = this.componentOrFragmentDeclaration(value, ctx);
329
+ const valueIsMapKey = Reflect.has(data[aoye.Keys.Raw], value);
330
+ const val = data[aoye.Keys.Raw][value];
331
+ if (typeof val === "function") {
332
+ _node = this.componentOrFragmentDeclaration(val, ctx);
333
+ } else {
334
+ const str = valueIsMapKey ? value : this.getFn(data, value);
335
+ _node = this.createNode("text");
336
+ this.onePropParsed(data, _node, "text", str, valueIsMapKey, false);
337
+ }
295
338
  }
296
339
  } else {
297
340
  _node = this.createNode(value);
@@ -305,6 +348,183 @@
305
348
  }
306
349
  return _node;
307
350
  }
351
+ forDeclaration() {
352
+ var _a;
353
+ const arrExp = this.tokenizer.nextToken().value;
354
+ this.tokenizer.nextToken();
355
+ const itemToken = this.tokenizer.nextToken();
356
+ const isDestruct = itemToken.type === TokenType.InsertionExp;
357
+ let itemExp = itemToken.value;
358
+ if (isDestruct) {
359
+ itemExp = "{" + itemExp + "}";
360
+ const vars = itemExp.match(bobeShared.jsVarRegexp).join(",");
361
+ itemExp = new Function("item", `let ${vars}; (${itemExp}=item); return {${vars}};`);
362
+ }
363
+ let indexName, keyExp;
364
+ while (this.tokenizer.code[this.tokenizer.i] !== "\n") {
365
+ const next = this.tokenizer.nextToken();
366
+ if (next.type !== TokenType.Semicolon) {
367
+ if (!indexName) {
368
+ indexName = next.value;
369
+ } else {
370
+ keyExp = next.value;
371
+ }
372
+ }
373
+ }
374
+ const owner = (_a = this.ctx.stack.peekByType(NodeSort.TokenizerSwitcher)) == null ? void 0 : _a.node;
375
+ const prevSibling = this.ctx.prevSibling;
376
+ const forNode = {
377
+ __logicType: FakeType.For,
378
+ snapshot: this.tokenizer.snapshot(["dentStack", "isFirstToken"]),
379
+ realParent: this.ctx.realParent,
380
+ prevSibling,
381
+ realBefore: (prevSibling == null ? void 0 : prevSibling.realAfter) || prevSibling,
382
+ realAfter: null,
383
+ arr: null,
384
+ itemExp,
385
+ indexName,
386
+ getKey: null,
387
+ children: [],
388
+ effect: null,
389
+ owner,
390
+ i: 0
391
+ };
392
+ if (keyExp) {
393
+ forNode.getKey = new Function("data", `let v;with(data){v=${keyExp}};return v;`);
394
+ }
395
+ window["for1"] = forNode;
396
+ const data = this.getData();
397
+ const cells = data[aoye.Keys.Meta].cells;
398
+ const hasArrExpKey = Reflect.has(data[aoye.Keys.Raw], arrExp);
399
+ const arrSignal = hasArrExpKey ? (
400
+ // 有 key 直接拿
401
+ (data[arrExp], cells.get(arrExp))
402
+ ) : (
403
+ // 无key
404
+ aoye.$(this.getFn(data, arrExp))
405
+ );
406
+ forNode.realAfter = this.insertAfterAnchor("for-after");
407
+ const _b = forNode.snapshot, { dentStack, isFirstToken } = _b, snapshotForUpdate = __objRest(_b, ["dentStack", "isFirstToken"]);
408
+ let isFirstRender = true;
409
+ forNode.effect = aoye.effect(() => {
410
+ var _a2;
411
+ let arr = forNode.arr = arrSignal.v;
412
+ arr[aoye.Keys.Iterator];
413
+ arr = aoye.toRaw(arr);
414
+ const children = forNode.children;
415
+ if (isFirstRender) {
416
+ const len = arr.length;
417
+ for (let i = len; i--; ) {
418
+ const nextItem = children[i + 1];
419
+ const item = this.createForItem(forNode, i, data);
420
+ const anchor = this.insertAfterAnchor("for-item-after");
421
+ item.realAfter = anchor;
422
+ if (nextItem) {
423
+ nextItem.realBefore = anchor;
424
+ }
425
+ item.realParent = forNode.realParent;
426
+ children[i] = item;
427
+ }
428
+ const firstInsert = children[0];
429
+ if (firstInsert) {
430
+ firstInsert.realBefore = forNode.realBefore;
431
+ this.tokenizer.nextToken();
432
+ this.tokenizer.nextToken();
433
+ } else {
434
+ this.tokenizer.skip();
435
+ }
436
+ } else {
437
+ const oldLen = children.length;
438
+ const newLen = arr.length;
439
+ const minLen = Math.min(oldLen, newLen);
440
+ const newChildren = [];
441
+ if (!forNode.getKey) {
442
+ if (newLen < oldLen) {
443
+ for (let i = oldLen - 1; i >= newLen; i--) {
444
+ const child = children[i];
445
+ this.removeLogicNode(child);
446
+ this.remove(child.realAfter);
447
+ child.effect();
448
+ }
449
+ }
450
+ if (oldLen < newLen) {
451
+ const lastAfter = ((_a2 = children.at(-1)) == null ? void 0 : _a2.realAfter) || forNode.realBefore;
452
+ for (let i = newLen - 1; i >= oldLen; i--) {
453
+ const item = this.createForItem(forNode, i, data);
454
+ newChildren[i] = item;
455
+ const nextItem = newChildren[i + 1];
456
+ const anchor = this.createAnchor("for-item-after");
457
+ this.insertAfter(forNode.realParent, anchor, lastAfter);
458
+ item.realAfter = anchor;
459
+ if (nextItem) {
460
+ nextItem.realBefore = anchor;
461
+ }
462
+ item.realParent = forNode.realParent;
463
+ this.tokenizer = owner.tokenizer;
464
+ this.tokenizer.resume(snapshotForUpdate);
465
+ this.tokenizer.useDedentAsEof = false;
466
+ aoye.runWithPulling(() => {
467
+ this.program(forNode.realParent, forNode.owner, lastAfter, item);
468
+ }, item.effect.ins);
469
+ }
470
+ const firstInsert = newChildren[oldLen];
471
+ if (firstInsert) {
472
+ firstInsert.realBefore = lastAfter;
473
+ }
474
+ }
475
+ for (let i = minLen; i--; ) {
476
+ const child = children[i];
477
+ newChildren[i] = child;
478
+ if (typeof itemExp === "string") {
479
+ child.data[itemExp] = arr[i];
480
+ } else {
481
+ Object.assign(child.data, itemExp(arr[i]));
482
+ }
483
+ }
484
+ forNode.children = newChildren;
485
+ }
486
+ }
487
+ isFirstRender = false;
488
+ });
489
+ return forNode.children[0] || forNode;
490
+ }
491
+ createForItem(forNode, i, parentData) {
492
+ let forItemNode;
493
+ const effect2 = aoye.scope(() => {
494
+ }, null);
495
+ const { arr, itemExp, indexName, getKey } = forNode;
496
+ let data;
497
+ if (typeof itemExp === "string") {
498
+ data = aoye.$(
499
+ indexName ? {
500
+ [itemExp]: arr[i],
501
+ [indexName]: i
502
+ } : {
503
+ [itemExp]: arr[i]
504
+ }
505
+ );
506
+ } else {
507
+ const rawData = itemExp(arr[i]);
508
+ if (indexName) {
509
+ rawData[indexName] = i;
510
+ }
511
+ data = aoye.$(rawData);
512
+ }
513
+ Object.setPrototypeOf(data, parentData);
514
+ forItemNode = {
515
+ id: this.forItemId++,
516
+ __logicType: FakeType.ForItem,
517
+ realParent: null,
518
+ realBefore: null,
519
+ realAfter: null,
520
+ forNode,
521
+ key: getKey == null ? void 0 : getKey(data),
522
+ effect: null,
523
+ data
524
+ };
525
+ forItemNode.effect = effect2;
526
+ return forItemNode;
527
+ }
308
528
  getData() {
309
529
  const { node } = this.ctx.stack.peekByType(NodeSort.CtxProvider);
310
530
  return node.data || node.owner.data;
@@ -336,10 +556,6 @@
336
556
  }
337
557
  componentOrFragmentDeclaration(ComponentOrRender, ctx) {
338
558
  let Component, render, child;
339
- const data = this.getData();
340
- if (typeof ComponentOrRender === "string") {
341
- ComponentOrRender = data[ComponentOrRender];
342
- }
343
559
  const isCC = ComponentOrRender.prototype instanceof aoye.Store;
344
560
  if (isCC) {
345
561
  Component = ComponentOrRender;
@@ -353,89 +569,76 @@
353
569
  const node = {
354
570
  __logicType: isCC ? FakeType.Component : FakeType.Fragment,
355
571
  realParent: ctx.realParent,
572
+ realBefore: null,
573
+ realAfter: null,
356
574
  data: child,
357
575
  tokenizer: render ? render(true) : child["ui"](true)
358
576
  };
359
- this.onePropParsed = (data2, _, key, value, valueIsMapKey, isFn, hookI) => {
577
+ this.onePropParsed = (data, _, key, value, valueIsMapKey, isFn, hookI) => {
360
578
  if (isFn) {
361
579
  child[aoye.Keys.Raw][key] = value;
362
580
  } else if (valueIsMapKey) {
363
- aoye.shareSignal(data2, value, child, key);
364
- } else if (typeof value === "function") {
581
+ aoye.shareSignal(data, value, child, key);
582
+ } else {
365
583
  const meta = child[aoye.Keys.Meta];
366
584
  const cells = meta.cells;
367
- const computed = aoye.$(value);
368
- cells.set(key, computed);
369
- child[aoye.Keys.Raw][key] = void 0;
370
- } else {
371
- child[aoye.Keys.Raw][key] = value;
585
+ if (typeof value === "function") {
586
+ const computed = aoye.$(value);
587
+ cells.set(key, computed);
588
+ child[aoye.Keys.Raw][key] = void 0;
589
+ } else {
590
+ cells.set(key, { v: value });
591
+ child[aoye.Keys.Raw][key] = value;
592
+ }
372
593
  }
373
594
  };
374
- node.realAfter = this.insertAfterAnchor(ctx);
595
+ node.realAfter = this.insertAfterAnchor("component-after");
375
596
  return node;
376
597
  }
598
+ getFn(data, expression) {
599
+ return new Function("data", `let v;with(data){v=${expression}};return v;`).bind(void 0, data);
600
+ }
377
601
  // TODO: 优化代码逻辑,拆分 if elseif else
378
602
  condDeclaration(ctx) {
379
603
  var _a;
380
604
  const { prevSibling } = ctx;
381
- const snapbackUp = this.tokenizer.snapshot();
382
605
  const keyWord = this.tokenizer.token;
383
- this.tokenizer.nextToken();
384
- const noSelfCond = this.tokenizer.token.type === TokenType.NewLine;
385
- const [hookType, value] = this.tokenizer._hook({});
606
+ const expToken = this.tokenizer.condExp();
607
+ const value = expToken.value;
386
608
  const isElse = keyWord.value === "else";
387
609
  const isIf = keyWord.value === "if";
388
610
  const preIsCond = (prevSibling == null ? void 0 : prevSibling.__logicType) & CondBit;
389
- const needCalcWithPrevIf = isElse && preIsCond;
390
611
  const data = this.getData();
612
+ const noCond = value === true;
613
+ const valueIsMapKey = !noCond && Reflect.has(data[aoye.Keys.Raw], value);
391
614
  const owner = (_a = ctx.stack.peekByType(NodeSort.TokenizerSwitcher)) == null ? void 0 : _a.node;
392
615
  const ifNode = {
393
616
  __logicType: isElse ? FakeType.Else : isIf ? FakeType.If : FakeType.Fail,
394
- snapshot: noSelfCond ? snapbackUp : this.tokenizer.snapshot(),
395
- condition: null,
617
+ // 此时 token exp, 下次解析 从 \n 开始
618
+ snapshot: this.tokenizer.snapshot(),
396
619
  realParent: null,
620
+ realBefore: null,
621
+ realAfter: null,
622
+ condition: null,
397
623
  preCond: preIsCond ? prevSibling : null,
398
624
  isFirstRender: true,
399
625
  effect: null,
400
626
  owner
401
627
  };
402
628
  let signal;
403
- if (noSelfCond) {
404
- if (isElse) {
405
- signal = aoye.$(() => {
406
- let point = ifNode.preCond;
407
- while (point) {
408
- if (point.condition.v) {
409
- return false;
410
- }
411
- if (point.__logicType === FakeType.If) {
412
- break;
413
- }
414
- point = point.preCond;
415
- }
416
- return true;
417
- });
418
- } else {
419
- signal = aoye.$(() => {
420
- let point = ifNode.preCond;
421
- while (point) {
422
- if (point.condition.v) {
423
- return false;
424
- }
425
- point = point.preCond;
426
- }
427
- return true;
428
- });
429
- }
430
- } else {
431
- const valueIsMapKey = Reflect.has(data[aoye.Keys.Raw], value);
432
- if (valueIsMapKey && !needCalcWithPrevIf) {
433
- aoye.runWithPulling(() => data[value], null);
434
- const { cells } = data[aoye.Keys.Meta];
435
- signal = cells.get(value);
436
- } else {
437
- const fn = new Function("data", `let v;with(data){v=${value}};return v;`).bind(void 0, data);
438
- if (needCalcWithPrevIf) {
629
+ switch (keyWord.value) {
630
+ case "if":
631
+ if (valueIsMapKey) {
632
+ aoye.runWithPulling(() => data[value], null);
633
+ const { cells } = data[aoye.Keys.Meta];
634
+ signal = cells.get(value);
635
+ } else {
636
+ const fn = this.getFn(data, value);
637
+ signal = aoye.$(fn);
638
+ }
639
+ break;
640
+ case "else":
641
+ if (noCond) {
439
642
  signal = aoye.$(() => {
440
643
  let point = ifNode.preCond;
441
644
  while (point) {
@@ -447,43 +650,57 @@
447
650
  }
448
651
  point = point.preCond;
449
652
  }
450
- return fn();
653
+ return true;
451
654
  });
452
655
  } else {
453
- signal = aoye.$(fn);
656
+ const fn = valueIsMapKey ? null : this.getFn(data, value);
657
+ signal = aoye.$(() => {
658
+ let point = ifNode.preCond;
659
+ while (point) {
660
+ if (point.condition.v) {
661
+ return false;
662
+ }
663
+ if (point.__logicType === FakeType.If) {
664
+ break;
665
+ }
666
+ point = point.preCond;
667
+ }
668
+ return valueIsMapKey ? data[value] : fn();
669
+ });
454
670
  }
455
- }
671
+ break;
672
+ case "fail":
673
+ signal = aoye.$(() => {
674
+ let point = ifNode.preCond;
675
+ while (point) {
676
+ if (point.condition.v) {
677
+ return false;
678
+ }
679
+ point = point.preCond;
680
+ }
681
+ return true;
682
+ });
683
+ break;
456
684
  }
457
685
  ifNode.condition = signal;
458
- ifNode.realAfter = this.insertAfterAnchor(ctx);
686
+ ifNode.realAfter = this.insertAfterAnchor(`${keyWord.value}-after`);
459
687
  ifNode.effect = aoye.effect(
460
688
  ({ val }) => {
461
689
  if (val) {
462
690
  if (ifNode.isFirstRender) {
463
- if (!noSelfCond) {
464
- this.tokenizer.nextToken();
465
- }
691
+ this.tokenizer.nextToken();
466
692
  this.tokenizer.nextToken();
467
693
  } else {
468
694
  this.tokenizer = ifNode.owner.tokenizer;
469
695
  this.tokenizer.resume(ifNode.snapshot);
470
- this.program(ifNode.realParent, ifNode.owner, ifNode.realBefore);
696
+ this.tokenizer.useDedentAsEof = false;
697
+ this.program(ifNode.realParent, ifNode.owner, ifNode.realBefore, ifNode);
471
698
  }
472
699
  } else {
473
700
  if (ifNode.isFirstRender) {
474
- if (noSelfCond) {
475
- this.tokenizer.i = this.tokenizer.i - 1;
476
- this.tokenizer.needIndent = false;
477
- }
478
701
  this.tokenizer.skip();
479
702
  } else {
480
- const { realBefore, realAfter, realParent } = ifNode;
481
- let point = realBefore ? this.nextSib(realBefore) : this.firstChild(realParent);
482
- while (point !== realAfter) {
483
- const next = this.nextSib(point);
484
- this.remove(point, realParent, realBefore);
485
- point = next;
486
- }
703
+ this.removeLogicNode(ifNode);
487
704
  }
488
705
  }
489
706
  ifNode.isFirstRender = false;
@@ -492,6 +709,15 @@
492
709
  );
493
710
  return ifNode;
494
711
  }
712
+ removeLogicNode(node) {
713
+ const { realBefore, realAfter, realParent } = node;
714
+ let point = realBefore ? this.nextSib(realBefore) : this.firstChild(realParent);
715
+ while (point !== realAfter) {
716
+ const next = this.nextSib(point);
717
+ this.remove(point, realParent, realBefore);
718
+ point = next;
719
+ }
720
+ }
495
721
  /**
496
722
  * <extensionLines> ::= PIPE <attributeList> NEWLINE <extensionLines>
497
723
  * | ε
@@ -542,7 +768,7 @@
542
768
  const isFn = typeof rawVal === "function";
543
769
  if (hookType === "dynamic") {
544
770
  const valueIsMapKey = Reflect.has(data[aoye.Keys.Raw], value);
545
- const fn = isFn ? rawVal : valueIsMapKey ? value : new Function("data", `let v;with(data){v=${value}};return v;`).bind(void 0, data);
771
+ const fn = isFn ? rawVal : valueIsMapKey ? value : this.getFn(data, value);
546
772
  this.onePropParsed(data, _node, key, fn, valueIsMapKey, isFn, hookI);
547
773
  } else if (hookType === "static") {
548
774
  this.onePropParsed(data, _node, key, value, false, isFn, hookI);
@@ -572,14 +798,9 @@
572
798
  firstChild(node) {
573
799
  return node.firstChild;
574
800
  }
575
- _createAnchor() {
576
- const anchor = this.createAnchor();
577
- anchor[IsAnchor] = true;
578
- return anchor;
579
- }
580
- createAnchor() {
801
+ createAnchor(name) {
581
802
  return {
582
- name: "anchor",
803
+ name,
583
804
  nextSibling: null
584
805
  };
585
806
  }
@@ -635,9 +856,9 @@
635
856
  };
636
857
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
637
858
  const _Tokenizer = class _Tokenizer {
638
- constructor(hook, isSubToken) {
859
+ constructor(hook, useDedentAsEof) {
639
860
  this.hook = hook;
640
- this.isSubToken = isSubToken;
861
+ this.useDedentAsEof = useDedentAsEof;
641
862
  /** 缩进大小 默认 2 */
642
863
  this.TabSize = 2;
643
864
  /** 缩进字符 */
@@ -682,7 +903,7 @@
682
903
  }
683
904
  return [hookType, value];
684
905
  };
685
- if (isSubToken) {
906
+ if (useDedentAsEof) {
686
907
  this.setToken(TokenType.Indent, "");
687
908
  this.isFirstToken = true;
688
909
  }
@@ -700,11 +921,20 @@
700
921
  this.dentStack = [0];
701
922
  Object.assign(this, _snapshot);
702
923
  }
703
- snapshot() {
704
- return {
924
+ snapshot(keys) {
925
+ const snap = {
705
926
  i: this.i,
706
927
  waitingTokens: this.waitingTokens.clone()
707
928
  };
929
+ if (keys) {
930
+ for (const k of keys) {
931
+ snap[k] = this[k];
932
+ if (k === "dentStack") {
933
+ snap[k] = this[k].slice();
934
+ }
935
+ }
936
+ }
937
+ return snap;
708
938
  }
709
939
  skip() {
710
940
  const logicDentLen = this.dentStack[this.dentStack.length - 1];
@@ -818,17 +1048,21 @@ ${_Tokenizer.EofId}`;
818
1048
  this.str(char);
819
1049
  break;
820
1050
  case "{":
821
- this.brace();
1051
+ const braceToken = this.brace();
1052
+ this.setToken(TokenType.InsertionExp, braceToken);
822
1053
  break;
823
1054
  case "$":
824
1055
  const handled = this.dynamic(char);
825
1056
  if (handled) break;
1057
+ case ";":
1058
+ this.setToken(TokenType.Semicolon, ";");
1059
+ break;
826
1060
  default:
827
1061
  if (bobeShared.isNum(char)) {
828
1062
  this.number(char);
829
1063
  break;
830
1064
  }
831
- if (typeof char === "string" && bobeShared.matchIdStart(char)) {
1065
+ if (typeof char === "string" && bobeShared.matchIdStart2(char, 0)) {
832
1066
  this.identifier(char);
833
1067
  }
834
1068
  break;
@@ -847,6 +1081,58 @@ ${_Tokenizer.EofId}`;
847
1081
  this.handledTokens.push(this.token);
848
1082
  }
849
1083
  }
1084
+ condExp() {
1085
+ let value = "";
1086
+ this.token = null;
1087
+ while (1) {
1088
+ const char = this.code[this.i];
1089
+ if (char === "\n") {
1090
+ break;
1091
+ }
1092
+ value += char;
1093
+ this.i++;
1094
+ }
1095
+ value = value.trim();
1096
+ this.setToken(TokenType.Identifier, value || true);
1097
+ return this.token;
1098
+ }
1099
+ /**
1100
+ * 解析到 for 时使用这个方法获取 for 后方的子表达式
1101
+ * 表达式通过 “;” 分割
1102
+ * // 最多可有三个表达式
1103
+ * for arr ; item index; item.key
1104
+ * @returns {boolean} 是否含有 key
1105
+ */
1106
+ forLoopSubExp() {
1107
+ this.token = null;
1108
+ let value = "";
1109
+ let count = 0;
1110
+ while (1) {
1111
+ const char = this.code[this.i];
1112
+ const isSemicolon = char === ";";
1113
+ if (isSemicolon || char === "\n") {
1114
+ value = value.trim();
1115
+ if (!this.token) {
1116
+ this.setToken(TokenType.Identifier, value);
1117
+ } else {
1118
+ this.waitingTokens.push({
1119
+ type: TokenType.Identifier,
1120
+ typeName: TokenType[TokenType.Identifier],
1121
+ value
1122
+ });
1123
+ }
1124
+ value = "";
1125
+ count++;
1126
+ if (count > 3) {
1127
+ throw SyntaxError(`for \u5FAA\u73AF\u6700\u591A\u53EF\u5305\u542B\u4E09\u4E2A\u8868\u8FBE\u5F0F, \u5206\u522B\u4E3A arr ; item index [; key]`);
1128
+ }
1129
+ if (!isSemicolon) return count === 3;
1130
+ } else {
1131
+ value += char;
1132
+ }
1133
+ this.i++;
1134
+ }
1135
+ }
850
1136
  assignment() {
851
1137
  this.setToken(TokenType.Assign, "=");
852
1138
  }
@@ -912,8 +1198,7 @@ ${_Tokenizer.EofId}`;
912
1198
  }
913
1199
  }
914
1200
  if (count === 0 && inString == null && inComment == null) {
915
- this.setToken(TokenType.InsertionExp, value.slice(1));
916
- return;
1201
+ return value.slice(1);
917
1202
  }
918
1203
  value += this.code[this.i];
919
1204
  this.i++;
@@ -1018,13 +1303,13 @@ ${_Tokenizer.EofId}`;
1018
1303
  const yes = this.dentStack.length === 1;
1019
1304
  if (yes) {
1020
1305
  if (!this.token) {
1021
- if (this.isSubToken) {
1306
+ if (this.useDedentAsEof) {
1022
1307
  this.setToken(TokenType.Dedent, "");
1023
1308
  } else {
1024
1309
  this.setToken(TokenType.Identifier, _Tokenizer.EofId);
1025
1310
  }
1026
1311
  } else {
1027
- if (this.isSubToken) {
1312
+ if (this.useDedentAsEof) {
1028
1313
  this.waitingTokens.push({
1029
1314
  type: TokenType.Dedent,
1030
1315
  typeName: TokenType[TokenType.Dedent],
@@ -1046,13 +1331,13 @@ ${_Tokenizer.EofId}`;
1046
1331
  let nextC;
1047
1332
  while (1) {
1048
1333
  nextC = this.code[this.i + 1];
1049
- if (typeof nextC !== "string" || !bobeShared.matchIdStart(nextC)) {
1334
+ if (typeof nextC !== "string" || !bobeShared.matchIdStart2(nextC, 0)) {
1050
1335
  break;
1051
1336
  }
1052
1337
  value += nextC;
1053
1338
  this.i++;
1054
1339
  }
1055
- if (value === _Tokenizer.EofId && this.isSubToken) {
1340
+ if (value === _Tokenizer.EofId && this.useDedentAsEof) {
1056
1341
  this.setToken(TokenType.Dedent, "");
1057
1342
  return;
1058
1343
  }