bobe 0.0.18 → 0.0.20

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,104 +556,89 @@
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;
346
562
  child = Component.new();
347
563
  } else {
348
564
  render = ComponentOrRender;
565
+ const boundStore = render.boundStore;
349
566
  child = aoye.deepSignal({}, aoye.getPulling(), true);
350
- Object.setPrototypeOf(child, data);
567
+ Object.setPrototypeOf(child, boundStore);
351
568
  }
352
569
  const node = {
353
570
  __logicType: isCC ? FakeType.Component : FakeType.Fragment,
354
571
  realParent: ctx.realParent,
572
+ realBefore: null,
573
+ realAfter: null,
355
574
  data: child,
356
575
  tokenizer: render ? render(true) : child["ui"](true)
357
576
  };
358
- this.onePropParsed = (data2, _, key, value, valueIsMapKey, isFn, hookI) => {
577
+ this.onePropParsed = (data, _, key, value, valueIsMapKey, isFn, hookI) => {
359
578
  if (isFn) {
360
579
  child[aoye.Keys.Raw][key] = value;
361
580
  } else if (valueIsMapKey) {
362
- aoye.shareSignal(data2, value, child, key);
363
- } else if (typeof value === "function") {
581
+ aoye.shareSignal(data, value, child, key);
582
+ } else {
364
583
  const meta = child[aoye.Keys.Meta];
365
584
  const cells = meta.cells;
366
- const computed = aoye.$(value);
367
- cells.set(key, computed);
368
- } else {
369
- 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
+ }
370
593
  }
371
594
  };
372
- node.realAfter = this.insertAfterAnchor(ctx);
595
+ node.realAfter = this.insertAfterAnchor("component-after");
373
596
  return node;
374
597
  }
598
+ getFn(data, expression) {
599
+ return new Function("data", `let v;with(data){v=${expression}};return v;`).bind(void 0, data);
600
+ }
375
601
  // TODO: 优化代码逻辑,拆分 if elseif else
376
602
  condDeclaration(ctx) {
377
603
  var _a;
378
604
  const { prevSibling } = ctx;
379
- const snapbackUp = this.tokenizer.snapshot();
380
605
  const keyWord = this.tokenizer.token;
381
- this.tokenizer.nextToken();
382
- const noSelfCond = this.tokenizer.token.type === TokenType.NewLine;
383
- const [hookType, value] = this.tokenizer._hook({});
606
+ const expToken = this.tokenizer.condExp();
607
+ const value = expToken.value;
384
608
  const isElse = keyWord.value === "else";
385
609
  const isIf = keyWord.value === "if";
386
610
  const preIsCond = (prevSibling == null ? void 0 : prevSibling.__logicType) & CondBit;
387
- const needCalcWithPrevIf = isElse && preIsCond;
388
611
  const data = this.getData();
612
+ const noCond = value === true;
613
+ const valueIsMapKey = !noCond && Reflect.has(data[aoye.Keys.Raw], value);
389
614
  const owner = (_a = ctx.stack.peekByType(NodeSort.TokenizerSwitcher)) == null ? void 0 : _a.node;
390
615
  const ifNode = {
391
616
  __logicType: isElse ? FakeType.Else : isIf ? FakeType.If : FakeType.Fail,
392
- snapshot: noSelfCond ? snapbackUp : this.tokenizer.snapshot(),
393
- condition: null,
617
+ // 此时 token exp, 下次解析 从 \n 开始
618
+ snapshot: this.tokenizer.snapshot(),
394
619
  realParent: null,
620
+ realBefore: null,
621
+ realAfter: null,
622
+ condition: null,
395
623
  preCond: preIsCond ? prevSibling : null,
396
624
  isFirstRender: true,
397
625
  effect: null,
398
626
  owner
399
627
  };
400
628
  let signal;
401
- if (noSelfCond) {
402
- if (isElse) {
403
- signal = aoye.$(() => {
404
- let point = ifNode.preCond;
405
- while (point) {
406
- if (point.condition.v) {
407
- return false;
408
- }
409
- if (point.__logicType === FakeType.If) {
410
- break;
411
- }
412
- point = point.preCond;
413
- }
414
- return true;
415
- });
416
- } else {
417
- signal = aoye.$(() => {
418
- let point = ifNode.preCond;
419
- while (point) {
420
- if (point.condition.v) {
421
- return false;
422
- }
423
- point = point.preCond;
424
- }
425
- return true;
426
- });
427
- }
428
- } else {
429
- const valueIsMapKey = Reflect.has(data[aoye.Keys.Raw], value);
430
- if (valueIsMapKey && !needCalcWithPrevIf) {
431
- aoye.runWithPulling(() => data[value], null);
432
- const { cells } = data[aoye.Keys.Meta];
433
- signal = cells.get(value);
434
- } else {
435
- const fn = new Function("data", `let v;with(data){v=${value}};return v;`).bind(void 0, data);
436
- 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) {
437
642
  signal = aoye.$(() => {
438
643
  let point = ifNode.preCond;
439
644
  while (point) {
@@ -445,43 +650,57 @@
445
650
  }
446
651
  point = point.preCond;
447
652
  }
448
- return fn();
653
+ return true;
449
654
  });
450
655
  } else {
451
- 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
+ });
452
670
  }
