bobe 0.0.36 → 0.0.37

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
@@ -174,7 +174,22 @@ type TerpConf = Partial<Pick<Interpreter, 'createNode' | 'setProp' | 'insertAfte
174
174
  type CustomRenderConf = Pick<TerpConf, 'createNode' | 'setProp' | 'insertAfter' | 'remove' | 'createAnchor' | 'firstChild' | 'nextSib'>;
175
175
  type Hook = (props: HookProps) => any;
176
176
  type HookType = 'dynamic' | 'static';
177
- type ParseErrorCode = 'UNCLOSED_BRACE' | 'UNCLOSED_STRING' | 'UNCLOSED_STATIC_INS' | 'INCONSISTENT_INDENT' | 'INDENT_MISMATCH' | 'MISSING_ASSIGN' | 'INVALID_TAG_NAME' | 'ELSE_WITHOUT_IF' | 'EMPTY_IF_BODY' | 'EMPTY_FOR_BODY' | 'MISSING_FOR_COLLECTION' | 'MISSING_FOR_SEMICOLON' | 'MISSING_FOR_ITEM' | 'PIPE_IN_WRONG_CONTEXT';
177
+ declare enum ParseErrorCode {
178
+ UNCLOSED_BRACE = 9001,
179
+ UNCLOSED_STRING = 9002,
180
+ UNCLOSED_STATIC_INS = 9003,
181
+ INCONSISTENT_INDENT = 9004,
182
+ INDENT_MISMATCH = 9005,
183
+ MISSING_ASSIGN = 9006,
184
+ INVALID_TAG_NAME = 9007,
185
+ ELSE_WITHOUT_IF = 9008,
186
+ EMPTY_IF_BODY = 9009,
187
+ EMPTY_FOR_BODY = 9010,
188
+ MISSING_FOR_COLLECTION = 9011,
189
+ MISSING_FOR_SEMICOLON = 9012,
190
+ MISSING_FOR_ITEM = 9013,
191
+ PIPE_IN_WRONG_CONTEXT = 9014
192
+ }
178
193
  type ParseError = {
179
194
  code: ParseErrorCode;
180
195
  message: string;
@@ -310,6 +325,7 @@ declare class Tokenizer {
310
325
  private brace;
311
326
  private newLine;
312
327
  private getDentValue;
328
+ emptyLoc(): SourceLocation;
313
329
  private dent;
314
330
  private shorterThanBaseDentEof;
315
331
  private identifier;
@@ -413,7 +429,6 @@ declare class Compiler {
413
429
  errors: ParseError[];
414
430
  constructor(tokenizer: Tokenizer, hooks?: ParseHooks);
415
431
  private addError;
416
- private emptyLoc;
417
432
  /**
418
433
  * 编译程序入口,生成AST
419
434
  */
@@ -476,5 +491,5 @@ type ParseHooks = Partial<{
476
491
  declare function bobe(fragments: TemplateStringsArray, ...values: any[]): BobeUI;
477
492
  declare function customRender(option: CustomRenderConf): <T>(Ctor: typeof Store, root: any) => (ComponentNode$1 | Store)[];
478
493
 
479
- export { Compiler, NodeType, ParseSyntaxError, Tokenizer, bobe, customRender };
480
- export type { ASTNodeType, BaseNode, ComponentNode, ConditionalNode, DynamicValue, ElementNode, FragmentNode, InterpolationNode, LoopNode, ParseError, ParseErrorCode, Program, Property, PropertyKeyNode, PropertyValue, SourceLocation, StaticValue, TemplateNode, TextNode };
494
+ export { Compiler, NodeType, ParseErrorCode, ParseSyntaxError, Tokenizer, bobe, customRender };
495
+ export type { ASTNodeType, BaseNode, ComponentNode, ConditionalNode, DynamicValue, ElementNode, FragmentNode, InterpolationNode, LoopNode, ParseError, Program, Property, PropertyKeyNode, PropertyValue, SourceLocation, StaticValue, TemplateNode, TextNode };
package/dist/index.umd.js CHANGED
@@ -44,6 +44,23 @@
44
44
  TerpEvt["HandledComponentNode"] = "handled-component-node";
45
45
  return TerpEvt;
46
46
  })({});
47
+ let ParseErrorCode = function (ParseErrorCode) {
48
+ ParseErrorCode[ParseErrorCode["UNCLOSED_BRACE"] = 9001] = "UNCLOSED_BRACE";
49
+ ParseErrorCode[ParseErrorCode["UNCLOSED_STRING"] = 9002] = "UNCLOSED_STRING";
50
+ ParseErrorCode[ParseErrorCode["UNCLOSED_STATIC_INS"] = 9003] = "UNCLOSED_STATIC_INS";
51
+ ParseErrorCode[ParseErrorCode["INCONSISTENT_INDENT"] = 9004] = "INCONSISTENT_INDENT";
52
+ ParseErrorCode[ParseErrorCode["INDENT_MISMATCH"] = 9005] = "INDENT_MISMATCH";
53
+ ParseErrorCode[ParseErrorCode["MISSING_ASSIGN"] = 9006] = "MISSING_ASSIGN";
54
+ ParseErrorCode[ParseErrorCode["INVALID_TAG_NAME"] = 9007] = "INVALID_TAG_NAME";
55
+ ParseErrorCode[ParseErrorCode["ELSE_WITHOUT_IF"] = 9008] = "ELSE_WITHOUT_IF";
56
+ ParseErrorCode[ParseErrorCode["EMPTY_IF_BODY"] = 9009] = "EMPTY_IF_BODY";
57
+ ParseErrorCode[ParseErrorCode["EMPTY_FOR_BODY"] = 9010] = "EMPTY_FOR_BODY";
58
+ ParseErrorCode[ParseErrorCode["MISSING_FOR_COLLECTION"] = 9011] = "MISSING_FOR_COLLECTION";
59
+ ParseErrorCode[ParseErrorCode["MISSING_FOR_SEMICOLON"] = 9012] = "MISSING_FOR_SEMICOLON";
60
+ ParseErrorCode[ParseErrorCode["MISSING_FOR_ITEM"] = 9013] = "MISSING_FOR_ITEM";
61
+ ParseErrorCode[ParseErrorCode["PIPE_IN_WRONG_CONTEXT"] = 9014] = "PIPE_IN_WRONG_CONTEXT";
62
+ return ParseErrorCode;
63
+ }({});
47
64
  class ParseSyntaxError extends SyntaxError {
48
65
  constructor(code, message, loc) {
49
66
  super(message);
@@ -161,7 +178,7 @@
161
178
  const expLen = this.dentStack[i];
162
179
  if (currLen === expLen) break;
163
180
  if (currLen > expLen) {
164
- throw SyntaxError(`缩进错误,缩进长度不匹配`);
181
+ throw new ParseSyntaxError(ParseErrorCode.INCONSISTENT_INDENT, '缩进大小不统一', this.emptyLoc());
165
182
  }
166
183
  if (this.shorterThanBaseDentEof()) {
167
184
  break;
@@ -352,7 +369,7 @@
352
369
  while (1) {
353
370
  nextC = this.code[this.i + 1];
354
371
  if (nextC === undefined) {
355
- this.throwUnclosed('UNCLOSED_STATIC_INS', '未闭合的 "${...}"', startOffset, startLine, startCol);
372
+ this.throwUnclosed(ParseErrorCode.UNCLOSED_STATIC_INS, '未闭合的 "${...}"', startOffset, startLine, startCol);
356
373
  }
357
374
  value += nextC;
358
375
  this.next();
@@ -381,7 +398,7 @@
381
398
  while (1) {
382
399
  const char = this.code[this.i];
383
400
  if (char === undefined) {
384
- this.throwUnclosed('UNCLOSED_BRACE', '未闭合的 "{"', startOffset, startLine, startCol);
401
+ this.throwUnclosed(ParseErrorCode.UNCLOSED_BRACE, '未闭合的 "{"', startOffset, startLine, startCol);
385
402
  }
386
403
  const nextChar = this.code[this.i + 1];
387
404
  if (inComment === 'single' && char === '\n') {
@@ -470,6 +487,18 @@
470
487
  isEmptyLine
471
488
  };
472
489
  }
490
+ emptyLoc() {
491
+ const pos = this.getCurrentPos();
492
+ return {
493
+ start: pos,
494
+ end: {
495
+ offset: pos.offset + 1,
496
+ line: pos.line,
497
+ column: pos.column + 1
498
+ },
499
+ source: ' '
500
+ };
501
+ }
473
502
  dent() {
474
503
  const _this$getDentValue2 = this.getDentValue(),
475
504
  value = _this$getDentValue2.value,
@@ -496,7 +525,7 @@
496
525
  const expLen = this.dentStack[i];
497
526
  if (currLen === expLen) break;
498
527
  if (currLen > expLen) {
499
- throw SyntaxError('缩进大小不统一');
528
+ throw new ParseSyntaxError(ParseErrorCode.INCONSISTENT_INDENT, '缩进大小不统一', this.emptyLoc());
500
529
  }
501
530
  if (this.shorterThanBaseDentEof()) {
502
531
  return;
@@ -574,7 +603,7 @@
574
603
  while (1) {
575
604
  nextC = this.code[this.i + 1];
576
605
  if (nextC === undefined) {
577
- this.throwUnclosed('UNCLOSED_STRING', '未闭合的字符串字面量', startOffset, startLine, startCol);
606
+ this.throwUnclosed(ParseErrorCode.UNCLOSED_STRING, '未闭合的字符串字面量', startOffset, startLine, startCol);
578
607
  }
579
608
  const memoCount = continuousBackslashCount;
580
609
  if (nextC === '\\') {
@@ -895,18 +924,6 @@
895
924
  loc
896
925
  });
897
926
  }
898
- emptyLoc() {
899
- const pos = this.tokenizer.getCurrentPos();
900
- return {
901
- start: pos,
902
- end: {
903
- offset: pos.offset + 1,
904
- line: pos.line,
905
- column: pos.column + 1
906
- },
907
- source: ' '
908
- };
909
- }
910
927
  parseProgram() {
911
928
  const body = [];
912
929
  try {
@@ -920,10 +937,8 @@
920
937
  } catch (error) {
921
938
  if (error instanceof ParseSyntaxError) {
922
939
  this.addError(error.code, error.message, error.loc);
923
- } else if (error instanceof SyntaxError) {
924
- const knownCodes = ['INCONSISTENT_INDENT', 'INDENT_MISMATCH'];
925
- const code = knownCodes.includes(error.message) ? error.message : 'INCONSISTENT_INDENT';
926
- this.addError(code, error.message, this.emptyLoc());
940
+ } else {
941
+ this.addError(error.toString(), '未知错误', this.tokenizer.emptyLoc());
927
942
  }
928
943
  }
929
944
  return {
@@ -963,7 +978,7 @@
963
978
  templateNode(siblings) {
964
979
  const token = this.tokenizer.token;
965
980
  if (token.type & TokenType.Pipe) {
966
- this.addError('PIPE_IN_WRONG_CONTEXT', '"|" 只能出现在元素属性扩展行中', token.loc ?? this.emptyLoc());
981
+ this.addError(ParseErrorCode.PIPE_IN_WRONG_CONTEXT, '"|" 只能出现在元素属性扩展行中', token.loc ?? this.tokenizer.emptyLoc());
967
982
  this.tokenizer.nextToken();
968
983
  return null;
969
984
  }
@@ -971,12 +986,13 @@
971
986
  _this$tokenizer$_hook2 = _slicedToArray(_this$tokenizer$_hook, 2),
972
987
  hookType = _this$tokenizer$_hook2[0],
973
988
  value = _this$tokenizer$_hook2[1];
974
- if (value === 'if' || value === 'else' || value === 'fail') {
975
- if (value === 'else' || value === 'fail') {
989
+ const isElseOrFail = value === 'else' || value === 'fail';
990
+ if (value === 'if' || isElseOrFail) {
991
+ if (isElseOrFail) {
976
992
  const lastSibling = siblings[siblings.length - 1];
977
993
  const lastType = lastSibling?.type;
978
994
  if (lastType !== NodeType.If && lastType !== NodeType.Else && lastType !== NodeType.Fail) {
979
- this.addError('ELSE_WITHOUT_IF', `"${value}" 前必须有 "if" 或 "else" 节点`, token.loc ?? this.emptyLoc());
995
+ this.addError(ParseErrorCode.ELSE_WITHOUT_IF, `"${value}" 前必须有 "if" 或 "else" 节点`, token.loc ?? this.tokenizer.emptyLoc());
980
996
  }
981
997
  }
982
998
  return this.parseConditionalNode();
@@ -1004,7 +1020,7 @@
1004
1020
  parseElementNode(node) {
1005
1021
  const tagToken = this.tokenizer.token;
1006
1022
  if (!(tagToken.type & TokenType.Identifier)) {
1007
- this.addError('INVALID_TAG_NAME', `无效的标签名,期望标识符但得到 "${tagToken.value}"`, tagToken.loc ?? this.emptyLoc());
1023
+ this.addError(ParseErrorCode.INVALID_TAG_NAME, `无效的标签名,期望标识符但得到 "${tagToken.value}"`, tagToken.loc ?? this.tokenizer.emptyLoc());
1008
1024
  while (!(this.tokenizer.token.type & TokenType.NewLine) && !this.tokenizer.isEof()) {
1009
1025
  this.tokenizer.nextToken();
1010
1026
  }
@@ -1035,15 +1051,15 @@
1035
1051
  return node;
1036
1052
  }
1037
1053
  parseLoopNode(node) {
1038
- const forLoc = this.tokenizer.token.loc ?? this.emptyLoc();
1054
+ const forLoc = this.tokenizer.token.loc ?? this.tokenizer.emptyLoc();
1039
1055
  this.tokenizer.nextToken();
1040
1056
  const collection = this.parsePropertyValue();
1041
1057
  if (!collection.value && collection.value !== 0) {
1042
- this.addError('MISSING_FOR_COLLECTION', '"for" 缺少集合表达式', forLoc);
1058
+ this.addError(ParseErrorCode.MISSING_FOR_COLLECTION, '"for" 缺少集合表达式', forLoc);
1043
1059
  }
1044
1060
  const semicolonToken = this.tokenizer.nextToken();
1045
1061
  if (!(semicolonToken.type & TokenType.Semicolon)) {
1046
- this.addError('MISSING_FOR_SEMICOLON', '"for" 语法:for <集合>; <item> [index][; key],缺少第一个 ";"', semicolonToken.loc ?? this.emptyLoc());
1062
+ this.addError(ParseErrorCode.MISSING_FOR_SEMICOLON, '"for" 语法:for <集合>; <item> [index][; key],缺少第一个 ";"', semicolonToken.loc ?? this.tokenizer.emptyLoc());
1047
1063
  }
1048
1064
  const itemToken = this.tokenizer.nextToken();
1049
1065
  const isDestruct = itemToken.type === TokenType.InsertionExp;
@@ -1052,7 +1068,7 @@
1052
1068
  }
1053
1069
  const item = this.parsePropertyValue();
1054
1070
  if (!item.value && item.value !== 0) {
1055
- this.addError('MISSING_FOR_ITEM', '"for" 缺少 item 变量名', itemToken.loc ?? this.emptyLoc());
1071
+ this.addError(ParseErrorCode.MISSING_FOR_ITEM, '"for" 缺少 item 变量名', itemToken.loc ?? this.tokenizer.emptyLoc());
1056
1072
  }
1057
1073
  let char = this.tokenizer.peekChar(),
1058
1074
  key,
@@ -1117,7 +1133,7 @@
1117
1133
  node.value = this.parsePropertyValue();
1118
1134
  this.tokenizer.nextToken();
1119
1135
  } else {
1120
- this.addError('MISSING_ASSIGN', `属性 "${node.key.key}" 缺少 "=" 赋值符号`, node.key.loc ?? this.emptyLoc());
1136
+ this.addError(ParseErrorCode.MISSING_ASSIGN, `属性 "${node.key.key}" 缺少 "=" 赋值符号`, node.key.loc ?? this.tokenizer.emptyLoc());
1121
1137
  }
1122
1138
  node.loc.start = node.key.loc.start;
1123
1139
  node.loc.end = node.value ? node.value.loc.end : node.key.loc.end;