bobe 0.0.57 → 0.0.59

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
@@ -20,7 +20,7 @@ declare class Interpreter {
20
20
  ctx: ProgramCtx;
21
21
  rootComponent: ComponentNode$1 | null;
22
22
  program(root: any, componentNode?: ComponentNode$1, before?: any, ctxProvider?: any): ComponentNode$1;
23
- insertAfterAnchor(name?: string): any;
23
+ insertAnchor(name?: string, isBefore?: boolean): any;
24
24
  /** 处理
25
25
  * 是逻辑 是普通
26
26
  * 父节点 将子节点加入 directList 调用 insert 方法挨个插入子节点
@@ -97,12 +97,16 @@ declare class Interpreter {
97
97
  createNode(name: string): any;
98
98
  nextSib(node: any): any;
99
99
  firstChild(node: any): any;
100
- createAnchor(name: string): any;
100
+ createAnchor(name: string, isBefore?: boolean): any;
101
101
  insertAfter(parent: any, node: any, prev: any): void;
102
102
  defaultInsert(parent: any, node: any, prev: any): void;
103
103
  remove(node: any, parent?: any, prev?: any): void;
104
104
  defaultRemove(node: any, parent: any, prevSibling: any): void;
105
105
  setProp(node: any, key: string, value: any, hookI?: number): any | (() => void);
106
+ beforeIndent?: (node: any) => boolean | void;
107
+ leaveNode?: (node: any, isDedent: boolean) => void;
108
+ beforeLogicIndent?: (node: any) => void;
109
+ leaveLogicNode?: (node: any, isDedent: boolean) => void;
106
110
  Effect: typeof Effect;
107
111
  effect: typeof effect$1;
108
112
  }
@@ -193,10 +197,13 @@ type HookProps = {
193
197
  /** 父节点 */
194
198
  parentNode?: any;
195
199
  };
196
- type TerpConf = Partial<Pick<Interpreter, 'createNode' | 'setProp' | 'insertAfter' | 'remove' | 'createAnchor' | 'firstChild' | 'nextSib'>> & {
200
+ type TerpConf = Partial<Pick<Interpreter, 'createNode' | 'setProp' | 'insertAfter' | 'remove' | 'createAnchor' | 'firstChild' | 'nextSib' | 'beforeIndent' | 'leaveNode' | 'leaveLogicNode' | 'beforeLogicIndent'>> & {
197
201
  noopEffect?: boolean;
198
202
  };
199
- type CustomRenderConf = Pick<TerpConf, 'createNode' | 'setProp' | 'insertAfter' | 'remove' | 'createAnchor' | 'firstChild' | 'nextSib'>;
203
+ type CustomRenderConf = Pick<TerpConf, 'createNode' | 'setProp' | 'insertAfter' | 'remove' | 'createAnchor' | 'firstChild' | 'nextSib' | 'beforeIndent' | 'leaveNode' | 'leaveLogicNode' | 'beforeLogicIndent' | 'noopEffect'> & {
204
+ /** program() 之后、flushMicroEffectManual() 之前调用 */
205
+ onBeforeFlush?: () => void;
206
+ };
200
207
  type Hook = (props: HookProps) => any;
201
208
  type HookType = 'dynamic' | 'static';
202
209
  declare enum ParseErrorCode {
@@ -588,4 +595,4 @@ declare const context: IContext;
588
595
  declare const effect: (callback: (...args: ValueDiff[]) => void, depOrOpt?: Dep[] | Dep | CustomEffectOpt, opt?: CustomEffectOpt) => aoye.Effect;
589
596
 
590
597
  export { Compiler, FakeType, NodeType, ParseErrorCode, ParseSyntaxError, Tokenizer, bobe, context, customRender, effect };
591
- export type { ASTNodeType, BaseNode, CommentNode, ComponentNode, ConditionalNode, DynamicValue, ElementNode, FragmentNode, IContext, InterpolationNode, LoopNode, ParseError, Program, Property, PropertyKeyNode, PropertyValue, SourceLocation, StaticValue, TemplateNode, TextNode };
598
+ export type { ASTNodeType, BaseNode, CommentNode, ComponentNode, ConditionalNode, DynamicValue, ElementNode, FragmentNode, IContext, InterpolationNode, LogicNode, LoopNode, ParseError, Program, Property, PropertyKeyNode, PropertyValue, SourceLocation, StaticValue, TemplateNode, TextNode };
package/dist/index.umd.js CHANGED
@@ -245,7 +245,6 @@
245
245
  }
246
246
  isEof() {
247
247
  if (!this.token) return false;
248
- if (this.i >= this.code.length && !this.waitingTokens.len) return true;
249
248
  return this.token.type & TokenType.Identifier && this.token.value === Tokenizer.EofId;
250
249
  }
251
250
  setToken(type, value, dt = 1) {
@@ -262,6 +261,7 @@
262
261
  if (this.isEof()) {
263
262
  return this.token;
264
263
  }
264
+ if (this.i >= this.code.length && !this.waitingTokens.len) return this.token;
265
265
  this.token = undefined;
266
266
  if (this.waitingTokens.len) {
267
267
  const item = this.waitingTokens.shift();
@@ -1478,6 +1478,9 @@
1478
1478
  if (this.tokenizer.isEof()) {
1479
1479
  if (!ctx.prevSibling) ctx.prevSibling = before;
1480
1480
  this.handleInsert(root, ctx.current, ctx.prevSibling, componentNode);
1481
+ if (ctx.current) {
1482
+ ctx.current.__logicType ? this.leaveLogicNode?.(ctx.current, false) : this.leaveNode?.(ctx.current, false);
1483
+ }
1481
1484
  break;
1482
1485
  }
1483
1486
  const token = this.tokenizer.token;
@@ -1489,6 +1492,7 @@
1489
1492
  prev: ctx.prevSibling
1490
1493
  }, !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));
