bobe 0.0.34 → 0.0.36
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/bobe.cjs.js +146 -34
- package/dist/bobe.cjs.js.map +1 -1
- package/dist/bobe.compiler.cjs.js +146 -34
- package/dist/bobe.compiler.cjs.js.map +1 -1
- package/dist/bobe.compiler.esm.js +146 -35
- package/dist/bobe.compiler.esm.js.map +1 -1
- package/dist/bobe.esm.js +146 -35
- package/dist/bobe.esm.js.map +1 -1
- package/dist/index.d.ts +27 -5
- package/dist/index.umd.js +146 -34
- package/dist/index.umd.js.map +1 -1
- package/package.json +3 -3
package/dist/bobe.cjs.js
CHANGED
|
@@ -43,6 +43,13 @@ let NodeSort = function (NodeSort) {
|
|
|
43
43
|
TerpEvt["HandledComponentNode"] = "handled-component-node";
|
|
44
44
|
return TerpEvt;
|
|
45
45
|
})({});
|
|
46
|
+
class ParseSyntaxError extends SyntaxError {
|
|
47
|
+
constructor(code, message, loc) {
|
|
48
|
+
super(message);
|
|
49
|
+
this.code = code;
|
|
50
|
+
this.loc = loc;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
46
53
|
|
|
47
54
|
class Tokenizer {
|
|
48
55
|
TabSize = 2;
|
|
@@ -81,6 +88,25 @@ class Tokenizer {
|
|
|
81
88
|
column: this.column
|
|
82
89
|
};
|
|
83
90
|
}
|
|
91
|
+
unclosedLoc(startOffset, startLine, startCol) {
|
|
92
|
+
const end = this.code.length - 1;
|
|
93
|
+
return {
|
|
94
|
+
start: {
|
|
95
|
+
offset: startOffset,
|
|
96
|
+
line: startLine,
|
|
97
|
+
column: startCol
|
|
98
|
+
},
|
|
99
|
+
end: {
|
|
100
|
+
offset: end,
|
|
101
|
+
line: this.line,
|
|
102
|
+
column: this.column
|
|
103
|
+
},
|
|
104
|
+
source: this.code.slice(startOffset, end)
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
throwUnclosed(code, message, startOffset, startLine, startCol) {
|
|
108
|
+
throw new ParseSyntaxError(code, message, this.unclosedLoc(startOffset, startLine, startCol));
|
|
109
|
+
}
|
|
84
110
|
resume(_snapshot) {
|
|
85
111
|
this.token = undefined;
|
|
86
112
|
this.needIndent = false;
|
|
@@ -249,8 +275,7 @@ class Tokenizer {
|
|
|
249
275
|
}
|
|
250
276
|
return this.token;
|
|
251
277
|
} catch (error) {
|
|
252
|
-
|
|
253
|
-
return this.token;
|
|
278
|
+
throw error;
|
|
254
279
|
} finally {
|
|
255
280
|
this.handledTokens.push(this.token);
|
|
256
281
|
}
|
|
@@ -313,6 +338,9 @@ class Tokenizer {
|
|
|
313
338
|
this.setToken(TokenType.Pipe, '|');
|
|
314
339
|
}
|
|
315
340
|
staticIns() {
|
|
341
|
+
const startOffset = this.preI,
|
|
342
|
+
startLine = this.line,
|
|
343
|
+
startCol = this.preCol;
|
|
316
344
|
let nextC = this.code[this.i + 1];
|
|
317
345
|
if (nextC !== '{') {
|
|
318
346
|
return false;
|
|
@@ -322,6 +350,9 @@ class Tokenizer {
|
|
|
322
350
|
let innerBrace = 0;
|
|
323
351
|
while (1) {
|
|
324
352
|
nextC = this.code[this.i + 1];
|
|
353
|
+
if (nextC === undefined) {
|
|
354
|
+
this.throwUnclosed('UNCLOSED_STATIC_INS', '未闭合的 "${...}"', startOffset, startLine, startCol);
|
|
355
|
+
}
|
|
325
356
|
value += nextC;
|
|
326
357
|
this.next();
|
|
327
358
|
if (nextC === '{') {
|
|
@@ -338,6 +369,9 @@ class Tokenizer {
|
|
|
338
369
|
return true;
|
|
339
370
|
}
|
|
340
371
|
brace() {
|
|
372
|
+
const startOffset = this.preI,
|
|
373
|
+
startLine = this.line,
|
|
374
|
+
startCol = this.preCol;
|
|
341
375
|
let inComment,
|
|
342
376
|
inString,
|
|
343
377
|
count = 0,
|
|
@@ -345,6 +379,9 @@ class Tokenizer {
|
|
|
345
379
|
backslashCount = 0;
|
|
346
380
|
while (1) {
|
|
347
381
|
const char = this.code[this.i];
|
|
382
|
+
if (char === undefined) {
|
|
383
|
+
this.throwUnclosed('UNCLOSED_BRACE', '未闭合的 "{"', startOffset, startLine, startCol);
|
|
384
|
+
}
|
|
348
385
|
const nextChar = this.code[this.i + 1];
|
|
349
386
|
if (inComment === 'single' && char === '\n') {
|
|
350
387
|
inComment = null;
|
|
@@ -527,11 +564,17 @@ class Tokenizer {
|
|
|
527
564
|
this.setToken(TokenType.Identifier, realValue);
|
|
528
565
|
}
|
|
529
566
|
str(char) {
|
|
567
|
+
const startOffset = this.preI,
|
|
568
|
+
startLine = this.line,
|
|
569
|
+
startCol = this.preCol;
|
|
530
570
|
let value = '';
|
|
531
571
|
let nextC;
|
|
532
572
|
let continuousBackslashCount = 0;
|
|
533
573
|
while (1) {
|
|
534
574
|
nextC = this.code[this.i + 1];
|
|
575
|
+
if (nextC === undefined) {
|
|
576
|
+
this.throwUnclosed('UNCLOSED_STRING', '未闭合的字符串字面量', startOffset, startLine, startCol);
|
|
577
|
+
}
|
|
535
578
|
const memoCount = continuousBackslashCount;
|
|
536
579
|
if (nextC === '\\') {
|
|
537
580
|
continuousBackslashCount++;
|
|
@@ -599,24 +642,6 @@ class Tokenizer {
|
|
|
599
642
|
}
|
|
600
643
|
}
|
|
601
644
|
|
|
602
|
-
var NodeType = function (NodeType) {
|
|
603
|
-
NodeType["Element"] = "Element";
|
|
604
|
-
NodeType["Text"] = "Text";
|
|
605
|
-
NodeType["Interpolation"] = "Interpolation";
|
|
606
|
-
NodeType["Property"] = "Property";
|
|
607
|
-
NodeType["PropertyKey"] = "PropertyKey";
|
|
608
|
-
NodeType["StaticValue"] = "StaticValue";
|
|
609
|
-
NodeType["DynamicValue"] = "DynamicValue";
|
|
610
|
-
NodeType["Program"] = "Program";
|
|
611
|
-
NodeType["If"] = "If";
|
|
612
|
-
NodeType["Else"] = "Else";
|
|
613
|
-
NodeType["Fail"] = "Fail";
|
|
614
|
-
NodeType["For"] = "For";
|
|
615
|
-
NodeType["Component"] = "Component";
|
|
616
|
-
NodeType["Fragment"] = "Fragment";
|
|
617
|
-
return NodeType;
|
|
618
|
-
}(NodeType || {});
|
|
619
|
-
|
|
620
645
|
function _applyDecs2311(e, t, n, r, o, i) {
|
|
621
646
|
var a,
|
|
622
647
|
c,
|
|
@@ -833,24 +858,71 @@ function _unsupportedIterableToArray(r, a) {
|
|
|
833
858
|
}
|
|
834
859
|
}
|
|
835
860
|
|
|
861
|
+
var NodeType = function (NodeType) {
|
|
862
|
+
NodeType["Element"] = "Element";
|
|
863
|
+
NodeType["Text"] = "Text";
|
|
864
|
+
NodeType["Interpolation"] = "Interpolation";
|
|
865
|
+
NodeType["Property"] = "Property";
|
|
866
|
+
NodeType["PropertyKey"] = "PropertyKey";
|
|
867
|
+
NodeType["StaticValue"] = "StaticValue";
|
|
868
|
+
NodeType["DynamicValue"] = "DynamicValue";
|
|
869
|
+
NodeType["Program"] = "Program";
|
|
870
|
+
NodeType["If"] = "If";
|
|
871
|
+
NodeType["Else"] = "Else";
|
|
872
|
+
NodeType["Fail"] = "Fail";
|
|
873
|
+
NodeType["For"] = "For";
|
|
874
|
+
NodeType["Component"] = "Component";
|
|
875
|
+
NodeType["Fragment"] = "Fragment";
|
|
876
|
+
return NodeType;
|
|
877
|
+
}(NodeType || {});
|
|
878
|
+
|
|
836
879
|
let _initProto;
|
|
837
880
|
class Compiler {
|
|
838
881
|
static {
|
|
839
|
-
var _applyDecs$e = _slicedToArray(_applyDecs2311(this, [], [[NodeHook, 2, "parseProgram"], [[NodeHook, NodeLoc], 2, "parseComponentNode"], [[NodeHook, NodeLoc], 2, "parseElementNode"], [[NodeHook, NodeLoc], 2, "parseConditionalNode"], [[NodeHook, NodeLoc], 2, "parseLoopNode"], [NodeHook, 2, "parseProperty"], [[NodeHook, TokenLoc], 2, "parsePropertyKey"], [[NodeHook, TokenLoc], 2, "parsePropertyValue"]]).e, 1);
|
|
882
|
+
var _applyDecs$e = _slicedToArray(_applyDecs2311(this, [], [[NodeHook, 2, "parseProgram"], [[NodeHook, NodeLoc], 2, "parseComponentNode"], [[NodeHook, NodeLoc], 2, "parseElementNode"], [[NodeHook, NodeLoc], 2, "parseConditionalNode"], [[NodeHook, NodeLoc], 2, "parseLoopNode"], [NodeHook, 2, "parseProperty"], [[NodeHook, TokenLoc], 2, "parsePropertyKey"], [[NodeHook, TokenLoc], 2, "parsePropertyValue"], [[NodeHook, TokenLoc], 2, "parseName"]]).e, 1);
|
|
840
883
|
_initProto = _applyDecs$e[0];
|
|
841
884
|
}
|
|
885
|
+
errors = (_initProto(this), []);
|
|
842
886
|
constructor(tokenizer, hooks = {}) {
|
|
843
887
|
this.tokenizer = tokenizer;
|
|
844
888
|
this.hooks = hooks;
|
|
845
|
-
|
|
889
|
+
}
|
|
890
|
+
addError(code, message, loc) {
|
|
891
|
+
this.errors.push({
|
|
892
|
+
code,
|
|
893
|
+
message,
|
|
894
|
+
loc
|
|
895
|
+
});
|
|
896
|
+
}
|
|
897
|
+
emptyLoc() {
|
|
898
|
+
const pos = this.tokenizer.getCurrentPos();
|
|
899
|
+
return {
|
|
900
|
+
start: pos,
|
|
901
|
+
end: {
|
|
902
|
+
offset: pos.offset + 1,
|
|
903
|
+
line: pos.line,
|
|
904
|
+
column: pos.column + 1
|
|
905
|
+
},
|
|
906
|
+
source: ' '
|
|
907
|
+
};
|
|
846
908
|
}
|
|
847
909
|
parseProgram() {
|
|
848
|
-
this.tokenizer.nextToken();
|
|
849
910
|
const body = [];
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
911
|
+
try {
|
|
912
|
+
this.tokenizer.nextToken();
|
|
913
|
+
while (!this.tokenizer.isEof()) {
|
|
914
|
+
const node = this.templateNode(body);
|
|
915
|
+
if (node) {
|
|
916
|
+
body.push(node);
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
} catch (error) {
|
|
920
|
+
if (error instanceof ParseSyntaxError) {
|
|
921
|
+
this.addError(error.code, error.message, error.loc);
|
|
922
|
+
} else if (error instanceof SyntaxError) {
|
|
923
|
+
const knownCodes = ['INCONSISTENT_INDENT', 'INDENT_MISMATCH'];
|
|
924
|
+
const code = knownCodes.includes(error.message) ? error.message : 'INCONSISTENT_INDENT';
|
|
925
|
+
this.addError(code, error.message, this.emptyLoc());
|
|
854
926
|
}
|
|
855
927
|
}
|
|
856
928
|
return {
|
|
@@ -876,7 +948,7 @@ class Compiler {
|
|
|
876
948
|
if (this.tokenizer.token.type & TokenType.Indent) {
|
|
877
949
|
this.tokenizer.nextToken();
|
|
878
950
|
while (!(this.tokenizer.token.type & TokenType.Dedent) && !this.tokenizer.isEof()) {
|
|
879
|
-
const child = this.templateNode();
|
|
951
|
+
const child = this.templateNode(children);
|
|
880
952
|
if (child) {
|
|
881
953
|
children.push(child);
|
|
882
954
|
}
|
|
@@ -887,13 +959,25 @@ class Compiler {
|
|
|
887
959
|
}
|
|
888
960
|
return children;
|
|
889
961
|
}
|
|
890
|
-
templateNode() {
|
|
891
|
-
this.tokenizer.token;
|
|
962
|
+
templateNode(siblings) {
|
|
963
|
+
const token = this.tokenizer.token;
|
|
964
|
+
if (token.type & TokenType.Pipe) {
|
|
965
|
+
this.addError('PIPE_IN_WRONG_CONTEXT', '"|" 只能出现在元素属性扩展行中', token.loc ?? this.emptyLoc());
|
|
966
|
+
this.tokenizer.nextToken();
|
|
967
|
+
return null;
|
|
968
|
+
}
|
|
892
969
|
const _this$tokenizer$_hook = this.tokenizer._hook({}),
|
|
893
970
|
_this$tokenizer$_hook2 = _slicedToArray(_this$tokenizer$_hook, 2),
|
|
894
971
|
hookType = _this$tokenizer$_hook2[0],
|
|
895
972
|
value = _this$tokenizer$_hook2[1];
|
|
896
973
|
if (value === 'if' || value === 'else' || value === 'fail') {
|
|
974
|
+
if (value === 'else' || value === 'fail') {
|
|
975
|
+
const lastSibling = siblings[siblings.length - 1];
|
|
976
|
+
const lastType = lastSibling?.type;
|
|
977
|
+
if (lastType !== NodeType.If && lastType !== NodeType.Else && lastType !== NodeType.Fail) {
|
|
978
|
+
this.addError('ELSE_WITHOUT_IF', `"${value}" 前必须有 "if" 或 "else" 节点`, token.loc ?? this.emptyLoc());
|
|
979
|
+
}
|
|
980
|
+
}
|
|
897
981
|
return this.parseConditionalNode();
|
|
898
982
|
}
|
|
899
983
|
if (value === 'for') {
|
|
@@ -905,12 +989,11 @@ class Compiler {
|
|
|
905
989
|
return this.parseElementNode();
|
|
906
990
|
}
|
|
907
991
|
parseComponentNode(node) {
|
|
908
|
-
const
|
|
909
|
-
const tagName = tagToken.value;
|
|
992
|
+
const name = this.parseName();
|
|
910
993
|
this.tokenizer.nextToken();
|
|
911
994
|
const props = this.headerLineAndExtensions();
|
|
912
995
|
node.type = NodeType.Component;
|
|
913
|
-
node.componentName =
|
|
996
|
+
node.componentName = name;
|
|
914
997
|
node.props = props;
|
|
915
998
|
this.hooks.parseComponentNode?.propsAdded?.call(this, node);
|
|
916
999
|
const children = this.handleChildren();
|
|
@@ -919,6 +1002,13 @@ class Compiler {
|
|
|
919
1002
|
}
|
|
920
1003
|
parseElementNode(node) {
|
|
921
1004
|
const tagToken = this.tokenizer.token;
|
|
1005
|
+
if (!(tagToken.type & TokenType.Identifier)) {
|
|
1006
|
+
this.addError('INVALID_TAG_NAME', `无效的标签名,期望标识符但得到 "${tagToken.value}"`, tagToken.loc ?? this.emptyLoc());
|
|
1007
|
+
while (!(this.tokenizer.token.type & TokenType.NewLine) && !this.tokenizer.isEof()) {
|
|
1008
|
+
this.tokenizer.nextToken();
|
|
1009
|
+
}
|
|
1010
|
+
return null;
|
|
1011
|
+
}
|
|
922
1012
|
const tagName = tagToken.value;
|
|
923
1013
|
this.tokenizer.nextToken();
|
|
924
1014
|
const props = this.headerLineAndExtensions();
|
|
@@ -944,15 +1034,25 @@ class Compiler {
|
|
|
944
1034
|
return node;
|
|
945
1035
|
}
|
|
946
1036
|
parseLoopNode(node) {
|
|
1037
|
+
const forLoc = this.tokenizer.token.loc ?? this.emptyLoc();
|
|
947
1038
|
this.tokenizer.nextToken();
|
|
948
1039
|
const collection = this.parsePropertyValue();
|
|
949
|
-
|
|
1040
|
+
if (!collection.value && collection.value !== 0) {
|
|
1041
|
+
this.addError('MISSING_FOR_COLLECTION', '"for" 缺少集合表达式', forLoc);
|
|
1042
|
+
}
|
|
1043
|
+
const semicolonToken = this.tokenizer.nextToken();
|
|
1044
|
+
if (!(semicolonToken.type & TokenType.Semicolon)) {
|
|
1045
|
+
this.addError('MISSING_FOR_SEMICOLON', '"for" 语法:for <集合>; <item> [index][; key],缺少第一个 ";"', semicolonToken.loc ?? this.emptyLoc());
|
|
1046
|
+
}
|
|
950
1047
|
const itemToken = this.tokenizer.nextToken();
|
|
951
1048
|
const isDestruct = itemToken.type === TokenType.InsertionExp;
|
|
952
1049
|
if (isDestruct) {
|
|
953
1050
|
itemToken.value = '{' + itemToken.value + '}';
|
|
954
1051
|
}
|
|
955
1052
|
const item = this.parsePropertyValue();
|
|
1053
|
+
if (!item.value && item.value !== 0) {
|
|
1054
|
+
this.addError('MISSING_FOR_ITEM', '"for" 缺少 item 变量名', itemToken.loc ?? this.emptyLoc());
|
|
1055
|
+
}
|
|
956
1056
|
let char = this.tokenizer.peekChar(),
|
|
957
1057
|
key,
|
|
958
1058
|
index;
|
|
@@ -1015,6 +1115,8 @@ class Compiler {
|
|
|
1015
1115
|
this.tokenizer.nextToken();
|
|
1016
1116
|
node.value = this.parsePropertyValue();
|
|
1017
1117
|
this.tokenizer.nextToken();
|
|
1118
|
+
} else {
|
|
1119
|
+
this.addError('MISSING_ASSIGN', `属性 "${node.key.key}" 缺少 "=" 赋值符号`, node.key.loc ?? this.emptyLoc());
|
|
1018
1120
|
}
|
|
1019
1121
|
node.loc.start = node.key.loc.start;
|
|
1020
1122
|
node.loc.end = node.value ? node.value.loc.end : node.key.loc.end;
|
|
@@ -1035,6 +1137,15 @@ class Compiler {
|
|
|
1035
1137
|
node.value = value;
|
|
1036
1138
|
return node;
|
|
1037
1139
|
}
|
|
1140
|
+
parseName(node) {
|
|
1141
|
+
const _this$tokenizer$_hook5 = this.tokenizer._hook({}),
|
|
1142
|
+
_this$tokenizer$_hook6 = _slicedToArray(_this$tokenizer$_hook5, 2),
|
|
1143
|
+
hookType = _this$tokenizer$_hook6[0],
|
|
1144
|
+
value = _this$tokenizer$_hook6[1];
|
|
1145
|
+
node.type = hookType === 'dynamic' ? NodeType.DynamicValue : NodeType.StaticValue;
|
|
1146
|
+
node.value = value;
|
|
1147
|
+
return node;
|
|
1148
|
+
}
|
|
1038
1149
|
}
|
|
1039
1150
|
function NodeLoc(target, context) {
|
|
1040
1151
|
return function (_node) {
|
|
@@ -2005,6 +2116,7 @@ function customRender(option) {
|
|
|
2005
2116
|
|
|
2006
2117
|
exports.Compiler = Compiler;
|
|
2007
2118
|
exports.NodeType = NodeType;
|
|
2119
|
+
exports.ParseSyntaxError = ParseSyntaxError;
|
|
2008
2120
|
exports.Tokenizer = Tokenizer;
|
|
2009
2121
|
exports.bobe = bobe;
|
|
2010
2122
|
exports.customRender = customRender;
|