453
- }
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;
454
684
  }
455
685
  ifNode.condition = signal;
456
- ifNode.realAfter = this.insertAfterAnchor(ctx);
686
+ ifNode.realAfter = this.insertAfterAnchor(`${keyWord.value}-after`);
457
687
  ifNode.effect = aoye.effect(
458
688
  ({ val }) => {
459
689
  if (val) {
460
690
  if (ifNode.isFirstRender) {
461
- if (!noSelfCond) {
462
- this.tokenizer.nextToken();
463
- }
691
+ this.tokenizer.nextToken();
464
692
  this.tokenizer.nextToken();
465
693
  } else {
466
694
  this.tokenizer = ifNode.owner.tokenizer;
467
695
  this.tokenizer.resume(ifNode.snapshot);
468
- this.program(ifNode.realParent, ifNode.owner, ifNode.realBefore);
696
+ this.tokenizer.useDedentAsEof = false;
697
+ this.program(ifNode.realParent, ifNode.owner, ifNode.realBefore, ifNode);
469
698
  }
470
699
  } else {
471
700
  if (ifNode.isFirstRender) {
472
- if (noSelfCond) {
473
- this.tokenizer.i = this.tokenizer.i - 1;
474
- this.tokenizer.needIndent = false;
475
- }
476
701
  this.tokenizer.skip();
477
702
  } else {
478
- const { realBefore, realAfter, realParent } = ifNode;
479
- let point = realBefore ? this.nextSib(realBefore) : this.firstChild(realParent);
480
- while (point !== realAfter) {
481
- const next = this.nextSib(point);
482
- this.remove(point, realParent, realBefore);
483
- point = next;
484
- }
703
+ this.removeLogicNode(ifNode);
485
704
  }
486
705
  }
487
706
  ifNode.isFirstRender = false;
@@ -490,6 +709,15 @@
490
709
  );
491
710
  return ifNode;
492
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
+ }
493
721
  /**
494
722
  * <extensionLines> ::= PIPE <attributeList> NEWLINE <extensionLines>
495
723
  * | ε
@@ -540,7 +768,7 @@
540
768
  const isFn = typeof rawVal === "function";
541
769
  if (hookType === "dynamic") {
542
770
  const valueIsMapKey = Reflect.has(data[aoye.Keys.Raw], value);
543
- 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);
544
772
  this.onePropParsed(data, _node, key, fn, valueIsMapKey, isFn, hookI);
545
773
  } else if (hookType === "static") {
546
774
  this.onePropParsed(data, _node, key, value, false, isFn, hookI);
@@ -570,14 +798,9 @@
570
798
  firstChild(node) {
571
799
  return node.firstChild;
572
800
  }
573
- _createAnchor() {
574
- const anchor = this.createAnchor();
575
- anchor[IsAnchor] = true;
576
- return anchor;
577
- }
578
- createAnchor() {
801
+ createAnchor(name) {
579
802
  return {
580
- name: "anchor",
803
+ name,
581
804
  nextSibling: null
582
805
  };
583
806
  }
@@ -633,9 +856,9 @@
633
856
  };
634
857
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
635
858
  const _Tokenizer = class _Tokenizer {
636
- constructor(hook, isSubToken) {
859
+ constructor(hook, useDedentAsEof) {
637
860
  this.hook = hook;
638
- this.isSubToken = isSubToken;
861
+ this.useDedentAsEof = useDedentAsEof;
639
862
  /** 缩进大小 默认 2 */
640
863
  this.TabSize = 2;
641
864
  /** 缩进字符 */