1491
1494
  if (ctx.current.__logicType) {
1495
+ this.beforeLogicIndent?.(ctx.current);
1492
1496
  if (isLogicNode) {
1493
1497
  aoye.setPulling(ctx.current.effect);
1494
1498
  if (ctx.current.__logicType & FakeType.ForItem) {
@@ -1497,6 +1501,12 @@
1497
1501
  }
1498
1502
  } else {
1499
1503
  if (ctx.current) {
1504
+ if (this.beforeIndent?.(ctx.current) === false) {
1505
+ const dentLen = this.tokenizer.dentStack[this.tokenizer.dentStack.length - 1];
1506
+ this.tokenizer.skip(dentLen);
1507
+ ctx.current = null;
1508
+ continue;
1509
+ }
1500
1510
  ctx.realParent = ctx.current;
1501
1511
  }
1502
1512
  ctx.prevSibling = null;
@@ -1509,6 +1519,7 @@
1509
1519
  ctx.prevSibling = before;
1510
1520
  }
1511
1521
  this.handleInsert(ctx.realParent, ctx.current, ctx.prevSibling);
1522
+ ctx.current.__logicType ? this.leaveLogicNode?.(ctx.current, false) : this.leaveNode?.(ctx.current, false);
1512
1523
  }
1513
1524
  if (this.tokenizer.token.type & TokenType.Dedent) {
1514
1525
  this.tokenizer.nextToken();
@@ -1543,6 +1554,7 @@
1543
1554
  const i = forNode.i,
1544
1555
  arr = forNode.arr,
1545
1556
  snapshot = forNode.snapshot;
1557
+ this.leaveLogicNode?.(parent, false);
1546
1558
  if (i + 1 < arr.length) {
1547
1559
  this.tokenizer.resume(snapshot);
1548
1560
  this.tokenizer.nextToken();
@@ -1565,13 +1577,13 @@
1565
1577
  }
1566
1578
  return componentNode;
1567
1579
  }
1568
- insertAfterAnchor(name = 'anchor') {
1580
+ insertAnchor(name = 'anchor', isBefore = false) {
1569
1581
  const _this$ctx = this.ctx,
1570
1582
  realParent = _this$ctx.realParent,
1571
1583
  prevSibling = _this$ctx.prevSibling,
1572
1584
  stack = _this$ctx.stack,
1573
1585
  before = _this$ctx.before;
1574
- const afterAnchor = this.createAnchor(name);
1586
+ const afterAnchor = this.createAnchor(name, isBefore);
1575
1587
  this.ctx.prevSibling = stack.length === 2 && !prevSibling ? before : prevSibling;
1576
1588
  this.handleInsert(realParent, afterAnchor, prevSibling);
1577
1589
  return afterAnchor;
@@ -1625,7 +1637,7 @@
1625
1637
  _node = this.componentOrFragmentDeclaration(value, ctx);
1626
1638
  } else {
1627
1639
  _node = this.createNode('text');
1628
- _node.text = String(value);
1640
+ this.setProp(_node, 'text', String(value));
1629
1641
  }
1630
1642
  } else {
1631
1643
  return this.dynamicDeclaration(data, value, ctx);
@@ -1659,7 +1671,7 @@
1659
1671
  parentDataProvider: ctx.stack.peekByType(NodeSort.CtxProvider)?.node
1660
1672
  };
