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.
@@ -20,6 +20,7 @@ let TokenType = function (TokenType) {
20
20
  TokenType[TokenType["Null"] = 8192] = "Null";
21
21
  TokenType[TokenType["Undefined"] = 16384] = "Undefined";
22
22
  TokenType[TokenType["Comment"] = 32768] = "Comment";
23
+ TokenType[TokenType["TypeArguments"] = 65536] = "TypeArguments";
23
24
  return TokenType;
24
25
  }({});
25
26
  const ChildrenSugarType = TokenType.String | TokenType.InsertionExp | TokenType.StaticInsExp ;
@@ -75,6 +76,7 @@ let ParseErrorCode = function (ParseErrorCode) {
75
76
  ParseErrorCode[ParseErrorCode["MISSING_COMMENT_SECOND_SLASH"] = 9015] = "MISSING_COMMENT_SECOND_SLASH";
76
77
  ParseErrorCode[ParseErrorCode["MISSING_PROP_ASSIGNMENT"] = 9016] = "MISSING_PROP_ASSIGNMENT";
77
78
  ParseErrorCode[ParseErrorCode["PIPE_IN_WRONG_CONTEXT"] = 9017] = "PIPE_IN_WRONG_CONTEXT";
79
+ ParseErrorCode[ParseErrorCode["UNCLOSED_TYPE_ARGUMENTS"] = 9018] = "UNCLOSED_TYPE_ARGUMENTS";
78
80
  return ParseErrorCode;
79
81
  }({});
80
82
  class ParseSyntaxError extends SyntaxError {
@@ -257,7 +259,7 @@ class Tokenizer {
257
259
  if (!this.token) return false;
258
260
  return this.token.type & TokenType.Identifier && this.token.value === Tokenizer.EofId;
259
261
  }
260
- setToken(type, value, dt = 1) {
262
+ setToken(type, value, dt = 1, extra) {
261
263
  this.token = {
262
264
  type,
263
265
  typeName: TokenType[type],
@@ -274,7 +276,8 @@ class Tokenizer {
274
276
  column: this.column + dt
275
277
  },
276
278
  source: this.code.slice(this.preI, this.i + dt)
277
- } : null
279
+ } : null,
280
+ ...extra
278
281
  };
279
282
  this.isFirstToken = false;
280
283
  }
