bobe 0.0.73 → 0.0.75

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
@@ -70,9 +70,11 @@ declare class Interpreter {
70
70
  private createComponentData;
71
71
  componentOrFragmentDeclaration(ComponentOrRender: UI | typeof Store | InlineFragment, ctx: ProgramCtx): ComponentNode$1;
72
72
  getFn(data: any, expression: string | number): any;
73
+ getBoolFn(data: any, expression: string | number): any;
73
74
  getAssignFn(data: any, expression: string | number): any;
74
75
  condDeclaration(ctx: ProgramCtx): IfNode;
75
76
  removeLogicNode(node: LogicNode): void;
77
+ private skipComponentTypeArguments;
76
78
  /**
77
79
  * 首行属性 + 可选的 pipe 扩展行
78
80
  * <headerLineAndExtensions> ::= <attributeList> NEWLINE (PIPE <attributeList> NEWLINE)*
@@ -178,7 +180,8 @@ declare enum TokenType {
178
180
  Boolean = 4096,
179
181
  Null = 8192,
180
182
  Undefined = 16384,
181
- Comment = 32768
183
+ Comment = 32768,
184
+ TypeArguments = 65536
182
185
  }
183
186
  declare enum FakeType {
184
187
  If = 1,
@@ -209,6 +212,10 @@ type Token = {
209
212
  typeName: string;
210
213
  value: BaseType;
211
214
  loc: SourceLocation;
215
+ typeArguments?: {
216
+ raw: string;
217
+ loc: SourceLocation;
218
+ }[];
212
219
  };
213
220
  type HookProps = {
214
221
  /** 通过哪个 HookId 进入的 */
@@ -247,7 +254,8 @@ declare enum ParseErrorCode {
247
254
  MISSING_FOR_ITEM = 9014,
248
255
  MISSING_COMMENT_SECOND_SLASH = 9015,
249
256
  MISSING_PROP_ASSIGNMENT = 9016,
250
- PIPE_IN_WRONG_CONTEXT = 9017
257
+ PIPE_IN_WRONG_CONTEXT = 9017,
258
+ UNCLOSED_TYPE_ARGUMENTS = 9018
251
259
  }
252
260
  type ParseError = {
253
261
  code: ParseErrorCode;
@@ -434,6 +442,7 @@ declare class Tokenizer {
434
442
  * @returns {boolean} 是否含有 key
435
443
  */
436
444
  jsExp(): Token;
445
+ private typeArguments;
437
446
  peekChar(): string;
438
447
  peekCharIsEol(): boolean;
439
448
  charIsEol(char: string): char is "/" | "\n";
@@ -538,9 +547,15 @@ interface LoopNode extends BaseNode {
538
547
  key?: PropertyValue;
539
548
  children: TemplateNode[];
540
549
  }
550
+ interface TypeArgumentNode extends BaseNode {
551
+ type: NodeType.StaticValue;
552
+ raw: string;
553
+ }
541
554
  interface ComponentNode extends BaseNode {
542
555
  type: NodeType.Component;
543
556
  componentName: PropertyValue;
557
+ typeArguments?: TypeArgumentNode[];
558
+ typeArgumentsLoc?: SourceLocation;
544
559
  props: Property[];
545
560
  children?: TemplateNode[];
546
561
  }
@@ -618,6 +633,7 @@ type ParseHooks = Partial<{
618
633
  [K in keyof ParseProps]: {
619
634
  enter?: (this: Compiler, ...args: Parameters<ParseProps[K]>) => void;
620
635
  leave?: (this: Compiler, ...args: Parameters<ParseProps[K]>) => void;
636
+ nameAdded?: (this: Compiler, ...args: Parameters<ParseProps[K]>) => void;
621
637
  propsAdded?: (this: Compiler, ...args: Parameters<ParseProps[K]>) => void;
622
638
  };
623
639
  }>;
@@ -631,4 +647,4 @@ declare const context: IContext;
631
647
  declare const effect: (callback: (...args: ValueDiff[]) => void, depOrOpt?: Dep[] | Dep | CustomEffectOpt, opt?: CustomEffectOpt) => aoye.Effect;
632
648
 
633
649
  export { Compiler, FakeType, Interpreter, Mw, MwCtx, NodeType, ParseErrorCode, ParseSyntaxError, Tokenizer, bobe, context, customRender, effect };
634
- export type { ASTNodeType, BaseNode, CommentNode, ComponentNode, ConditionalNode, DynamicValue, ElementNode, FragmentNode, IContext, InterpolationNode, LogicNode, LoopNode, ParseError, Program, Property, PropertyKeyNode, PropertyValue, SourceLocation, StaticValue, TemplateNode, TextNode, UI };
650
+ export type { ASTNodeType, BaseNode, CommentNode, ComponentNode, ConditionalNode, DynamicValue, ElementNode, FragmentNode, IContext, InterpolationNode, LogicNode, LoopNode, ParseError, Program, Property, PropertyKeyNode, PropertyValue, SourceLocation, StaticValue, TemplateNode, TextNode, TypeArgumentNode, UI };
package/dist/index.umd.js CHANGED
@@ -21,6 +21,7 @@
21
21
  TokenType[TokenType["Null"] = 8192] = "Null";
22
22
  TokenType[TokenType["Undefined"] = 16384] = "Undefined";
23
23
  TokenType[TokenType["Comment"] = 32768] = "Comment";
24
+ TokenType[TokenType["TypeArguments"] = 65536] = "TypeArguments";
24
25
  return TokenType;
25
26
  }({});
26
27
  const ChildrenSugarType = TokenType.String | TokenType.InsertionExp;
@@ -76,6 +77,7 @@
76
77
  ParseErrorCode[ParseErrorCode["MISSING_COMMENT_SECOND_SLASH"] = 9015] = "MISSING_COMMENT_SECOND_SLASH";
77
78
  ParseErrorCode[ParseErrorCode["MISSING_PROP_ASSIGNMENT"] = 9016] = "MISSING_PROP_ASSIGNMENT";
78
79
  ParseErrorCode[ParseErrorCode["PIPE_IN_WRONG_CONTEXT"] = 9017] = "PIPE_IN_WRONG_CONTEXT";
80
+ ParseErrorCode[ParseErrorCode["UNCLOSED_TYPE_ARGUMENTS"] = 9018] = "UNCLOSED_TYPE_ARGUMENTS";
79
81
  return ParseErrorCode;
80
82
  }({});
81
83
  class ParseSyntaxError extends SyntaxError {
@@ -249,12 +251,13 @@
249
251
  if (!this.token) return false;
250
252
  return this.token.type & TokenType.Identifier && this.token.value === Tokenizer.EofId;
251
253
  }
252
- setToken(type, value, dt = 1) {
254
+ setToken(type, value, dt = 1, extra) {
253
255
  this.token = {
254
256
  type,
255
257
  typeName: TokenType[type],
256
258
  value,
257
- loc: null
259
+ loc: null,
260
+ ...extra
258
261
  };
259
262
  this.isFirstToken = false;
260
263
  }
@@ -308,6 +311,9 @@
308
311
  const braceToken = this.brace();
309
312
  this.setToken(TokenType.InsertionExp, braceToken);
310
313
  break;
314
+ case '<':
315
+ this.typeArguments();
316
+ break;
311
317
  case '$':
312
318
  const handled = this.staticIns();
313
319
  if (handled) break;
@@ -396,6 +402,104 @@
396
402
  this.locEnd();
397
403
  return this.token;
398
404
  }
405
+ typeArguments() {
406
+ const startOffset = this.i;
407
+ const startLine = this.line;
408
+ const startColumn = this.column;
409
+ let angleDepth = 0;
410
+ let braceDepth = 0;
411
+ let bracketDepth = 0;
412
+ let parenDepth = 0;
413
+ let current = '';
414
+ const args = [];
415
+ let argStart = this.i + 1;
416
+ const makeLoc = (start, end) => ({
417
+ start: {
418
+ offset: start,
419
+ line: startLine,
420
+ column: startColumn + (start - startOffset)
421
+ },
422
+ end: {
423
+ offset: end,
424
+ line: startLine,
425
+ column: startColumn + (end - startOffset)
426
+ },
427
+ source: this.code.slice(start, end)
428
+ });
429
+ const pushArg = end => {
430
+ const raw = current.trim();
431
+ if (!raw) return;
432
+ const leading = current.length - current.trimStart().length;
433
+ const trailingEnd = current.trimEnd().length;
434
+ args.push({
435
+ raw,
436
+ loc: makeLoc(argStart + leading, argStart + trailingEnd)
437
+ });
438
+ };
439
+ while (true) {
440
+ const char = this.code[this.i];
441
+ if (char === undefined || char === '\n') {
442
+ throw new ParseSyntaxError(ParseErrorCode.UNCLOSED_TYPE_ARGUMENTS, '未闭合的组件泛型参数', makeLoc(startOffset, this.i));
443
+ }
444
+ if (char === '\'' || char === '"' || char === '`') {
445
+ const quote = char;
446
+ current += char;
447
+ this.next();
448
+ while (true) {
449
+ const inner = this.code[this.i];
450
+ if (inner === undefined || inner === '\n') {
451
+ throw new ParseSyntaxError(ParseErrorCode.UNCLOSED_TYPE_ARGUMENTS, '未闭合的组件泛型参数', makeLoc(startOffset, this.i));
452
+ }
453
+ current += inner;
454
+ if (inner === '\\') {
455
+ this.next();
456
+ current += this.code[this.i] ?? '';
457
+ } else if (inner === quote) {
458
+ break;
459
+ }
460
+ this.next();
461
+ }
462
+ } else if (char === '<') {
463
+ angleDepth++;
464
+ if (angleDepth > 1) current += char;
465
+ } else if (char === '>' && this.code[this.i - 1] !== '=') {
466
+ angleDepth--;
467
+ if (angleDepth === 0) {
468
+ pushArg(this.i);
469
+ this.setToken(TokenType.TypeArguments, this.code.slice(startOffset + 1, this.i), 1, {
470
+ typeArguments: args
471
+ });
472
+ return;
473
+ }
474
+ current += char;
475
+ } else if (char === '{') {
476
+ braceDepth++;
477
+ current += char;
478
+ } else if (char === '}') {
479
+ braceDepth = Math.max(0, braceDepth - 1);
480
+ current += char;
481
+ } else if (char === '[') {
482
+ bracketDepth++;
483
+ current += char;
484
+ } else if (char === ']') {
485
+ bracketDepth = Math.max(0, bracketDepth - 1);
486
+ current += char;
487
+ } else if (char === '(') {
488
+ parenDepth++;
489
+ current += char;
490
+ } else if (char === ')') {
491
+ parenDepth = Math.max(0, parenDepth - 1);
492
+ current += char;
493
+ } else if (char === ',' && angleDepth === 1 && braceDepth === 0 && bracketDepth === 0 && parenDepth === 0) {
494
+ pushArg(this.i);
495
+ current = '';
496
+ argStart = this.i + 1;
497
+ } else {
498
+ current += char;
499
+ }
500
+ this.next();
501
+ }
502
+ }
399
503
  peekChar() {
400
504
  let i = this.i;
401
505
  while (this.code[i] === ' ' || this.code[i] === '\t') {
@@ -1107,8 +1211,19 @@
1107
1211
  parseComponentNode(node) {
1108
1212
  const name = this.parseName();
1109
1213
  this.tokenizer.nextToken();
1214
+ const typeArgumentsToken = this.tokenizer.token.type & TokenType.TypeArguments ? this.tokenizer.token : undefined;
1215
+ if (typeArgumentsToken) {
1216
+ this.tokenizer.nextToken();
1217
+ }
1110
1218
  node.type = NodeType.Component;
1111
1219
  node.componentName = name;
1220
+ node.typeArguments = typeArgumentsToken?.typeArguments?.map(arg => ({
1221
+ type: NodeType.StaticValue,
1222
+ raw: arg.raw,
1223
+ loc: arg.loc
1224
+ }));
1225
+ node.typeArgumentsLoc = typeArgumentsToken?.loc;
1226
+ this.hooks.parseComponentNode?.nameAdded?.call(this, node);
1112
1227
  const props = this.headerLineAndExtensions();
1113
1228
  node.props = props;
1114
1229
  this.hooks.parseComponentNode?.propsAdded?.call(this, node);
@@ -1696,6 +1811,7 @@
1696
1811
  _node = this.createNode(value);
1697
1812
  }
1698
1813
  this.tokenizer.nextToken();
1814
+ this.skipComponentTypeArguments(_node);
1699
1815
  this.headerLineAndExtensions(_node);
1700
1816
  this.onePropParsed = this.oneRealPropParsed;
1701
1817
  if (_node.__logicType & TokenizerSwitcherBit) {
@@ -1749,6 +1865,7 @@
1749
1865
  }, NodeSort.CtxProvider);
1750
1866
  }
1751
1867
  this.tokenizer.nextToken();
1868
+ this.skipComponentTypeArguments(node);
1752
1869
  this.headerLineAndExtensions(node);
1753
1870
  if (isUpdate) {
1754
1871
  this.ctx.stack.pop();
@@ -1778,6 +1895,7 @@
1778
1895
  this.handleInsert(node.realParent, textNode, node.realBefore);
1779
1896
  } else {
1780
1897
  this.tokenizer.nextToken();
1898
+ this.skipComponentTypeArguments(node, true);
1781
1899
  this.headerLineAndExtensions(node);
1782
1900
  const _this$ctx2 = this.ctx,
1783
1901
  realParent = _this$ctx2.realParent,
@@ -2383,6 +2501,11 @@
2383
2501
  getFn(data, expression) {
2384
2502
  return new Function('data', `with(data){return (${expression})}`).bind(undefined, safe(data));
2385
2503
  }
2504
+ getBoolFn(data, expression) {
2505
+ return new Function('data', `with(data){return Boolean(${expression})}`).bind(undefined, safeExclude(data, {
2506
+ 'Boolean': true
2507
+ }));
2508
+ }
2386
2509
  getAssignFn(data, expression) {
2387
2510
  const valueId = `value_bobe_${bobeShared.date32()}`;
2388
2511
  return new Function('data', valueId, `with(data){${expression}=${valueId}};`).bind(undefined, safeExclude(data, {
@@ -2420,11 +2543,9 @@
2420
2543
  switch (keyWord.value) {
2421
2544
  case 'if':
2422
2545
  if (valueIsMapKey) {
2423
- aoye.runWithPulling(() => data[value], null);
2424
- const cells = data[aoye.Keys.Meta].cells;
2425
- signal = cells.get(value);
2546
+ signal = new aoye.Computed(() => Boolean(data[value]));
2426
2547
  } else {
2427
- const fn = this.getFn(data, value);
2548
+ const fn = this.getBoolFn(data, value);
2428
2549
  signal = new aoye.Computed(fn);
2429
2550
  }
2430
2551
  break;
@@ -2444,7 +2565,7 @@
2444
2565
  return true;
2445
2566
  });
2446
2567
  } else {
2447
- const fn = valueIsMapKey ? null : this.getFn(data, value);
2568
+ const fn = valueIsMapKey ? null : this.getBoolFn(data, value);
2448
2569
  signal = new aoye.Computed(() => {
2449
2570
  let point = ifNode.preCond;
2450
2571
  while (point) {
@@ -2456,7 +2577,7 @@
2456
2577
  }
2457
2578
  point = point.preCond;
2458
2579
  }
2459
- return valueIsMapKey ? data[value] : fn();
2580
+ return valueIsMapKey ? Boolean(data[value]) : fn();
2460
2581
  });
2461
2582
  }
2462
2583
  break;
@@ -2513,6 +2634,11 @@
2513
2634
  point = next;
2514
2635
  }
2515
2636
  }
2637
+ skipComponentTypeArguments(node, force = false) {
2638
+ if ((force || node.__logicType & TokenizerSwitcherBit) && this.tokenizer.token.type & TokenType.TypeArguments) {
2639
+ this.tokenizer.nextToken();
2640
+ }
2641
+ }
2516
2642
  headerLineAndExtensions(_node) {
2517
2643
  const tokenizer = this.tokenizer;
2518
2644
  do {
@@ -2872,6 +2998,7 @@
2872
2998
  exports.Mw = Mw;
2873
2999
  exports.MwCtx = MwCtx;
2874
3000
  exports.NodeType = NodeType;
3001
+ exports.ParseErrorCode = ParseErrorCode;
2875
3002
  exports.ParseSyntaxError = ParseSyntaxError;
2876
3003
  exports.Tokenizer = Tokenizer;
2877
3004
  exports.bobe = bobe;