1661
1673
  let isUpdate = false;
1662
- node.realAfter = this.insertAfterAnchor(`dynamic-after`);
1674
+ node.realAfter = this.insertAnchor(`dynamic-after`);
1663
1675
  node.effect = this.effect(({
1664
1676
  old,
1665
1677
  val
@@ -1695,11 +1707,13 @@
1695
1707
  this.tokenizer = node.tokenizer;
1696
1708
  if (node.fragmentSnapshot) {
1697
1709
  this.tokenizer.resume(node.fragmentSnapshot);
1698
- this.tokenizer.useDedentAsEof = true;
1699
- this.tokenizer.initIndentWhenUseDedentAsEof();
1700
1710
  }
1701
1711
  if (isUpdate) {
1712
+ this.tokenizer.useDedentAsEof = false;
1702
1713
  this.program(node.realParent, node.owner, node.realBefore, node);
1714
+ } else {
1715
+ this.tokenizer.useDedentAsEof = true;
1716
+ this.tokenizer.initIndentWhenUseDedentAsEof();
1703
1717
  }
1704
1718
  } else {
1705
1719
  node.__logicType = FakeType.DynamicText;
@@ -1708,7 +1722,7 @@
1708
1722
  if (isNewTextNode) {
1709
1723
  textNode = node.textNode = this.createNode('text');
1710
1724
  }
1711
- textNode.text = String(val);
1725
+ this.setProp(textNode, 'text', String(val));
1712
1726
  if (isNewTextNode) {
1713
1727
  if (isUpdate) {
1714
1728
  this.handleInsert(node.realParent, textNode, node.realBefore);
@@ -1720,6 +1734,7 @@
1720
1734
  prevSibling = _this$ctx2.prevSibling;
1721
1735
  this.handleInsert(realParent, textNode, prevSibling);
1722
1736
  }
1737
+ this.leaveNode?.(textNode, false);
1723
1738
  }
1724
1739
  }
1725
1740
  isUpdate = true;
@@ -1750,7 +1765,7 @@
1750
1765
  realBefore: null,
1751
1766
  realAfter: null
1752
1767
  };
1753
- node.realAfter = this.insertAfterAnchor('context-after');
1768
+ node.realAfter = this.insertAnchor('context-after');
1754
1769
  return node;
1755
1770
  }
1756
1771
  formatForCollection(collection) {
@@ -1848,7 +1863,7 @@
1848
1863
  const hasArrExpKey = Reflect.has(data[aoye.Keys.Raw], arrExp);
1849
1864
  const arrSignal = hasArrExpKey ? (data[arrExp], cells.get(arrExp)) : new aoye.Computed(this.getFn(data, arrExp));
1850
1865
  forNode.arrSignal = arrSignal;
1851
- forNode.realAfter = this.insertAfterAnchor('for-after');
1866
+ forNode.realAfter = this.insertAnchor('for-after');
1852
1867
  const _forNode$snapshot = forNode.snapshot;
1853
1868
  _forNode$snapshot.dentStack;
1854
1869
  _forNode$snapshot.isFirstToken;
@@ -1871,8 +1886,8 @@
1871
1886
  const len = arr.length;
1872
1887
  for (let i = len; i--;) {
1873
1888
  const item = this.createForItem(forNode, i, data);
1874
- item.realAfter = this.insertAfterAnchor('for-item-after');
1875
- item.realBefore = this.insertAfterAnchor('for-item-before');
1889
+ item.realAfter = this.insertAnchor('for-item-after');
1890
+ item.realBefore = this.insertAnchor('for-item-before', true);
1876
1891
  item.realParent = forNode.realParent;
1877
1892
  children[i] = item;
1878
1893
  }
@@ -2039,7 +2054,7 @@
2039
2054
  newChildren[i] = item;
2040
2055
  let realAfter = this.createAnchor('for-item-after');
2041
2056
  this.handleInsert(forNode.realParent, realAfter, before);
2042
- let realBefore = this.createAnchor('for-item-before');
2057
+ let realBefore = this.createAnchor('for-item-before', true);
2043
2058
  this.handleInsert(forNode.realParent, realBefore, before);
2044
2059
  item.realBefore = realBefore;
2045
2060
  item.realAfter = realAfter;
@@ -2208,7 +2223,7 @@
2208
2223
  resumeSnapshot
2209
2224
  };