@@ -328,6 +331,9 @@ class Tokenizer {
328
331
  const braceToken = this.brace();
329
332
  this.setToken(TokenType.InsertionExp, braceToken);
330
333
  break;
334
+ case '<':
335
+ this.typeArguments();
336
+ break;
331
337
  case '$':
332
338
  const handled = this.staticIns();
333
339
  if (handled) break;
@@ -424,6 +430,104 @@ class Tokenizer {
424
430
  this.locEnd();
425
431
  return this.token;
426
432
  }
433
+ typeArguments() {
434
+ const startOffset = this.i;
435
+ const startLine = this.line;
436
+ const startColumn = this.column;
437
+ let angleDepth = 0;
438
+ let braceDepth = 0;
439
+ let bracketDepth = 0;
440
+ let parenDepth = 0;
441
+ let current = '';
442
+ const args = [];
443
+ let argStart = this.i + 1;
444
+ const makeLoc = (start, end) => ({
445
+ start: {
446
+ offset: start,
447
+ line: startLine,
448
+ column: startColumn + (start - startOffset)
449
+ },
450
+ end: {
451
+ offset: end,
452
+ line: startLine,
453
+ column: startColumn + (end - startOffset)
454
+ },
455
+ source: this.code.slice(start, end)
456
+ });
457
+ const pushArg = end => {
458
+ const raw = current.trim();
459
+ if (!raw) return;
460
+ const leading = current.length - current.trimStart().length;
461
+ const trailingEnd = current.trimEnd().length;
462
+ args.push({
463
+ raw,
464
+ loc: makeLoc(argStart + leading, argStart + trailingEnd)
465
+ });
466
+ };
467
+ while (true) {
468
+ const char = this.code[this.i];
469
+ if (char === undefined || char === '\n') {
470
+ throw new ParseSyntaxError(ParseErrorCode.UNCLOSED_TYPE_ARGUMENTS, '未闭合的组件泛型参数', makeLoc(startOffset, this.i));
471
+ }
472
+ if (char === '\'' || char === '"' || char === '`') {
473
+ const quote = char;
474
+ current += char;
475
+ this.next();
476
+ while (true) {
477
+ const inner = this.code[this.i];
478
+ if (inner === undefined || inner === '\n') {
479
+ throw new ParseSyntaxError(ParseErrorCode.UNCLOSED_TYPE_ARGUMENTS, '未闭合的组件泛型参数', makeLoc(startOffset, this.i));
480
+ }
481
+ current += inner;
482
+ if (inner === '\\') {
483
+ this.next();
484
+ current += this.code[this.i] ?? '';
485
+ } else if (inner === quote) {
486
+ break;
487
+ }
488
+ this.next();
489
+ }
490
+ } else if (char === '<') {
491
+ angleDepth++;
492
+ if (angleDepth > 1) current += char;
493
+ } else if (char === '>' && this.code[this.i - 1] !== '=') {
494
+ angleDepth--;
495
+ if (angleDepth === 0) {
496
+ pushArg(this.i);
497
+ this.setToken(TokenType.TypeArguments, this.code.slice(startOffset + 1, this.i), 1, {
498
+ typeArguments: args
499
+ });
500
+ return;
501
+ }
502
+ current += char;
503
+ } else if (char === '{') {
504
+ braceDepth++;
505
+ current += char;
506
+ } else if (char === '}') {
507
+ braceDepth = Math.max(0, braceDepth - 1);
508
+ current += char;
509
+ } else if (char === '[') {
510
+ bracketDepth++;
511
+ current += char;
512
+ } else if (char === ']') {
513
+ bracketDepth = Math.max(0, bracketDepth - 1);
514
+ current += char;
515
+ } else if (char === '(') {
516
+ parenDepth++;
517
+ current += char;
518
+ } else if (char === ')') {
519
+ parenDepth = Math.max(0, parenDepth - 1);
520
+ current += char;
521
+ } else if (char === ',' && angleDepth === 1 && braceDepth === 0 && bracketDepth === 0 && parenDepth === 0) {
522
+ pushArg(this.i);
523
+ current = '';
524
+ argStart = this.i + 1;
525
+ } else {
526
+ current += char;
527
+ }
528
+ this.next();
529
+ }
530
+ }
427
531
  peekChar() {
428
532
  let i = this.i;
429
533
  while (this.code[i] === ' ' || this.code[i] === '\t') {
@@ -1133,8 +1237,19 @@ class Compiler {
1133
1237
  parseComponentNode(node) {
1134
1238
  const name = this.parseName();
1135
1239
  this.tokenizer.nextToken();
1240
+ const typeArgumentsToken = this.tokenizer.token.type & TokenType.TypeArguments ? this.tokenizer.token : undefined;
1241
+ if (typeArgumentsToken) {
1242
+ this.tokenizer.nextToken();
1243
+ }
1136
1244
  node.type = NodeType.Component;
1137
1245
  node.componentName = name;
1246
+ node.typeArguments = typeArgumentsToken?.typeArguments?.map(arg => ({
1247
+ type: NodeType.StaticValue,
1248
+ raw: arg.raw,
1249
+ loc: arg.loc
1250
+ }));
1251
+ node.typeArgumentsLoc = typeArgumentsToken?.loc;
1252
+ this.hooks.parseComponentNode?.nameAdded?.call(this, node);
1138
1253
  const props = this.headerLineAndExtensions();
1139
1254
  node.props = props;
1140
1255
  this.hooks.parseComponentNode?.propsAdded?.call(this, node);
@@ -1722,6 +1837,7 @@ class Interpreter {
1722
1837
  _node = this.createNode(value);
1723
1838
  }
1724
1839
  this.tokenizer.nextToken();
1840
+ this.skipComponentTypeArguments(_node);
1725
1841
  this.headerLineAndExtensions(_node);
1726
1842
  this.onePropParsed = this.oneRealPropParsed;
1727
1843
  if (_node.__logicType & TokenizerSwitcherBit) {
@@ -1775,6 +1891,7 @@ class Interpreter {
1775
1891
  }, NodeSort.CtxProvider);
1776
1892
  }
1777
1893
  this.tokenizer.nextToken();
1894
+ this.skipComponentTypeArguments(node);
1778
1895
  this.headerLineAndExtensions(node);
1779
1896
  if (isUpdate) {
1780
1897
  this.ctx.stack.pop();
@@ -1804,6 +1921,7 @@ class Interpreter {
1804
1921
  this.handleInsert(node.realParent, textNode, node.realBefore);
1805
1922
  } else {
1806
1923
  this.tokenizer.nextToken();
1924
+ this.skipComponentTypeArguments(node, true);
1807
1925
  this.headerLineAndExtensions(node);
1808
1926
  const _this$ctx2 = this.ctx,
1809
1927
  realParent = _this$ctx2.realParent,
@@ -2539,6 +2657,11 @@ class Interpreter {
2539
2657
  point = next;
2540
2658
  }
2541
2659
  }
2660
+ skipComponentTypeArguments(node, force = false) {
2661
+ if ((force || node.__logicType & TokenizerSwitcherBit) && this.tokenizer.token.type & TokenType.TypeArguments) {
2662
+ this.tokenizer.nextToken();
2663
+ }
2664
+ }
2542
2665
  headerLineAndExtensions(_node) {
2543
2666
  const tokenizer = this.tokenizer;
2544
2667
  do {
@@ -2770,8 +2893,11 @@ function bobe(fragments, ...values) {
2770
2893
  }
2771
2894
  function customRender(option) {
2772
2895
  const mw = new Mw();
2773
- function render(Ctor, root) {
2896
+ function render(Ctor, root, options = {}) {
2774
2897
  const store = Ctor.new();
2898
+ if (options.props) {
2899
+ Object.assign(store, options.props);
2900
+ }
2775
2901
  const tokenizer = store.ui(false);
2776
2902
  const terp = new Interpreter(tokenizer);
2777
2903
  terp.config(option);
@@ -2895,6 +3021,7 @@ exports.Interpreter = Interpreter;
2895
3021
  exports.Mw = Mw;
2896
3022
  exports.MwCtx = MwCtx;
2897
3023
  exports.NodeType = NodeType;
3024
+ exports.ParseErrorCode = ParseErrorCode;
2898
3025
  exports.ParseSyntaxError = ParseSyntaxError;
2899
3026
  exports.Tokenizer = Tokenizer;
2900
3027
  exports.bobe = bobe;