bobe 0.0.54 → 0.0.57

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
@@ -1,8 +1,17 @@
1
1
  import { Queue } from 'bobe-shared';
2
2
  import * as aoye from 'aoye';
3
- import { Store, Keys, Effect, effect as effect$1, Scope, Signal, Computed, SignalNode, ValueDiff, CustomEffectOpt } from 'aoye';
3
+ import { Keys, Store, Effect, effect as effect$1, Scope, Signal, Computed, SignalNode, ValueDiff, CustomEffectOpt } from 'aoye';
4
4
  export { Store } from 'aoye';
5
5
 
6
+ declare class InlineFragment {
7
+ snapshot: Partial<Tokenizer>;
8
+ data: any;
9
+ key: string;
10
+ tokenizer: Tokenizer;
11
+ [Keys.ProxyFreeObject]: boolean;
12
+ constructor(snapshot: Partial<Tokenizer>, data: any, key: string, tokenizer: Tokenizer);
13
+ }
14
+
6
15
  declare class Interpreter {
7
16
  private tokenizer;
8
17
  opt: TerpConf;
@@ -11,10 +20,7 @@ declare class Interpreter {
11
20
  ctx: ProgramCtx;
12
21
  rootComponent: ComponentNode$1 | null;
13
22
  program(root: any, componentNode?: ComponentNode$1, before?: any, ctxProvider?: any): ComponentNode$1;
14
- insertAfterAnchor(name?: string): {
15
- name: string;
16
- nextSibling: any;
17
- };
23
+ insertAfterAnchor(name?: string): any;
18
24
  /** 处理
19
25
  * 是逻辑 是普通
20
26
  * 父节点 将子节点加入 directList 调用 insert 方法挨个插入子节点
@@ -30,6 +36,7 @@ declare class Interpreter {
30
36
  * <declaration> ::= <tagName=token> <headerLineAndExtensions>
31
37
  * */
32
38
  declaration(ctx: ProgramCtx): any;
39
+ dynamicDeclaration(pData: any, value: string, ctx: ProgramCtx): DynamicNode;
33
40
  createContextNode(): ContextNode;
34
41
  formatForCollection(collection: any): {
35
42
  arr: any[];
@@ -55,6 +62,7 @@ declare class Interpreter {
55
62
  * */
56
63
  onePropParsed(data: Store, node: any, key: string, value: any, valueIsMapKey: boolean, isFn: boolean, hookI?: number): void;
57
64
  oneRealPropParsed: Interpreter['onePropParsed'];
65
+ private createComponentData;
58
66
  componentOrFragmentDeclaration(ComponentOrRender: UI | typeof Store | InlineFragment, ctx: ProgramCtx): ComponentNode$1;
59
67
  getFn(data: any, expression: string | number): any;
60
68
  getAssignFn(data: any, expression: string | number): any;
@@ -86,33 +94,18 @@ declare class Interpreter {
86
94
  */
87
95
  attributeList(_node: any, data: any): string;
88
96
  config(opt: TerpConf): void;
89
- createNode(name: string): {
90
- name: string;
91
- props: {};
92
- nextSibling: any;
93
- };
97
+ createNode(name: string): any;
94
98
  nextSib(node: any): any;
95
99
  firstChild(node: any): any;
96
- createAnchor(name: string): {
97
- name: string;
98
- nextSibling: any;
99
- };
100
+ createAnchor(name: string): any;
100
101
  insertAfter(parent: any, node: any, prev: any): void;
101
102
  defaultInsert(parent: any, node: any, prev: any): void;
102
103
  remove(node: any, parent?: any, prev?: any): void;
103
104
  defaultRemove(node: any, parent: any, prevSibling: any): void;
104
- setProp(node: any, key: string, value: any, hookI?: number): void | undefined | (() => void);
105
+ setProp(node: any, key: string, value: any, hookI?: number): any | (() => void);
105
106
  Effect: typeof Effect;
106
107
  effect: typeof effect$1;
107
108
  }
108
- declare class InlineFragment {
109
- snapshot: Partial<Tokenizer>;
110
- data: any;
111
- key: string;
112
- tokenizer: Tokenizer;
113
- [Keys.ProxyFreeObject]: boolean;
114
- constructor(snapshot: Partial<Tokenizer>, data: any, key: string, tokenizer: Tokenizer);
115
- }
116
109
 
117
110
  interface StackNode<T> {
118
111
  value: T;
@@ -171,7 +164,8 @@ declare enum FakeType {
171
164
  Component = 16,
172
165
  Fragment = 32,
173
166
  ForItem = 64,
174
- Context = 128
167
+ Context = 128,
168
+ DynamicText = 256
175
169
  }
176
170
  type NodeSortBit = number;
177
171
  type BaseType = string | number | boolean | undefined | null;
@@ -246,6 +240,7 @@ type ProgramCtx = {
246
240
  type UI<T = any> = {
247
241
  /** 在哪个 Store 声明的 */
248
242
  boundStore: Store;
243
+ __BOBE_IS_UI: true;
249
244
  /** 用户声明片段内可用的 props */
250
245
  defineProps?: T;
251
246
  (isSub: boolean): Tokenizer;
@@ -294,8 +289,23 @@ type IfNode = LogicNode & {
294
289
  type ContextNode = Omit<LogicNode, 'data'> & {
295
290
  context: any;
296
291
  };
292
+ type DynamicNode = Omit<LogicNode, 'data'> & {
293
+ tokenizer: Tokenizer;
294
+ /** 模版片段快照 */
295
+ fragmentSnapshot?: ReturnType<Tokenizer['snapshot']>;
296
+ /** 渲染模版片段前的 快照,渲染完成后用于恢复 */
297
+ resumeSnapshot?: ReturnType<Tokenizer['snapshot']>;
298
+ snapshot: ReturnType<Tokenizer['snapshot']>;
299
+ owner: ComponentNode$1 | FragmentNode$1;
300
+ data?: any;
301
+ parentDataProvider: any;
302
+ effect: Effect;
303
+ textNode: any;
304
+ };
297
305
  type FragmentNode$1 = LogicNode & {
298
306
  tokenizer: Tokenizer;
307
+ fragmentSnapshot?: ReturnType<Tokenizer['snapshot']>;
308
+ resumeSnapshot?: ReturnType<Tokenizer['snapshot']>;
299
309
  };
300
310
  type ComponentNode$1 = LogicNode & {
301
311
  tokenizer: Tokenizer;
@@ -577,5 +587,5 @@ declare const context: IContext;
577
587
 
578
588
  declare const effect: (callback: (...args: ValueDiff[]) => void, depOrOpt?: Dep[] | Dep | CustomEffectOpt, opt?: CustomEffectOpt) => aoye.Effect;
579
589
 
580
- export { Compiler, NodeType, ParseErrorCode, ParseSyntaxError, Tokenizer, bobe, context, customRender, effect };
590
+ export { Compiler, FakeType, NodeType, ParseErrorCode, ParseSyntaxError, Tokenizer, bobe, context, customRender, effect };
581
591
  export type { ASTNodeType, BaseNode, CommentNode, ComponentNode, ConditionalNode, DynamicValue, ElementNode, FragmentNode, IContext, InterpolationNode, LoopNode, ParseError, Program, Property, PropertyKeyNode, PropertyValue, SourceLocation, StaticValue, TemplateNode, TextNode };
package/dist/index.umd.js CHANGED
@@ -34,11 +34,12 @@
34
34
  FakeType[FakeType["Fragment"] = 32] = "Fragment";
35
35
  FakeType[FakeType["ForItem"] = 64] = "ForItem";
36
36
  FakeType[FakeType["Context"] = 128] = "Context";
37
+ FakeType[FakeType["DynamicText"] = 256] = "DynamicText";
37
38
  return FakeType;
38
39
  }({});
39
40
  const CondBit = FakeType.If | FakeType.Fail | FakeType.Else;
40
41
  const LogicalBit = FakeType.If | FakeType.Fail | FakeType.Else | FakeType.For | FakeType.ForItem;
41
- FakeType.If | FakeType.Fail | FakeType.Else | FakeType.For | FakeType.ForItem | FakeType.Component | FakeType.Fragment;
42
+ const CtxProviderBit = FakeType.If | FakeType.Fail | FakeType.Else | FakeType.For | FakeType.ForItem | FakeType.Component | FakeType.Fragment | FakeType.DynamicText;
42
43
  const ContextBit = FakeType.If | FakeType.Fail | FakeType.Else | FakeType.ForItem | FakeType.Context;
43
44
  const TokenizerSwitcherBit = FakeType.Component | FakeType.Fragment;
44
45
  let NodeSort = function (NodeSort) {
@@ -244,6 +245,7 @@
244
245
  }
245
246
  isEof() {
246
247
  if (!this.token) return false;
248
+ if (this.i >= this.code.length && !this.waitingTokens.len) return true;
247
249
  return this.token.type & TokenType.Identifier && this.token.value === Tokenizer.EofId;
248
250
  }
249
251
  setToken(type, value, dt = 1) {
@@ -1418,6 +1420,17 @@
1418
1420
  }
1419
1421
  return candyLast;
1420
1422
  }
1423
+ class InlineFragment {
1424
+ [aoye.Keys.ProxyFreeObject] = true;
1425
+ constructor(snapshot, data, key, tokenizer) {
1426
+ this.snapshot = snapshot;
1427
+ this.data = data;
1428
+ this.key = key;
1429
+ this.tokenizer = tokenizer;
1430
+ }
1431
+ }
1432
+ const isUI = fn => typeof fn === 'function' && fn.__BOBE_IS_UI;
1433
+ const isRenderAble = val => aoye.isStore(val) || isUI(val) || val instanceof InlineFragment;
1421
1434
 
1422
1435
  const KEY_INDEX = '__BOBE_KEY_INDEX';
1423
1436
  let _ctxStack;
@@ -1474,7 +1487,7 @@
1474
1487
  stack.push({
1475
1488
  node: ctx.current,
1476
1489
  prev: ctx.prevSibling
1477
- }, !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 !== FakeType.Context ? NodeSort.CtxProvider : 0));
1490
+ }, !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));
1478
1491
  if (ctx.current.__logicType) {
1479
1492
  if (isLogicNode) {
1480
1493
  aoye.setPulling(ctx.current.effect);
@@ -1608,21 +1621,14 @@
1608
1621
  } else if (hookType) {
1609
1622
  const data = this.getData();
1610
1623
  if (hookType === 'static') {
1611
- if (typeof value === 'function') {
1624
+ if (isRenderAble(value)) {
1612
1625
  _node = this.componentOrFragmentDeclaration(value, ctx);
1613
1626
  } else {
1614
- throw new SyntaxError(`declaration 不支持 ${value} 类型的静态插值`);
1615
- }
1616
- } else {
1617
- const valueIsMapKey = Reflect.has(data[aoye.Keys.Raw], value);
1618
- const val = data[aoye.Keys.Raw][value];
1619
- if (typeof val === 'function' || val instanceof InlineFragment) {
1620
- _node = this.componentOrFragmentDeclaration(val, ctx);
1621
- } else {
1622
- const str = valueIsMapKey ? value : this.getFn(data, value);
1623
1627
  _node = this.createNode('text');
1624
- this.onePropParsed(data, _node, 'text', str, valueIsMapKey, false);
1628
+ _node.text = String(value);
1625
1629
  }
1630
+ } else {
1631
+ return this.dynamicDeclaration(data, value, ctx);
1626
1632
  }
1627
1633
  } else {
1628
1634
  _node = this.createNode(value);
@@ -1640,6 +1646,96 @@
1640
1646
  }
1641
1647
  return _node;
1642
1648
  }
1649
+ dynamicDeclaration(pData, value, ctx) {
1650
+ const valueIsMapKey = Reflect.has(pData[aoye.Keys.Raw], value);
1651
+ let node = {
1652
+ __logicType: null,
1653
+ realParent: null,
1654
+ tokenizer: null,
1655
+ effect: null,
1656
+ textNode: null,
1657
+ owner: ctx.stack.peekByType(NodeSort.TokenizerSwitcher)?.node,
1658
+ snapshot: this.tokenizer.snapshot(['dentStack']),
1659
+ parentDataProvider: ctx.stack.peekByType(NodeSort.CtxProvider)?.node
1660
+ };
1661
+ let isUpdate = false;
1662
+ node.realAfter = this.insertAfterAnchor(`dynamic-after`);
1663
+ node.effect = this.effect(({
1664
+ old,
1665
+ val
1666
+ }) => {
1667
+ let oldLogicType = node.__logicType,
1668
+ oldTextNode = node.textNode;
1669
+ if (oldLogicType) {
1670
+ this.removeLogicNode(node);
1671
+ bobeShared.pickInPlace(node, ['realParent', 'realBefore', 'realAfter',, 'owner', 'snapshot', 'parentDataProvider']);
1672
+ }
1673
+ if (isRenderAble(val)) {
1674
+ if (oldTextNode) {
1675
+ this.remove(oldTextNode);
1676
+ }
1677
+ const info = this.createComponentData(val);
1678
+ info.__logicType;
1679
+ Object.assign(node, info);
1680
+ this.onePropParsed = info.onePropParsed;
1681
+ if (isUpdate) {
1682
+ this.tokenizer = node.owner.tokenizer;
1683
+ this.tokenizer.resume(node.snapshot);
1684
+ this.ctx.stack.push({
1685
+ node: node.parentDataProvider,
1686
+ prev: null
1687
+ }, NodeSort.CtxProvider);
1688
+ }
1689
+ this.tokenizer.nextToken();
1690
+ this.headerLineAndExtensions(node);
1691
+ if (isUpdate) {
1692
+ this.ctx.stack.pop();
1693
+ }
1694
+ this.onePropParsed = this.oneRealPropParsed;
1695
+ this.tokenizer = node.tokenizer;
1696
+ if (node.fragmentSnapshot) {
1697
+ this.tokenizer.resume(node.fragmentSnapshot);
1698
+ this.tokenizer.useDedentAsEof = true;
1699
+ this.tokenizer.initIndentWhenUseDedentAsEof();
1700
+ }
1701
+ if (isUpdate) {
1702
+ this.program(node.realParent, node.owner, node.realBefore, node);
1703
+ }
1704
+ } else {
1705
+ node.__logicType = FakeType.DynamicText;
1706
+ let textNode = oldTextNode;
1707
+ const isNewTextNode = !textNode;
1708
+ if (isNewTextNode) {
1709
+ textNode = node.textNode = this.createNode('text');
1710
+ }
1711
+ textNode.text = String(val);
1712
+ if (isNewTextNode) {
1713
+ if (isUpdate) {
1714
+ this.handleInsert(node.realParent, textNode, node.realBefore);
1715
+ } else {
1716
+ this.tokenizer.nextToken();
1717
+ this.headerLineAndExtensions(node);
1718
+ const _this$ctx2 = this.ctx,
1719
+ realParent = _this$ctx2.realParent,
1720
+ prevSibling = _this$ctx2.prevSibling;
1721
+ this.handleInsert(realParent, textNode, prevSibling);
1722
+ }
1723
+ }
1724
+ }
1725
+ isUpdate = true;
1726
+ return isDestroy => {
1727
+ if (isDestroy) {
1728
+ this.removeLogicNode(node);
1729
+ }
1730
+ };
1731
+ }, [() => {
1732
+ const val = valueIsMapKey ? pData[value] : this.getFn(pData, value)();
1733
+ return val;
1734
+ }], {
1735
+ type: 'render'
1736
+ });
1737
+ return node;
1738
+ }
1643
1739
  createContextNode() {
1644
1740
  const child = aoye.deepSignal({}, aoye.getPulling());
1645
1741
  const parentContext = this.ctx.stack.peekByType(NodeSort.Context)?.node?.context;
@@ -2058,20 +2154,22 @@
2058
2154
  }
2059
2155
  }
2060
2156
  oneRealPropParsed = this.onePropParsed.bind(this);
2061
- componentOrFragmentDeclaration(ComponentOrRender, ctx) {
2062
- let Component, tokenizer, child, fragmentSnapshot, resumeSnapshot;
2157
+ createComponentData(ComponentOrRender) {
2158
+ let tokenizer, child, fragmentSnapshot, resumeSnapshot, __logicType;
2063
2159
  const isCC = ComponentOrRender.prototype instanceof aoye.Store;
2064
2160
  if (isCC) {
2065
- Component = ComponentOrRender;
2161
+ const Component = ComponentOrRender;
2066
2162
  child = Component.new();
2067
2163
  tokenizer = child.ui(true);
2164
+ __logicType = FakeType.Component;
2068
2165
  } else if (ComponentOrRender instanceof InlineFragment) {
2069
2166
  const conf = ComponentOrRender;
2070
2167
  child = aoye.deepSignal({}, aoye.getPulling(), true);
2071
2168
  Object.setPrototypeOf(child, conf.data);
2072
2169
  tokenizer = conf.tokenizer;
2073
2170
  fragmentSnapshot = conf.snapshot;
2074
- resumeSnapshot = tokenizer.snapshot(['token', 'needIndent', 'isFirstToken', 'dentStack', 'isFirstToken', 'useDedentAsEof']);
2171
+ __logicType = FakeType.Fragment;
2172
+ resumeSnapshot = tokenizer.snapshot(['dentStack', 'token', 'needIndent', 'isFirstToken', 'isFirstToken', 'useDedentAsEof']);
2075
2173
  } else {
2076
2174
  const render = ComponentOrRender;
2077
2175
  const boundStore = render.boundStore;
@@ -2080,18 +2178,36 @@
2080
2178
  Object.setPrototypeOf(child, boundStore);
2081
2179
  }
2082
2180
  tokenizer = render(true);
2181
+ __logicType = FakeType.Fragment;
2083
2182
  }
2183
+ return {
2184
+ data: child,
2185
+ tokenizer,
2186
+ onePropParsed: createStoreOnePropParsed(child),
2187
+ fragmentSnapshot,
2188
+ resumeSnapshot,
2189
+ __logicType
2190
+ };
2191
+ }
2192
+ componentOrFragmentDeclaration(ComponentOrRender, ctx) {
2193
+ const _this$createComponent = this.createComponentData(ComponentOrRender),
2194
+ data = _this$createComponent.data,
2195
+ tokenizer = _this$createComponent.tokenizer,
2196
+ onePropParsed = _this$createComponent.onePropParsed,
2197
+ fragmentSnapshot = _this$createComponent.fragmentSnapshot,
2198
+ resumeSnapshot = _this$createComponent.resumeSnapshot,
2199
+ __logicType = _this$createComponent.__logicType;
2084
2200
  const node = {
2085
- __logicType: isCC ? FakeType.Component : FakeType.Fragment,
2201
+ __logicType,
2086
2202
  realParent: ctx.realParent,
2087
2203
  realBefore: null,
2088
2204
  realAfter: null,
2089
- data: child,
2205
+ data,
2090
2206
  tokenizer,
2091
2207
  fragmentSnapshot,
2092
2208
  resumeSnapshot
2093
2209
  };
2094
- this.onePropParsed = createStoreOnePropParsed(child);
2210
+ this.onePropParsed = onePropParsed;
2095
2211
  node.realAfter = this.insertAfterAnchor('component-after');
2096
2212
  return node;
2097
2213
  }
@@ -2274,7 +2390,7 @@
2274
2390
  if (key === 'ref') {
2275
2391
  const valueIsMapKey = Reflect.has(data[aoye.Keys.Raw], value);
2276
2392
  let refValue = _node;
2277
- if (_node.__logicType === FakeType.Component) {
2393
+ if (_node.__logicType & TokenizerSwitcherBit) {
2278
2394
  refValue = _node.data;
2279
2395
  } else {
2280
2396
  refValue[aoye.Keys.ProxyFreeObject] = true;
@@ -2300,8 +2416,8 @@
2300
2416
  } else {
2301
2417
  this.onePropParsed(data, _node, key, value, false, isFn, hookI);
2302
2418
  }
2303
- key = null;
2304
- eq = null;
2419
+ key = undefined;
2420
+ eq = undefined;
2305
2421
  }
2306
2422
  this.tokenizer.nextToken();
2307
2423
  }
@@ -2389,15 +2505,6 @@
2389
2505
  };
2390
2506
  return onePropParsed;
2391
2507
  }
2392
- class InlineFragment {
2393
- [aoye.Keys.ProxyFreeObject] = true;
2394
- constructor(snapshot, data, key, tokenizer) {
2395
- this.snapshot = snapshot;
2396
- this.data = data;
2397
- this.key = key;
2398
- this.tokenizer = tokenizer;
2399
- }
2400
- }
2401
2508
 
2402
2509
  function bobe(fragments, ...values) {
2403
2510
  const ui = function ui(isSub) {
@@ -2410,6 +2517,7 @@
2410
2517
  return tokenizer;
2411
2518
  };
2412
2519
  ui.boundStore = aoye.Store.Current;
2520
+ ui.__BOBE_IS_UI = true;
2413
2521
  return ui;
2414
2522
  }
2415
2523
  function customRender(option) {
@@ -2425,6 +2533,7 @@
2425
2533
  tokenizer
2426
2534
  };
2427
2535
  terp.program(root, componentNode);
2536
+ aoye.flushMicroEffectManual();
2428
2537
  return [componentNode, store];
2429
2538
  };
2430
2539
  }
@@ -2473,6 +2582,7 @@
2473
2582
  get: function () { return aoye.Store; }
2474
2583
  });
2475
2584
  exports.Compiler = Compiler;
2585
+ exports.FakeType = FakeType;
2476
2586
  exports.NodeType = NodeType;
2477
2587
  exports.ParseSyntaxError = ParseSyntaxError;
2478
2588
  exports.Tokenizer = Tokenizer;