bobe 0.0.8 → 0.0.10

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,5 +1,5 @@
1
1
  import { Queue } from 'bobe-shared';
2
- import { effect, $ } from 'aoye';
2
+ import { Store } from 'aoye';
3
3
 
4
4
  declare enum TokenType {
5
5
  NewLine = 1,
@@ -8,13 +8,17 @@ declare enum TokenType {
8
8
  Identifier = 8,
9
9
  Assign = 16,
10
10
  Pipe = 32,
11
- Eof = 64
11
+ Eof = 64,
12
+ InsertionExp = 128
12
13
  }
13
14
  declare enum LogicType {
14
15
  If = 1,
15
16
  ElseIf = 2,
16
17
  Else = 4,
17
- For = 8
18
+ For = 8,
19
+ Component = 16,
20
+ Fragment = 32,
21
+ Root = 64
18
22
  }
19
23
  type BaseType = string | number | boolean | undefined | null;
20
24
  type Token = {
@@ -30,18 +34,20 @@ type HookProps = {
30
34
  /** 父节点 */
31
35
  parentNode?: any;
32
36
  };
37
+ type TerpConf = Partial<Pick<Terp, 'data' | 'createNode' | 'setProp' | 'hook' | 'HookId' | 'insert'>>;
38
+ type CustomRenderConf = Omit<TerpConf, 'data'>;
33
39
  type Hook = (props: HookProps) => any;
40
+ type HookType = 'dynamic' | 'static';
41
+ /** 返回值是用户自定义的节点 */
42
+ type BobeUI = (this: Store, options: CustomRenderConf, valOpt: TerpConf) => ComponentNode;
34
43
  type StackItem = {
35
44
  /** 表示当前节点子节点已处理完毕 */
36
45
  prevSibling: any;
37
46
  /** 当前节点*/
38
47
  node: any;
39
48
  };
40
- type IfNode = {
41
- __logicType: LogicType;
49
+ type IfNode = LogicNode & {
42
50
  condition: () => any;
43
- directList: any[];
44
- realList: any[];
45
51
  anchor: any;
46
52
  isFirstRender: boolean;
47
53
  snapshot: ReturnType<Tokenizer['snapshot']>;
@@ -49,6 +55,14 @@ type IfNode = {
49
55
  stop: () => void;
50
56
  };
51
57
  };
58
+ type LogicNode = {
59
+ __logicType: LogicType;
60
+ directList?: any[];
61
+ realList: any[];
62
+ };
63
+ type ComponentNode = LogicNode & {
64
+ store: Store;
65
+ };
52
66
 
53
67
  declare class Tokenizer {
54
68
  /** 缩进大小 默认 2 */
@@ -102,6 +116,7 @@ declare class Tokenizer {
102
116
  private assignment;
103
117
  private pipe;
104
118
  private dynamic;
119
+ private brace;
105
120
  private newLine;
106
121
  private getDentValue;
107
122
  private dent;
@@ -111,7 +126,7 @@ declare class Tokenizer {
111
126
  private eof;
112
127
  }
113
128
 
114
- declare class Interpreter {
129
+ declare class Terp {
115
130
  private tokenizer;
116
131
  /** 模板字符串动态节点的占位符 */
117
132
  HookId: string;
@@ -121,7 +136,13 @@ declare class Interpreter {
121
136
  hookI: number;
122
137
  stack: StackItem[];
123
138
  constructor(tokenizer: Tokenizer);
124
- program(): any[];
139
+ program(): ComponentNode;
140
+ /** 处理
141
+ * 是逻辑 是普通
142
+ * 父节点 将子节点们插入到 realList 调用 insert 方法挨个插入子节点
143
+ * 子节点 将其下 realList 插入到父节点 将本节点插入父节点
144
+ */
145
+ handleInsert(parent: any, child: any, prevSibling: any): void;
125
146
  /**
126
147
  * @deprecated
127
148
  * 节点列表:
@@ -144,6 +165,19 @@ declare class Interpreter {
144
165
  * <declaration> ::= <tagName=token> <headerLine> <extensionLines>
145
166
  * */
146
167
  declaration(): any;
168
+ fragmentDeclaration(renderFragment: BobeUI): LogicNode;
169
+ /**
170
+ * key 元素,组件的 key
171
+ * value
172
+ * 1. 静态类型值
173
+ * 2. 插值计算 函数,可以考虑 使用 effect 或 computed 做处理
174
+ *
175
+ * mapKey 映射, 对应子组件的属性
176
+ * */
177
+ onePropParsed(node: any, key: string, value: any, valueIsMapKey: boolean, hookI?: number): void;
178
+ componentDeclaration(Component: typeof Store): {
179
+ __logicType: LogicType;
180
+ };
147
181
  ifDeclaration(): IfNode;
148
182
  /**
149
183
  * <extensionLines> ::= PIPE <attributeList> NEWLINE <extensionLines>
@@ -162,8 +196,9 @@ declare class Interpreter {
162
196
  * <attributeList> ::= <attribute> <attributeList>
163
197
  * | ε
164
198
  *
165
- * <attribute> ::= <key> <=> <value or dataKey> <=> <value>
166
- *
199
+ * <attribute> ::= <key> = <value>
200
+ * 1. 普通节点 执行 setProps 🪝
201
+ * 2. 组件节点 收集映射关系,或通过 effect 直接设值
167
202
  */
168
203
  attributeList(_node: any): void;
169
204
  /** 子节点块:
@@ -172,34 +207,20 @@ declare class Interpreter {
172
207
  * | ε /* 空(表示叶子节点,没有孩子)
173
208
  * */
174
209
  childrenBlockOpt(parent: any): void | any[];
175
- config(opt: Partial<Pick<Interpreter, 'createRoot' | 'createNode' | 'setProp' | 'setDataProp' | 'setChildren' | 'hook' | 'HookId' | 'effect' | 'insert'>>): void;
176
- createData(data: Record<any, any>): Record<any, any>;
177
- setDataProp(data: Record<any, any>, key: any, value: any): any;
178
- setChildren(node: any, children: any[]): void;
210
+ opt: TerpConf;
211
+ config(opt: TerpConf): void;
179
212
  createNode(name: string): {
180
213
  name: string;
181
214
  props: {};
182
215
  };
183
- createRoot(): {
184
- name: string;
185
- props: {};
186
- };
187
- insert(parent: any, node: any, prevSibling: any, prevItem?: any): {
188
- value: any;
189
- next: any;
190
- };
191
- defaultInsert(parent: any, node: any, prevSibling: any, prevItem: any): {
192
- value: any;
193
- next: any;
194
- };
216
+ insert(parent: any, node: any, prevSibling: any, prevItem?: any): void;
217
+ defaultInsert(parent: any, node: any, prevSibling: any, prevItem: any): void;
195
218
  remove(parent: any, node: any, prevSibling: any, prevItem: any): void;
196
219
  defaultRemove(parent: any, node: any, prevSibling: any, prevItem: any): void;
197
220
  setProp(node: any, key: string, value: any, hookI?: number): void;
198
- effect: typeof effect;
199
- signal: typeof $;
200
221
  init(fragments: string | string[]): void;
201
222
  hook: Hook;
202
- _hook: (props: Partial<HookProps>) => [boolean, any];
223
+ _hook: (props: Partial<HookProps>) => [HookType | undefined, any];
203
224
  }
204
225
 
205
- export { Interpreter };
226
+ export { Terp };
package/dist/index.umd.js CHANGED
@@ -1,8 +1,8 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3
- typeof define === 'function' && define.amd ? define(['exports'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Bobe = {}));
5
- })(this, (function (exports) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('aoye'), require('bobe-shared')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'aoye', 'bobe-shared'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Bobe = {}, global.Aoye, global.BobeShared));
5
+ })(this, (function (exports, aoye, bobeShared) { 'use strict';
6
6
 
7
7
  var TokenType = /* @__PURE__ */ ((TokenType2) => {
8
8
  TokenType2[TokenType2["NewLine"] = 1] = "NewLine";
@@ -12,6 +12,7 @@
12
12
  TokenType2[TokenType2["Assign"] = 16] = "Assign";
13
13
  TokenType2[TokenType2["Pipe"] = 32] = "Pipe";
14
14
  TokenType2[TokenType2["Eof"] = 64] = "Eof";
15
+ TokenType2[TokenType2["InsertionExp"] = 128] = "InsertionExp";
15
16
  return TokenType2;
16
17
  })(TokenType || {});
17
18
  var LogicType = /* @__PURE__ */ ((LogicType2) => {
@@ -19,8 +20,16 @@
19
20
  LogicType2[LogicType2["ElseIf"] = 2] = "ElseIf";
20
21
  LogicType2[LogicType2["Else"] = 4] = "Else";
21
22
  LogicType2[LogicType2["For"] = 8] = "For";
23
+ LogicType2[LogicType2["Component"] = 16] = "Component";
24
+ LogicType2[LogicType2["Fragment"] = 32] = "Fragment";
25
+ LogicType2[LogicType2["Root"] = 64] = "Root";
22
26
  return LogicType2;
23
27
  })(LogicType || {});
28
+ var TerpEvt = /* @__PURE__ */ ((TerpEvt2) => {
29
+ TerpEvt2["AllAttrGot"] = "all-attr-got";
30
+ TerpEvt2["HandledComponentNode"] = "handled-component-node";
31
+ return TerpEvt2;
32
+ })(TerpEvt || {});
24
33
 
25
34
  var __defProp = Object.defineProperty;
26
35
  var __defProps = Object.defineProperties;
@@ -41,7 +50,8 @@
41
50
  return a;
42
51
  };
43
52
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
44
- class Interpreter {
53
+ const tap = new bobeShared.BaseEvent();
54
+ class Terp {
45
55
  constructor(tokenizer) {
46
56
  this.tokenizer = tokenizer;
47
57
  /** 模板字符串动态节点的占位符 */
@@ -53,27 +63,41 @@
53
63
  this.stack = [];
54
64
  this._hook = (props) => {
55
65
  const value = this.tokenizer.token.value;
56
- const isHook = typeof value === "string" && value.indexOf(this.HookId) === 0;
57
- if (this.hook && isHook) {
66
+ const isDynamicHook = this.tokenizer.token.type & TokenType.InsertionExp;
67
+ const isStaticHook = typeof value === "string" && value.indexOf(this.HookId) === 0;
68
+ const hookType = isDynamicHook ? "dynamic" : isStaticHook ? "static" : void 0;
69
+ if (this.hook && isStaticHook) {
58
70
  const hookI = Number(value.slice(this.HookId.length));
59
71
  const res = this.hook(__spreadProps(__spreadValues({}, props), {
60
72
  HookId: this.HookId,
61
73
  i: hookI
62
74
  }));
63
75
  this.hookI++;
64
- return [isHook, res];
76
+ return [hookType, res];
77
+ } else if (isDynamicHook) {
78
+ return [hookType, value];
65
79
  }
66
- return [isHook, value];
80
+ return [hookType, value];
67
81
  };
68
82
  }
83
+ // /** program 要挂载的父节点位置 */
84
+ // root: any;
85
+ // /** program 挂载的前置节点 */
86
+ // anchor: any;
69
87
  program() {
88
+ const root = {
89
+ __logicType: LogicType.Component,
90
+ store: this.data,
91
+ realList: [],
92
+ directList: []
93
+ };
70
94
  this.tokenizer.consume();
71
95
  let current;
72
96
  let prevSibling;
73
- const rootList = [];
97
+ this.stack = [{ node: root, prevSibling }];
74
98
  while (1) {
75
99
  if (this.tokenizer.isEof()) {
76
- rootList.push(current);
100
+ this.handleInsert(root, current, root.realList[root.realList.length - 1]);
77
101
  break;
78
102
  }
79
103
  const token = this.tokenizer.token;
@@ -88,11 +112,11 @@
88
112
  continue;
89
113
  }
90
114
  if (current) {
91
- if (this.stack.length) {
115
+ if (this.stack.length > 1) {
92
116
  const parent = this.stack[this.stack.length - 1].node;
93
- this.insert(parent, current, prevSibling);
117
+ this.handleInsert(parent, current, prevSibling);
94
118
  } else {
95
- rootList.push(current);
119
+ this.handleInsert(root, current, prevSibling);
96
120
  }
97
121
  }
98
122
  if (this.tokenizer.token.type & TokenType.Dedent) {
@@ -105,7 +129,29 @@
105
129
  current = this.declaration();
106
130
  }
107
131
  }
108
- return rootList;
132
+ return root;
133
+ }
134
+ /** 处理
135
+ * 是逻辑 是普通
136
+ * 父节点 将子节点们插入到 realList 调用 insert 方法挨个插入子节点
137
+ * 子节点 将其下 realList 插入到父节点 将本节点插入父节点
138
+ */
139
+ handleInsert(parent, child, prevSibling) {
140
+ let insertFn = this.insert.bind(this);
141
+ if (parent.__logicType) {
142
+ insertFn = (parent2, child2, prevSibling2) => {
143
+ parent2.realList.splice(parent2.realList.indexOf(prevSibling2) + 1, 0, child2);
144
+ };
145
+ }
146
+ if (child.__logicType) {
147
+ const realList = child.realList;
148
+ for (let i = realList.length; i--; ) {
149
+ const item = realList[i];
150
+ insertFn(parent, item, prevSibling);
151
+ }
152
+ } else {
153
+ insertFn(parent, child, prevSibling);
154
+ }
109
155
  }
110
156
  /**
111
157
  * @deprecated
@@ -186,21 +232,91 @@
186
232
  * <declaration> ::= <tagName=token> <headerLine> <extensionLines>
187
233
  * */
188
234
  declaration() {
189
- const [isHook, value] = this._hook({});
235
+ const [hookType, value] = this._hook({});
190
236
  let _node;
191
- if (isHook) {
192
- const { tree, data } = value();
193
- _node = tree;
194
- } else if (value === "if") {
237
+ if (value === "if") {
195
238
  return this.ifDeclaration();
239
+ } else if (hookType) {
240
+ if (hookType === "static") {
241
+ if (typeof value === "function" && value.prototype instanceof aoye.Store) {
242
+ _node = this.componentDeclaration(value);
243
+ } else if (typeof value === "function") {
244
+ _node = this.fragmentDeclaration(value);
245
+ } else {
246
+ throw new SyntaxError(`declaration \u4E0D\u652F\u6301 ${value} \u7C7B\u578B\u7684\u9759\u6001\u63D2\u503C`);
247
+ }
248
+ } else {
249
+ Boolean(this.data[aoye.Keys.Raw][value]);
250
+ new Function("data", `let v;with(data){v=(${value})};return v`);
251
+ _node = this.createNode(value);
252
+ }
196
253
  } else {
197
254
  _node = this.createNode(value);
198
255
  }
199
256
  this.tokenizer.consume();
200
257
  this.headerLine(_node);
201
258
  this.extensionLines(_node);
259
+ if (_node.__logicType === LogicType.Component) {
260
+ tap.once(TerpEvt.HandledComponentNode, (node) => _node = node);
261
+ tap.emit(TerpEvt.AllAttrGot);
262
+ }
202
263
  return _node;
203
264
  }
265
+ // TODO: 指定挂载位置
266
+ fragmentDeclaration(renderFragment) {
267
+ const fragmentNode = {
268
+ __logicType: LogicType.Fragment,
269
+ directList: [],
270
+ realList: []
271
+ };
272
+ renderFragment.call(this.data, this.opt, { data: this.data, root: "", anchor: "" });
273
+ return fragmentNode;
274
+ }
275
+ /**
276
+ * key 元素,组件的 key
277
+ * value
278
+ * 1. 静态类型值
279
+ * 2. 插值计算 函数,可以考虑 使用 effect 或 computed 做处理
280
+ *
281
+ * mapKey 映射, 对应子组件的属性
282
+ * */
283
+ onePropParsed(node, key, value, valueIsMapKey, hookI) {
284
+ if (typeof value === "function") {
285
+ aoye.effect(() => {
286
+ const res = value();
287
+ this.setProp(node, key, res, hookI);
288
+ });
289
+ } else if (valueIsMapKey) {
290
+ aoye.effect(() => {
291
+ const res = this.data[value];
292
+ this.setProp(node, key, res, hookI);
293
+ });
294
+ } else {
295
+ this.setProp(node, key, value, hookI);
296
+ }
297
+ }
298
+ componentDeclaration(Component) {
299
+ const child = Component.new();
300
+ const prevOnePropParsed = this.onePropParsed;
301
+ this.onePropParsed = (node, key, value, valueIsMapKey, hookI) => {
302
+ if (valueIsMapKey) {
303
+ aoye.shareSignal(this.data, value, child, key);
304
+ } else if (typeof value === "function") {
305
+ const meta = child[aoye.Keys.Meta];
306
+ const cells = meta.cells;
307
+ const computed = aoye.$(value);
308
+ cells.set(key, computed);
309
+ } else {
310
+ child[aoye.Keys.Raw][key] = value;
311
+ }
312
+ };
313
+ tap.once(TerpEvt.AllAttrGot, () => {
314
+ this.onePropParsed = prevOnePropParsed;
315
+ const root = child["ui"](this.opt, { data: child });
316
+ tap.emit(TerpEvt.HandledComponentNode, root);
317
+ });
318
+ return { __logicType: LogicType.Component };
319
+ }
204
320
  ifDeclaration() {
205
321
  this.tokenizer.consume();
206
322
  const [isHook, value] = this._hook({});
@@ -214,7 +330,7 @@
214
330
  watcher: null,
215
331
  anchor: null
216
332
  };
217
- ifNode.watcher = this.effect(
333
+ ifNode.watcher = aoye.effect(
218
334
  ({ val }) => {
219
335
  if (val) {
220
336
  this.tokenizer.consume();
@@ -259,44 +375,32 @@
259
375
  * <attributeList> ::= <attribute> <attributeList>
260
376
  * | ε
261
377
  *
262
- * <attribute> ::= <key> <=> <value or dataKey> <=> <value>
263
- *
378
+ * <attribute> ::= <key> = <value>
379
+ * 1. 普通节点 执行 setProps 🪝
380
+ * 2. 组件节点 收集映射关系,或通过 effect 直接设值
264
381
  */
265
382
  attributeList(_node) {
266
- let values = [];
267
- let prevToken = void 0;
268
- while (1) {
269
- if ((prevToken == null ? void 0 : prevToken.type) === TokenType.Identifier && this.tokenizer.token.type !== TokenType.Assign) {
270
- const [v1, v2, v3] = values;
271
- const key = v1;
272
- let dataKey, defaultVal;
273
- if (v3 !== void 0) {
274
- defaultVal = v3;
275
- dataKey = v2;
276
- } else if (v2 !== void 0) {
277
- if (typeof v2 === "string" && v2[0] === "$" && v2[1] !== "{") {
278
- dataKey = v2.slice(1);
279
- } else {
280
- defaultVal = v2;
281
- }
383
+ let key, eq;
384
+ while (!(this.tokenizer.token.type & TokenType.NewLine)) {
385
+ if (key == null) {
386
+ key = this.tokenizer.token.value;
387
+ } else if (eq == null) {
388
+ eq = "=";
389
+ } else {
390
+ const [hookType, value] = this._hook({});
391
+ if (hookType === "dynamic") {
392
+ const valueIsMapKey = Reflect.has(this.data[aoye.Keys.Raw], value);
393
+ const fn = valueIsMapKey ? value : new Function("data", `let v;with(data){v=${value}};return v;`).bind(void 0, this.data);
394
+ this.onePropParsed(_node, key, fn, valueIsMapKey, this.hookI);
395
+ } else if (hookType === "static") {
396
+ this.onePropParsed(_node, key, value, false, this.hookI);
282
397
  } else {
283
- dataKey = key;
284
- }
285
- let val = defaultVal;
286
- if (dataKey) {
287
- val = this.setDataProp(this.data, dataKey, defaultVal);
398
+ this.onePropParsed(_node, key, value, false, this.hookI);
288
399
  }
289
- this.setProp(_node, key, val, this.hookI - 1);
290
- const [isHook, value] = this._hook({});
291
- values = [value];
292
- } else if (this.tokenizer.token.type !== TokenType.Assign) {
293
- const [isHook, value] = this._hook({});
294
- values.push(value);
295
- }
296
- if (!(this.tokenizer.token.type & (TokenType.Identifier | TokenType.Assign))) {
297
- break;
400
+ key = null;
401
+ eq = null;
298
402
  }
299
- prevToken = this.tokenizer.consume();
403
+ this.tokenizer.consume();
300
404
  }
301
405
  }
302
406
  /** 子节点块:
@@ -314,15 +418,7 @@
314
418
  }
315
419
  config(opt) {
316
420
  Object.assign(this, opt);
317
- }
318
- createData(data) {
319
- return data;
320
- }
321
- setDataProp(data, key, value) {
322
- return data[key] = value;
323
- }
324
- setChildren(node, children) {
325
- node.children = children;
421
+ this.opt = opt;
326
422
  }
327
423
  createNode(name) {
328
424
  return {
@@ -330,59 +426,31 @@
330
426
  props: {}
331
427
  };
332
428
  }
333
- createRoot() {
334
- return this.createNode("root");
335
- }
336
429
  insert(parent, node, prevSibling, prevItem) {
337
430
  return this.defaultInsert(parent, node, prevSibling, prevItem);
338
431
  }
339
432
  defaultInsert(parent, node, prevSibling, prevItem) {
340
- if (!parent.child) {
341
- return parent.child = parent.lastChild = {
342
- value: node,
343
- next: null
344
- };
345
- }
346
- const nextItem = prevItem.next;
347
- const item = {
348
- value: node,
349
- next: nextItem
350
- };
351
- prevItem.next = item;
352
- if (!nextItem) {
353
- parent.lastChild = item;
433
+ if (prevSibling) {
434
+ const children = parent.children;
435
+ const insertI = children.findIndex((item) => item === prevSibling);
436
+ children.splice(insertI + 1, 0, node);
437
+ } else {
438
+ parent.children = [node];
354
439
  }
355
- return item;
356
440
  }
357
441
  remove(parent, node, prevSibling, prevItem) {
358
442
  return this.defaultRemove(parent, node, prevSibling, prevItem);
359
443
  }
360
444
  // TODO: 默认改成 prevItem
361
445
  defaultRemove(parent, node, prevSibling, prevItem) {
362
- const currItem = prevItem.next;
363
- const nextItem = currItem.next;
364
- if (prevItem) {
365
- if (nextItem) {
366
- prevItem.next = nextItem;
367
- } else {
368
- prevItem.next = null;
369
- parent.lastChild = prevItem;
370
- }
371
- } else {
372
- if (nextItem) {
373
- parent.child = nextItem;
374
- } else {
375
- parent.child = null;
376
- parent.lastChild = null;
377
- }
446
+ if (parent.children) {
447
+ parent.children.splice(parent.children.indexOf(node), 1);
378
448
  }
379
- currItem.next = null;
380
449
  }
381
450
  setProp(node, key, value, hookI) {
382
451
  node.props[key] = value;
383
452
  }
384
453
  init(fragments) {
385
- this.data = this.createData(this.data);
386
454
  if (typeof fragments === "string") {
387
455
  this.tokenizer.setCode(fragments);
388
456
  } else {
@@ -396,7 +464,7 @@
396
464
  }
397
465
  }
398
466
 
399
- exports.Interpreter = Interpreter;
467
+ exports.Terp = Terp;
400
468
 
401
469
  }));
402
470
  //# sourceMappingURL=index.umd.js.map