2210
2225
  this.onePropParsed = onePropParsed;
2211
- node.realAfter = this.insertAfterAnchor('component-after');
2226
+ node.realAfter = this.insertAnchor('component-after');
2212
2227
  return node;
2213
2228
  }
2214
2229
  getFn(data, expression) {
@@ -2303,7 +2318,7 @@
2303
2318
  break;
2304
2319
  }
2305
2320
  ifNode.condition = signal;
2306
- ifNode.realAfter = this.insertAfterAnchor(`${keyWord.value}-after`);
2321
+ ifNode.realAfter = this.insertAnchor(`${keyWord.value}-after`);
2307
2322
  const ef = this.effect(({
2308
2323
  val
2309
2324
  }) => {
@@ -2387,7 +2402,51 @@
2387
2402
  hookI = _this$tokenizer$_hook4[2];
2388
2403
  const rawVal = data[aoye.Keys.Raw][value];
2389
2404
  const isFn = typeof rawVal === 'function';
2390
- if (key === 'ref') {
2405
+ if (key === 'props') {
2406
+ let prevKeys = new Set();
2407
+ const savedDefaults = new Map();
2408
+ new this.Effect(() => {
2409
+ const props = isFn ? rawVal : Reflect.has(data[aoye.Keys.Raw], value) ? data[value] : this.getFn(data, value)();
2410
+ const isComponent = _node.__logicType & TokenizerSwitcherBit;
2411
+ const rawTarget = isComponent ? _node.data[aoye.Keys.Raw] : null;
2412
+ const cleanupKeys = keysToClean => {
2413
+ for (const k of keysToClean) {
2414
+ if (k.startsWith('on')) continue;
2415
+ if (isComponent) {
2416
+ _node.data[k] = savedDefaults.has(k) ? savedDefaults.get(k) : undefined;
2417
+ } else {
2418
+ this.setProp(_node, k, undefined, hookI);
2419
+ }
2420
+ }
2421
+ };
2422
+ if (!props || typeof props !== 'object') {
2423
+ cleanupKeys(prevKeys);
2424
+ prevKeys.clear();
2425
+ return;
2426
+ }
2427
+ props[aoye.Keys.Iterator];
2428
+ const raw = props[aoye.Keys.Raw] || props;
2429
+ const keys = Object.keys(raw);
2430
+ const newKeys = new Set();
2431
+ for (let i = 0; i < keys.length; i++) {
2432
+ const k = keys[i];
2433
+ newKeys.add(k);
2434
+ prevKeys.delete(k);
2435
+ if (isComponent) {
2436
+ const savedK = savedDefaults.has(k);
2437
+ if (!savedK && Object.prototype.hasOwnProperty.call(rawTarget, k)) {
2438
+ savedDefaults.set(k, rawTarget[k]);
2439
+ }
2440
+ const val = props[k];
2441
+ _node.data[k] = val === undefined && savedK ? savedDefaults.get(k) : val;
2442
+ } else {
2443
+ this.onePropParsed(props, _node, k, k, true, false, hookI);
2444
+ }
2445
+ }
2446
+ cleanupKeys(prevKeys);
2447
+ prevKeys = newKeys;
2448
+ }, aoye.ScheduleType.Render);
2449
+ } else if (key === 'ref') {
2391
2450
  const valueIsMapKey = Reflect.has(data[aoye.Keys.Raw], value);
2392
2451
  let refValue = _node;
2393
2452
  if (_node.__logicType & TokenizerSwitcherBit) {
@@ -2444,10 +2503,11 @@
2444
2503
  firstChild(node) {
2445
2504
  return node.firstChild;
2446
2505
  }
2447
- createAnchor(name) {
2506
+ createAnchor(name, isBefore) {
2448
2507
  return {
2449
2508
  name,
2450
- nextSibling: null
2509
+ nextSibling: null,
2510
+ isBefore
2451
2511
  };
2452
2512
  }
2453
2513
  insertAfter(parent, node, prev) {
@@ -2533,6 +2593,7 @@
2533
2593
  tokenizer
2534
2594
  };
2535
2595
  terp.program(root, componentNode);
2596
+ option.onBeforeFlush?.();
2536
2597
  aoye.flushMicroEffectManual();
2537
2598
  return [componentNode, store];
2538
2599
  };