bobe 0.0.60 → 0.0.61

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.d.ts CHANGED
@@ -16,11 +16,10 @@ declare class Interpreter {
16
16
  private tokenizer;
17
17
  opt: TerpConf;
18
18
  constructor(tokenizer: Tokenizer);
19
- isLogicNode(node: any): number;
20
19
  ctx: ProgramCtx;
21
20
  rootComponent: ComponentNode$1 | null;
22
21
  program(root: any, componentNode?: ComponentNode$1, before?: any, ctxProvider?: any): ComponentNode$1;
23
- insertAnchor(name?: string, isBefore?: boolean): any;
22
+ insertAnchor(node: any, name?: string, isBefore?: boolean): any;
24
23
  /** 处理
25
24
  * 是逻辑 是普通
26
25
  * 父节点 将子节点加入 directList 调用 insert 方法挨个插入子节点
@@ -37,12 +36,17 @@ declare class Interpreter {
37
36
  * */
38
37
  declaration(ctx: ProgramCtx): any;
39
38
  dynamicDeclaration(pData: any, value: string, ctx: ProgramCtx): DynamicNode;
39
+ createTpNode(): TpNode;
40
40
  createContextNode(): ContextNode;
41
41
  formatForCollection(collection: any): {
42
42
  arr: any[];
43
43
  keys: string[] | null;
44
44
  };
45
45
  forDeclaration(): ForNode | ForItemNode;
46
+ /** after 锚点,对 fake 节点反引用
47
+ * 用于 tp 节点 移动时,可以通过 after 锚点找到 fake 节点并做 realParent 的修正
48
+ */
49
+ anchorRefBack(anchor: any, node: LogicNode): void;
46
50
  insertForItem(forNode: ForNode, i: number, parentData: any, newChildren: ForItemNode[], before: any, snapshotForUpdate: any): void;
47
51
  removeForItem(children: ForItemNode[], i: number): void;
48
52
  reuseForItem(child: ForItemNode, data: any, itemExp: string | ((value: any) => any), i: number, indexName?: string,
@@ -169,7 +173,8 @@ declare enum FakeType {
169
173
  Fragment = 32,
170
174
  ForItem = 64,
171
175
  Context = 128,
172
- DynamicText = 256
176
+ DynamicText = 256,
177
+ Tp = 512
173
178
  }
174
179
  type NodeSortBit = number;
175
180
  type BaseType = string | number | boolean | undefined | null;
@@ -296,6 +301,14 @@ type IfNode = LogicNode & {
296
301
  type ContextNode = Omit<LogicNode, 'data'> & {
297
302
  context: any;
298
303
  };
304
+ type TpNode = LogicNode & {
305
+ tpData: any;
306
+ effect: Effect;
307
+ contentBefore: any;
308
+ contentAfter: any;
309
+ owner: ComponentNode$1 | FragmentNode$1;
310
+ snapshot: ReturnType<Tokenizer['snapshot']>;
311
+ };
299
312
  type DynamicNode = Omit<LogicNode, 'data'> & {
300
313
  tokenizer: Tokenizer;
301
314
  /** 模版片段快照 */
@@ -584,7 +597,7 @@ type ParseHooks = Partial<{
584
597
  }>;
585
598
 
586
599
  declare function bobe<T extends Record<any, any> = any>(fragments: TemplateStringsArray, ...values: any[]): UI<T>;
587
- declare function customRender(option: CustomRenderConf): <T>(Ctor: typeof Store, root: any) => (ComponentNode$1 | Store)[];
600
+ declare function customRender(option: CustomRenderConf): <T extends typeof Store>(Ctor: T, root: any) => readonly [ComponentNode$1, InstanceType<T>];
588
601
 
589
602
  type IContext = {
590
603
  <T = any>(name: string): T;
@@ -595,4 +608,4 @@ declare const context: IContext;
595
608
  declare const effect: (callback: (...args: ValueDiff[]) => void, depOrOpt?: Dep[] | Dep | CustomEffectOpt, opt?: CustomEffectOpt) => aoye.Effect;
596
609
 
597
610
  export { Compiler, FakeType, NodeType, ParseErrorCode, ParseSyntaxError, Tokenizer, bobe, context, customRender, effect };
598
- export type { ASTNodeType, BaseNode, CommentNode, ComponentNode, ConditionalNode, DynamicValue, ElementNode, FragmentNode, IContext, InterpolationNode, LogicNode, LoopNode, ParseError, Program, Property, PropertyKeyNode, PropertyValue, SourceLocation, StaticValue, TemplateNode, TextNode };
611
+ export type { ASTNodeType, BaseNode, CommentNode, ComponentNode, ConditionalNode, DynamicValue, ElementNode, FragmentNode, IContext, InterpolationNode, LogicNode, LoopNode, ParseError, Program, Property, PropertyKeyNode, PropertyValue, SourceLocation, StaticValue, TemplateNode, TextNode, UI };
package/dist/index.umd.js CHANGED
@@ -35,15 +35,15 @@
35
35
  FakeType[FakeType["ForItem"] = 64] = "ForItem";
36
36
  FakeType[FakeType["Context"] = 128] = "Context";
37
37
  FakeType[FakeType["DynamicText"] = 256] = "DynamicText";
38
+ FakeType[FakeType["Tp"] = 512] = "Tp";
38
39
  return FakeType;
39
40
  }({});
40
41
  const CondBit = FakeType.If | FakeType.Fail | FakeType.Else;
41
- const LogicalBit = FakeType.If | FakeType.Fail | FakeType.Else | FakeType.For | FakeType.ForItem;
42
42
  const CtxProviderBit = FakeType.If | FakeType.Fail | FakeType.Else | FakeType.For | FakeType.ForItem | FakeType.Component | FakeType.Fragment | FakeType.DynamicText;
43
- const ContextBit = FakeType.If | FakeType.Fail | FakeType.Else | FakeType.ForItem | FakeType.Context;
43
+ const ContextBit = FakeType.If | FakeType.Fail | FakeType.Else | FakeType.ForItem | FakeType.Context | FakeType.Tp;
44
44
  const TokenizerSwitcherBit = FakeType.Component | FakeType.Fragment;
45
45
  let NodeSort = function (NodeSort) {
46
- NodeSort[NodeSort["Logic"] = 1] = "Logic";
46
+ NodeSort[NodeSort["EffectNode"] = 1] = "EffectNode";
47
47
  NodeSort[NodeSort["Real"] = 2] = "Real";
48
48
  NodeSort[NodeSort["Component"] = 4] = "Component";
49
49
  NodeSort[NodeSort["CtxProvider"] = 8] = "CtxProvider";
@@ -56,6 +56,7 @@
56
56
  TerpEvt["HandledComponentNode"] = "handled-component-node";
57
57
  return TerpEvt;
58
58
  })({});
59
+ const FakeNode = Symbol('fake-node');
59
60
  let ParseErrorCode = function (ParseErrorCode) {
60
61
  ParseErrorCode[ParseErrorCode["UNCLOSED_BRACE"] = 9001] = "UNCLOSED_BRACE";
61
62
  ParseErrorCode[ParseErrorCode["UNCLOSED_STRING"] = 9002] = "UNCLOSED_STRING";
@@ -1450,9 +1451,6 @@
1450
1451
  constructor(tokenizer) {
1451
1452
  this.tokenizer = tokenizer;
1452
1453
  }
1453
- isLogicNode(node) {
1454
- return node && node.__logicType & LogicalBit;
1455
- }
1456
1454
  rootComponent = null;
1457
1455
  program(root, componentNode, before, ctxProvider) {
1458
1456
  this.rootComponent = componentNode;
@@ -1471,7 +1469,7 @@
1471
1469
  stack.push({
1472
1470
  node: ctxProvider,
1473
1471
  prev: null
1474
- }, (ctxProvider.__logicType & LogicalBit ? NodeSort.Logic : 0) | NodeSort.CtxProvider);
1472
+ }, (ctxProvider.__logicType && ctxProvider.effect ? NodeSort.EffectNode : 0) | NodeSort.CtxProvider);
1475
1473
  }
1476
1474
  const rootLen = stack.length;
1477
1475
  const ctx = this.ctx = {
@@ -1494,18 +1492,22 @@
1494
1492
  const token = this.tokenizer.token;
1495
1493
  if (token.type & TokenType.Indent) {
1496
1494
  this.tokenizer.nextToken();
1497
- const isLogicNode = this.isLogicNode(ctx.current);
1495
+ const isEffectNode = ctx.current && ctx.current.__logicType && ctx.current.effect;
1498
1496
  stack.push({
1499
1497
  node: ctx.current,
1500
1498
  prev: ctx.prevSibling
1501
- }, !ctx.current.__logicType ? NodeSort.Real : (ctx.current.__logicType & LogicalBit ? NodeSort.Logic : 0) | (ctx.current.__logicType & TokenizerSwitcherBit ? NodeSort.TokenizerSwitcher : 0) | (ctx.current.__logicType & ContextBit ? NodeSort.Context : 0) | (ctx.current.__logicType === FakeType.Component ? NodeSort.Component : 0) | (ctx.current.__logicType & CtxProviderBit ? NodeSort.CtxProvider : 0));
1499
+ }, !ctx.current.__logicType ? NodeSort.Real : (isEffectNode ? NodeSort.EffectNode : 0) | (ctx.current.__logicType & TokenizerSwitcherBit ? NodeSort.TokenizerSwitcher : 0) | (ctx.current.__logicType & ContextBit ? NodeSort.Context : 0) | (ctx.current.__logicType === FakeType.Component ? NodeSort.Component : 0) | (ctx.current.__logicType & CtxProviderBit ? NodeSort.CtxProvider : 0));
1502
1500
  if (ctx.current.__logicType) {
1503
1501
  this.beforeLogicIndent?.(ctx.current);
1504
- if (isLogicNode) {
1502
+ if (isEffectNode) {
1505
1503
  aoye.setPulling(ctx.current.effect);
1506
1504
  if (ctx.current.__logicType & FakeType.ForItem) {
1507
1505
  ctx.prevSibling = ctx.current.realBefore;
1508
1506
  }
1507
+ if (ctx.current.__logicType & FakeType.Tp) {
1508
+ ctx.realParent = ctx.current.tpData[aoye.Keys.Raw].node;
1509
+ ctx.prevSibling = ctx.current.contentBefore;
1510
+ }
1509
1511
  }
1510
1512
  } else {
1511
1513
  if (ctx.current) {
@@ -1541,14 +1543,17 @@
1541
1543
  const prevSameType = stack.peekByType(NodeSort.Real);
1542
1544
  ctx.realParent = prevSameType?.node || root;
1543
1545
  } else {
1544
- if (sort & NodeSort.Logic) {
1545
- const parentLogic = stack.peekByType(NodeSort.Logic)?.node;
1546
+ if (sort & NodeSort.EffectNode) {
1547
+ const parentLogic = stack.peekByType(NodeSort.EffectNode)?.node;
1546
1548
  if (parentLogic) {
1547
1549
  aoye.setPulling(parentLogic.effect);
1548
1550
  } else {
1549
1551
  aoye.setPulling(rootPulling);
1550
1552
  }
1551
1553
  }
1554
+ if (parent.__logicType === FakeType.Tp) {
1555
+ ctx.realParent = parent.realParent;
1556
+ }
1552
1557
  if (sort & NodeSort.TokenizerSwitcher) {
1553
1558
  const switcher = stack.peekByType(NodeSort.TokenizerSwitcher)?.node;
1554
1559
  if (parent.resumeSnapshot) {
@@ -1585,13 +1590,17 @@
1585
1590
  }
1586
1591
  return componentNode;
1587
1592
  }
1588
- insertAnchor(name = 'anchor', isBefore = false) {
1593
+ insertAnchor(node, name = 'anchor', isBefore = false) {
1589
1594
  const _this$ctx = this.ctx,
1590
1595
  realParent = _this$ctx.realParent,
1591
1596
  prevSibling = _this$ctx.prevSibling,
1592
1597
  stack = _this$ctx.stack,
1593
1598
  before = _this$ctx.before;
1599
+ _this$ctx.current;
1594
1600
  const afterAnchor = this.createAnchor(name, isBefore);
1601
+ if (!isBefore) {
1602
+ this.anchorRefBack(afterAnchor, node);
1603
+ }
1595
1604
  this.ctx.prevSibling = stack.length === 2 && !prevSibling ? before : prevSibling;
1596
1605
  this.handleInsert(realParent, afterAnchor, prevSibling);
1597
1606
  return afterAnchor;
@@ -1636,6 +1645,8 @@
1636
1645
  return this.condDeclaration(ctx);
1637
1646
  } else if (value === 'context') {
1638
1647
  _node = this.createContextNode();
1648
+ } else if (value === 'tp') {
1649
+ return this.createTpNode();
1639
1650
  } else if (value === 'for') {
1640
1651
  return this.forDeclaration();
1641
1652
  } else if (hookType) {
@@ -1679,7 +1690,7 @@
1679
1690
  parentDataProvider: ctx.stack.peekByType(NodeSort.CtxProvider)?.node
1680
1691
  };
1681
1692
  let isUpdate = false;
1682
- node.realAfter = this.insertAnchor(`dynamic-after`);
1693
+ node.realAfter = this.insertAnchor(node, `dynamic-after`);
1683
1694
  node.effect = this.effect(({
1684
1695
  old,
1685
1696
  val
@@ -1759,6 +1770,93 @@
1759
1770
  });
1760
1771
  return node;
1761
1772
  }
1773
+ createTpNode() {
1774
+ const child = aoye.deepSignal({}, aoye.getPulling());
1775
+ const node = {
1776
+ __logicType: FakeType.Tp,
1777
+ data: this.getData(),
1778
+ realParent: null,
1779
+ realBefore: null,
1780
+ realAfter: null,
1781
+ contentBefore: null,
1782
+ contentAfter: null,
1783
+ effect: null,
1784
+ snapshot: null,
1785
+ tpData: child,
1786
+ owner: this.ctx.stack.peekByType(NodeSort.TokenizerSwitcher)?.node
1787
+ };
1788
+ this.onePropParsed = createStoreOnePropParsed(child);
1789
+ this.tokenizer.nextToken();
1790
+ this.headerLineAndExtensions(node);
1791
+ this.onePropParsed = this.oneRealPropParsed;
1792
+ node.realAfter = this.insertAnchor(node, 'tp-after');
1793
+ const before = node.contentBefore = this.createAnchor('tp-content-before', true);
1794
+ const after = node.contentAfter = this.createAnchor('tp-content-after', true);
1795
+ let firstRender = true;
1796
+ node.effect = this.effect(({
1797
+ old: oldDom,
1798
+ val: dom
1799
+ }) => {
1800
+ const removeTpChild = () => {
1801
+ if (oldDom) {
1802
+ let point = before;
1803
+ do {
1804
+ const next = this.nextSib(point);
1805
+ this.remove(point, oldDom, null);
1806
+ if (point === after) break;
1807
+ point = next;
1808
+ } while (true);
1809
+ }
1810
+ };
1811
+ if (firstRender) {
1812
+ if (dom) {
1813
+ this.handleInsert(dom, after, null);
1814
+ this.handleInsert(dom, before, null);
1815
+ } else {
1816
+ if (this.tokenizer.token.type === TokenType.Indent) {
1817
+ const dentLen = this.tokenizer.dentStack[this.tokenizer.dentStack.length - 2] ?? 0;
1818
+ this.tokenizer.skip(dentLen);
1819
+ }
1820
+ }
1821
+ } else {
1822
+ if (dom) {
1823
+ if (oldDom) {
1824
+ let point = before,
1825
+ lastInsert = null;
1826
+ do {
1827
+ const next = this.nextSib(point);
1828
+ const fakeNode = point[FakeNode];
1829
+ if (fakeNode) {
1830
+ fakeNode.realParent = dom;
1831
+ }
1832
+ this.handleInsert(dom, point, lastInsert);
1833
+ if (point === after) break;
1834
+ lastInsert = point;
1835
+ point = next;
1836
+ } while (true);
1837
+ } else {
1838
+ this.handleInsert(dom, after, null);
1839
+ this.handleInsert(dom, before, null);
1840
+ this.tokenizer = node.owner.tokenizer;
1841
+ this.tokenizer.resume(node.snapshot);
1842
+ this.tokenizer.useDedentAsEof = false;
1843
+ this.program(dom, node.owner, before, node);
1844
+ }
1845
+ } else {
1846
+ removeTpChild();
1847
+ }
1848
+ }
1849
+ firstRender = false;
1850
+ return isDestroy => {
1851
+ if (isDestroy) {
1852
+ removeTpChild();
1853
+ }
1854
+ };
1855
+ }, [() => child.node], {
1856
+ type: 'render'
1857
+ });
1858
+ return node;
1859
+ }
1762
1860
  createContextNode() {
1763
1861
  const child = aoye.deepSignal({}, aoye.getPulling());
1764
1862
  const parentContext = this.ctx.stack.peekByType(NodeSort.Context)?.node?.context;
@@ -1773,7 +1871,7 @@
1773
1871
  realBefore: null,
1774
1872
  realAfter: null
1775
1873
  };
1776
- node.realAfter = this.insertAnchor('context-after');
1874
+ node.realAfter = this.insertAnchor(node, 'context-after');
1777
1875
  return node;
1778
1876
  }
1779
1877
  formatForCollection(collection) {
@@ -1866,13 +1964,12 @@
1866
1964
  const rawGetKey = new Function('data', `with(data){return (${keyExp})}`);
1867
1965
  forNode.getKey = data => rawGetKey(safe(data));
1868
1966
  }
1869
- window['for1'] = forNode;
1870
1967
  const data = this.getData();
1871
1968
  const cells = data[aoye.Keys.Meta].cells;
1872
1969
  const hasArrExpKey = Reflect.has(data[aoye.Keys.Raw], arrExp);
1873
1970
  const arrSignal = hasArrExpKey ? (data[arrExp], cells.get(arrExp)) : new aoye.Computed(this.getFn(data, arrExp));
1874
1971
  forNode.arrSignal = arrSignal;
1875
- forNode.realAfter = this.insertAnchor('for-after');
1972
+ forNode.realAfter = this.insertAnchor(forNode, 'for-after');
1876
1973
  const _forNode$snapshot = forNode.snapshot;
1877
1974
  _forNode$snapshot.dentStack;
1878
1975
  _forNode$snapshot.isFirstToken;
@@ -1895,8 +1992,8 @@
1895
1992
  const len = arr.length;
1896
1993
  for (let i = len; i--;) {
1897
1994
  const item = this.createForItem(forNode, i, data);
1898
- item.realAfter = this.insertAnchor('for-item-after');
1899
- item.realBefore = this.insertAnchor('for-item-before', true);
1995
+ item.realAfter = this.insertAnchor(item, 'for-item-after');
1996
+ item.realBefore = this.insertAnchor(item, 'for-item-before', true);
1900
1997
  item.realParent = forNode.realParent;
1901
1998
  children[i] = item;
1902
1999
  }
@@ -2058,10 +2155,14 @@
2058
2155
  }, aoye.ScheduleType.Render);
2059
2156
  return forNode.children[0] || forNode;
2060
2157
  }
2158
+ anchorRefBack(anchor, node) {
2159
+ anchor[FakeNode] = node;
2160
+ }
2061
2161
  insertForItem(forNode, i, parentData, newChildren, before, snapshotForUpdate) {
2062
2162
  const item = this.createForItem(forNode, i, parentData);
2063
2163
  newChildren[i] = item;
2064
2164
  let realAfter = this.createAnchor('for-item-after');
2165
+ this.anchorRefBack(realAfter, item);
2065
2166
  this.handleInsert(forNode.realParent, realAfter, before);
2066
2167
  let realBefore = this.createAnchor('for-item-before', true);
2067
2168
  this.handleInsert(forNode.realParent, realBefore, before);
@@ -2232,7 +2333,7 @@
2232
2333
  resumeSnapshot
2233
2334
  };
2234
2335
  this.onePropParsed = onePropParsed;
2235
- node.realAfter = this.insertAnchor('component-after');
2336
+ node.realAfter = this.insertAnchor(node, 'component-after');
2236
2337
  return node;
2237
2338
  }
2238
2339
  getFn(data, expression) {
@@ -2327,7 +2428,7 @@
2327
2428
  break;
2328
2429
  }
2329
2430
  ifNode.condition = signal;
2330
- ifNode.realAfter = this.insertAnchor(`${keyWord.value}-after`);
2431
+ ifNode.realAfter = this.insertAnchor(ifNode, `${keyWord.value}-after`);
2331
2432
  const ef = this.effect(({
2332
2433
  val
2333
2434
  }) => {
@@ -2370,10 +2471,11 @@
2370
2471
  const tokenizer = this.tokenizer;
2371
2472
  do {
2372
2473
  const isComponent = _node.__logicType & TokenizerSwitcherBit;
2474
+ const isTp = _node.__logicType === FakeType.Tp;
2373
2475
  let snapshot, dentLen;
2374
2476
  const data = this.getData();
2375
2477
  const unHandledKey = this.attributeList(_node, data);
2376
- if (isComponent) {
2478
+ if (isComponent || isTp) {
2377
2479
  snapshot = tokenizer.snapshot(undefined, -1);
2378
2480
  dentLen = tokenizer.dentStack[tokenizer.dentStack.length - 1];
2379
2481
  }
@@ -2385,6 +2487,9 @@
2385
2487
  if ((tokenizer.token.type & TokenType.Pipe) === 0) {
2386
2488
  break;
2387
2489
  }
2490
+ } else if (isTp) {
2491
+ _node.snapshot = snapshot;
2492
+ break;
2388
2493
  } else {
2389
2494
  break;
2390
2495
  }