@@ -680,7 +903,7 @@
680
903
  }
681
904
  return [hookType, value];
682
905
  };
683
- if (isSubToken) {
906
+ if (useDedentAsEof) {
684
907
  this.setToken(TokenType.Indent, "");
685
908
  this.isFirstToken = true;
686
909
  }
@@ -698,11 +921,20 @@
698
921
  this.dentStack = [0];
699
922
  Object.assign(this, _snapshot);
700
923
  }
701
- snapshot() {
702
- return {
924
+ snapshot(keys) {
925
+ const snap = {
703
926
  i: this.i,
704
927
  waitingTokens: this.waitingTokens.clone()
705
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;
706
938
  }
707
939
  skip() {
708
940
  const logicDentLen = this.dentStack[this.dentStack.length - 1];
@@ -816,17 +1048,21 @@ ${_Tokenizer.EofId}`;
816
1048
  this.str(char);
817
1049
  break;
818
1050
  case "{":
819
- this.brace();
1051
+ const braceToken = this.brace();
1052
+ this.setToken(TokenType.InsertionExp, braceToken);
820
1053
  break;
821
1054
  case "$":
822
1055
  const handled = this.dynamic(char);
823
1056
  if (handled) break;
1057
+ case ";":
1058
+ this.setToken(TokenType.Semicolon, ";");
1059
+ break;
824
1060
  default:
825
1061
  if (bobeShared.isNum(char)) {
826
1062
  this.number(char);
827
1063
  break;
828
1064
  }
829
- if (typeof char === "string" && bobeShared.matchIdStart(char)) {
1065
+ if (typeof char === "string" && bobeShared.matchIdStart2(char, 0)) {
830
1066
  this.identifier(char);
831
1067
  }
832
1068
  break;
@@ -845,6 +1081,58 @@ ${_Tokenizer.EofId}`;
845
1081
  this.handledTokens.push(this.token);
846
1082
  }
847
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
+ }
848
1136
  assignment() {
849
1137
  this.setToken(TokenType.Assign, "=");
850
1138
  }
@@ -910,8 +1198,7 @@ ${_Tokenizer.EofId}`;
910
1198
  }
911
1199
  }
912
1200
  if (count === 0 && inString == null && inComment == null) {
913
- this.setToken(TokenType.InsertionExp, value.slice(1));
914
- return;
1201
+ return value.slice(1);
915
1202
  }
916
1203
  value += this.code[this.i];
917
1204
  this.i++;
@@ -1016,13 +1303,13 @@ ${_Tokenizer.EofId}`;
1016
1303
  const yes = this.dentStack.length === 1;
1017
1304
  if (yes) {
1018
1305
  if (!this.token) {
1019
- if (this.isSubToken) {
1306
+ if (this.useDedentAsEof) {
1020
1307
  this.setToken(TokenType.Dedent, "");
1021
1308
  } else {
1022
1309
  this.setToken(TokenType.Identifier, _Tokenizer.EofId);
1023
1310
  }
1024
1311
  } else {
1025
- if (this.isSubToken) {
1312
+ if (this.useDedentAsEof) {
1026
1313
  this.waitingTokens.push({
1027
1314
  type: TokenType.Dedent,
1028
1315
  typeName: TokenType[TokenType.Dedent],
@@ -1044,13 +1331,13 @@ ${_Tokenizer.EofId}`;
1044
1331
  let nextC;
1045
1332
  while (1) {
1046
1333
  nextC = this.code[this.i + 1];
1047
- if (typeof nextC !== "string" || !bobeShared.matchIdStart(nextC)) {
1334
+ if (typeof nextC !== "string" || !bobeShared.matchIdStart2(nextC, 0)) {
1048
1335
  break;
1049
1336
  }
1050
1337
  value += nextC;
1051
1338
  this.i++;
1052
1339
  }
1053
- if (value === _Tokenizer.EofId && this.isSubToken) {
1340
+ if (value === _Tokenizer.EofId && this.useDedentAsEof) {
1054
1341
  this.setToken(TokenType.Dedent, "");
1055
1342
  return;
1056
1343
  }
@@ -1119,6 +1406,7 @@ ${_Tokenizer.EofId}`;
1119
1406
  tokenizer.init(Array.from(fragments));
1120
1407
  return tokenizer;
1121
1408
  };
1409
+ ui.boundStore = aoye.Store.Current;
1122
1410
  return ui;
1123
1411
  }
1124
1412
  function customRender(option) {