bobe 0.0.72 → 0.0.74

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
@@ -73,6 +73,7 @@ declare class Interpreter {
73
73
  getAssignFn(data: any, expression: string | number): any;
74
74
  condDeclaration(ctx: ProgramCtx): IfNode;
75
75
  removeLogicNode(node: LogicNode): void;
76
+ private skipComponentTypeArguments;
76
77
  /**
77
78
  * 首行属性 + 可选的 pipe 扩展行
78
79
  * <headerLineAndExtensions> ::= <attributeList> NEWLINE (PIPE <attributeList> NEWLINE)*
@@ -178,7 +179,8 @@ declare enum TokenType {
178
179
  Boolean = 4096,
179
180
  Null = 8192,
180
181
  Undefined = 16384,
181
- Comment = 32768
182
+ Comment = 32768,
183
+ TypeArguments = 65536
182
184
  }
183
185
  declare enum FakeType {
184
186
  If = 1,
@@ -209,6 +211,10 @@ type Token = {
209
211
  typeName: string;
210
212
  value: BaseType;
211
213
  loc: SourceLocation;
214
+ typeArguments?: {
215
+ raw: string;
216
+ loc: SourceLocation;
217
+ }[];
212
218
  };
213
219
  type HookProps = {
214
220
  /** 通过哪个 HookId 进入的 */
@@ -247,7 +253,8 @@ declare enum ParseErrorCode {
247
253
  MISSING_FOR_ITEM = 9014,
248
254
  MISSING_COMMENT_SECOND_SLASH = 9015,
249
255
  MISSING_PROP_ASSIGNMENT = 9016,
250
- PIPE_IN_WRONG_CONTEXT = 9017
256
+ PIPE_IN_WRONG_CONTEXT = 9017,
257
+ UNCLOSED_TYPE_ARGUMENTS = 9018
251
258
  }
252
259
  type ParseError = {
253
260
  code: ParseErrorCode;
@@ -356,7 +363,10 @@ type ComponentNode$1 = LogicNode & {
356
363
  type Dep = (() => any) | string;
357
364
  type RenderWithMw = {
358
365
  use: Mw['use'];
359
- <T extends typeof Store>(Ctor: T, root: any): [ComponentNode$1, InstanceType<T>];
366
+ <T extends typeof Store>(Ctor: T, root: any, options?: RenderOptions<T>): [ComponentNode$1, InstanceType<T>];
367
+ };
368
+ type RenderOptions<T extends typeof Store> = {
369
+ props?: Partial<Omit<InstanceType<T>, 'ui' | 'parent'>>;
360
370
  };
361
371
 
362
372
  declare class Tokenizer {
@@ -431,6 +441,7 @@ declare class Tokenizer {
431
441
  * @returns {boolean} 是否含有 key
432
442
  */
433
443
  jsExp(): Token;
444
+ private typeArguments;
434
445
  peekChar(): string;
435
446
  peekCharIsEol(): boolean;
436
447
  charIsEol(char: string): char is "/" | "\n";
@@ -535,9 +546,15 @@ interface LoopNode extends BaseNode {
535
546
  key?: PropertyValue;
536
547
  children: TemplateNode[];
537
548
  }
549
+ interface TypeArgumentNode extends BaseNode {
550
+ type: NodeType.StaticValue;
551
+ raw: string;
552
+ }
538
553
  interface ComponentNode extends BaseNode {
539
554
  type: NodeType.Component;
540
555
  componentName: PropertyValue;
556
+ typeArguments?: TypeArgumentNode[];
557
+ typeArgumentsLoc?: SourceLocation;
541
558
  props: Property[];
542
559
  children?: TemplateNode[];
543
560
  }
@@ -615,6 +632,7 @@ type ParseHooks = Partial<{
615
632
  [K in keyof ParseProps]: {
616
633
  enter?: (this: Compiler, ...args: Parameters<ParseProps[K]>) => void;
617
634
  leave?: (this: Compiler, ...args: Parameters<ParseProps[K]>) => void;
635
+ nameAdded?: (this: Compiler, ...args: Parameters<ParseProps[K]>) => void;
618
636
  propsAdded?: (this: Compiler, ...args: Parameters<ParseProps[K]>) => void;
619
637
  };
620
638
  }>;
@@ -628,4 +646,4 @@ declare const context: IContext;
628
646
  declare const effect: (callback: (...args: ValueDiff[]) => void, depOrOpt?: Dep[] | Dep | CustomEffectOpt, opt?: CustomEffectOpt) => aoye.Effect;
629
647
 
630
648
  export { Compiler, FakeType, Interpreter, Mw, MwCtx, NodeType, ParseErrorCode, ParseSyntaxError, Tokenizer, bobe, context, customRender, effect };
631
- export type { ASTNodeType, BaseNode, CommentNode, ComponentNode, ConditionalNode, DynamicValue, ElementNode, FragmentNode, IContext, InterpolationNode, LogicNode, LoopNode, ParseError, Program, Property, PropertyKeyNode, PropertyValue, SourceLocation, StaticValue, TemplateNode, TextNode, UI };
649
+ 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,
@@ -2513,6 +2631,11 @@
2513
2631
  point = next;
2514
2632
  }
2515
2633
  }
2634
+ skipComponentTypeArguments(node, force = false) {
2635
+ if ((force || node.__logicType & TokenizerSwitcherBit) && this.tokenizer.token.type & TokenType.TypeArguments) {
2636
+ this.tokenizer.nextToken();
2637
+ }
2638
+ }
2516
2639
  headerLineAndExtensions(_node) {
2517
2640
  const tokenizer = this.tokenizer;
2518
2641
  do {
@@ -2744,8 +2867,11 @@
2744
2867
  }
2745
2868
  function customRender(option) {
2746
2869
  const mw = new Mw();
2747
- function render(Ctor, root) {
2870
+ function render(Ctor, root, options = {}) {
2748
2871
  const store = Ctor.new();
2872
+ if (options.props) {
2873
+ Object.assign(store, options.props);
2874
+ }
2749
2875
  const tokenizer = store.ui(false);
2750
2876
  const terp = new Interpreter(tokenizer);
2751
2877
  terp.config(option);
@@ -2869,6 +2995,7 @@
2869
2995
  exports.Mw = Mw;
2870
2996
  exports.MwCtx = MwCtx;
2871
2997
  exports.NodeType = NodeType;
2998
+ exports.ParseErrorCode = ParseErrorCode;
2872
2999
  exports.ParseSyntaxError = ParseSyntaxError;
2873
3000
  exports.Tokenizer = Tokenizer;
2874
3001
  exports.bobe = bobe;