@herb-tools/core 0.1.1 → 0.3.0

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.
@@ -1,10 +1,3 @@
1
- class ASTNode {
2
- errors;
3
- constructor() {
4
- this.errors = [];
5
- }
6
- }
7
-
8
1
  const expectedFunctions = [
9
2
  "parse",
10
3
  "lex",
@@ -169,6 +162,8 @@ class Token {
169
162
  }
170
163
  }
171
164
 
165
+ // NOTE: This file is generated by the templates/template.rb script and should not
166
+ // be modified manually. See /Users/marcoroth/Development/herb-release/templates/javascript/packages/core/src/errors.ts.erb
172
167
  class HerbError {
173
168
  type;
174
169
  message;
@@ -192,24 +187,6 @@ class HerbError {
192
187
  return this.treeInspect(0);
193
188
  }
194
189
  }
195
-
196
- // NOTE: This file is generated by the templates/template.rb script and should not
197
- // be modified manually. See /Users/marcoroth/Development/herb-release/templates/javascript/packages/core/src/errors.ts.erb
198
- function fromSerializedError(error) {
199
- switch (error.type) {
200
- case "UNEXPECTED_ERROR": return UnexpectedError.from(error);
201
- case "UNEXPECTED_TOKEN_ERROR": return UnexpectedTokenError.from(error);
202
- case "MISSING_OPENING_TAG_ERROR": return MissingOpeningTagError.from(error);
203
- case "MISSING_CLOSING_TAG_ERROR": return MissingClosingTagError.from(error);
204
- case "TAG_NAMES_MISMATCH_ERROR": return TagNamesMismatchError.from(error);
205
- case "QUOTES_MISMATCH_ERROR": return QuotesMismatchError.from(error);
206
- case "VOID_ELEMENT_CLOSING_TAG_ERROR": return VoidElementClosingTagError.from(error);
207
- case "UNCLOSED_ELEMENT_ERROR": return UnclosedElementError.from(error);
208
- case "RUBY_PARSE_ERROR": return RubyParseError.from(error);
209
- default:
210
- throw new Error(`Unknown node type: ${error.type}`);
211
- }
212
- }
213
190
  class UnexpectedError extends HerbError {
214
191
  description;
215
192
  expected;
@@ -732,9 +709,24 @@ class RubyParseError extends HerbError {
732
709
  return output;
733
710
  }
734
711
  }
712
+ function fromSerializedError(error) {
713
+ switch (error.type) {
714
+ case "UNEXPECTED_ERROR": return UnexpectedError.from(error);
715
+ case "UNEXPECTED_TOKEN_ERROR": return UnexpectedTokenError.from(error);
716
+ case "MISSING_OPENING_TAG_ERROR": return MissingOpeningTagError.from(error);
717
+ case "MISSING_CLOSING_TAG_ERROR": return MissingClosingTagError.from(error);
718
+ case "TAG_NAMES_MISMATCH_ERROR": return TagNamesMismatchError.from(error);
719
+ case "QUOTES_MISMATCH_ERROR": return QuotesMismatchError.from(error);
720
+ case "VOID_ELEMENT_CLOSING_TAG_ERROR": return VoidElementClosingTagError.from(error);
721
+ case "UNCLOSED_ELEMENT_ERROR": return UnclosedElementError.from(error);
722
+ case "RUBY_PARSE_ERROR": return RubyParseError.from(error);
723
+ default:
724
+ throw new Error(`Unknown node type: ${error.type}`);
725
+ }
726
+ }
735
727
 
736
728
  var name = "@herb-tools/core";
737
- var version = "0.1.1";
729
+ var version = "0.3.0";
738
730
  var packageJSON = {
739
731
  name: name,
740
732
  version: version};
@@ -763,11 +755,19 @@ class Result {
763
755
  this.warnings = warnings || [];
764
756
  this.errors = errors || [];
765
757
  }
766
- success() {
767
- return false;
758
+ /**
759
+ * Determines if the parsing was successful.
760
+ * @returns `true` if there are no errors, otherwise `false`.
761
+ */
762
+ get successful() {
763
+ return this.errors.length === 0;
768
764
  }
769
- failed() {
770
- return true;
765
+ /**
766
+ * Determines if the parsing failed.
767
+ * @returns `true` if there are errors, otherwise `false`.
768
+ */
769
+ get failed() {
770
+ return this.errors.length > 0;
771
771
  }
772
772
  }
773
773
 
@@ -808,6 +808,18 @@ class TokenList {
808
808
  }
809
809
  }
810
810
 
811
+ class HerbWarning {
812
+ message;
813
+ location;
814
+ static from(warning) {
815
+ return new HerbWarning(warning.message, Location.from(warning.location));
816
+ }
817
+ constructor(message, location) {
818
+ this.message = message;
819
+ this.location = location;
820
+ }
821
+ }
822
+
811
823
  /**
812
824
  * Represents the result of a lexical analysis, extending the base `Result` class.
813
825
  * It contains the token list, source code, warnings, and errors.
@@ -821,7 +833,7 @@ class LexResult extends Result {
821
833
  * @returns A new `LexResult` instance.
822
834
  */
823
835
  static from(result) {
824
- return new LexResult(TokenList.from(result.tokens || []), result.source, result.warnings, result.errors);
836
+ return new LexResult(TokenList.from(result.tokens || []), result.source, result.warnings.map((warning) => HerbWarning.from(warning)), result.errors.map((error) => HerbError.from(error)));
825
837
  }
826
838
  /**
827
839
  * Constructs a new `LexResult`.
@@ -838,14 +850,14 @@ class LexResult extends Result {
838
850
  * Determines if the lexing was successful.
839
851
  * @returns `true` if there are no errors, otherwise `false`.
840
852
  */
841
- success() {
853
+ get successful() {
842
854
  return this.errors.length === 0;
843
855
  }
844
856
  /**
845
857
  * Determines if the lexing failed.
846
858
  * @returns `true` if there are errors, otherwise `false`.
847
859
  */
848
- failed() {
860
+ get failed() {
849
861
  return this.errors.length > 0;
850
862
  }
851
863
  /**
@@ -862,6 +874,8 @@ class LexResult extends Result {
862
874
  }
863
875
  }
864
876
 
877
+ // NOTE: This file is generated by the templates/template.rb script and should not
878
+ // be modified manually. See /Users/marcoroth/Development/herb-release/templates/javascript/packages/core/src/nodes.ts.erb
865
879
  class Node {
866
880
  type;
867
881
  location;
@@ -884,6 +898,9 @@ class Node {
884
898
  inspect() {
885
899
  return this.treeInspect(0);
886
900
  }
901
+ get isSingleLine() {
902
+ return this.location.start.line === this.location.end.line;
903
+ }
887
904
  inspectArray(array, prefix) {
888
905
  if (!array)
889
906
  return "∅\n";
@@ -920,42 +937,6 @@ class Node {
920
937
  return output;
921
938
  }
922
939
  }
923
-
924
- // NOTE: This file is generated by the templates/template.rb script and should not
925
- // be modified manually. See /Users/marcoroth/Development/herb-release/templates/javascript/packages/core/src/nodes.ts.erb
926
- function fromSerializedNode(node) {
927
- switch (node.type) {
928
- case "AST_DOCUMENT_NODE": return DocumentNode.from(node);
929
- case "AST_LITERAL_NODE": return LiteralNode.from(node);
930
- case "AST_HTML_OPEN_TAG_NODE": return HTMLOpenTagNode.from(node);
931
- case "AST_HTML_CLOSE_TAG_NODE": return HTMLCloseTagNode.from(node);
932
- case "AST_HTML_SELF_CLOSE_TAG_NODE": return HTMLSelfCloseTagNode.from(node);
933
- case "AST_HTML_ELEMENT_NODE": return HTMLElementNode.from(node);
934
- case "AST_HTML_ATTRIBUTE_VALUE_NODE": return HTMLAttributeValueNode.from(node);
935
- case "AST_HTML_ATTRIBUTE_NAME_NODE": return HTMLAttributeNameNode.from(node);
936
- case "AST_HTML_ATTRIBUTE_NODE": return HTMLAttributeNode.from(node);
937
- case "AST_HTML_TEXT_NODE": return HTMLTextNode.from(node);
938
- case "AST_HTML_COMMENT_NODE": return HTMLCommentNode.from(node);
939
- case "AST_HTML_DOCTYPE_NODE": return HTMLDoctypeNode.from(node);
940
- case "AST_WHITESPACE_NODE": return WhitespaceNode.from(node);
941
- case "AST_ERB_CONTENT_NODE": return ERBContentNode.from(node);
942
- case "AST_ERB_END_NODE": return ERBEndNode.from(node);
943
- case "AST_ERB_ELSE_NODE": return ERBElseNode.from(node);
944
- case "AST_ERB_IF_NODE": return ERBIfNode.from(node);
945
- case "AST_ERB_BLOCK_NODE": return ERBBlockNode.from(node);
946
- case "AST_ERB_WHEN_NODE": return ERBWhenNode.from(node);
947
- case "AST_ERB_CASE_NODE": return ERBCaseNode.from(node);
948
- case "AST_ERB_WHILE_NODE": return ERBWhileNode.from(node);
949
- case "AST_ERB_UNTIL_NODE": return ERBUntilNode.from(node);
950
- case "AST_ERB_FOR_NODE": return ERBForNode.from(node);
951
- case "AST_ERB_RESCUE_NODE": return ERBRescueNode.from(node);
952
- case "AST_ERB_ENSURE_NODE": return ERBEnsureNode.from(node);
953
- case "AST_ERB_BEGIN_NODE": return ERBBeginNode.from(node);
954
- case "AST_ERB_UNLESS_NODE": return ERBUnlessNode.from(node);
955
- default:
956
- throw new Error(`Unknown node type: ${node.type}`);
957
- }
958
- }
959
940
  class DocumentNode extends Node {
960
941
  children;
961
942
  static from(data) {
@@ -970,10 +951,16 @@ class DocumentNode extends Node {
970
951
  super(props.type, props.location, props.errors);
971
952
  this.children = props.children;
972
953
  }
954
+ accept(visitor) {
955
+ visitor.visitDocumentNode(this);
956
+ }
973
957
  childNodes() {
974
958
  return [
975
959
  ...this.children,
976
- ].filter(node => node !== null && node !== undefined);
960
+ ];
961
+ }
962
+ compactChildNodes() {
963
+ return this.childNodes().filter(node => node !== null && node !== undefined);
977
964
  }
978
965
  recursiveErrors() {
979
966
  return [
@@ -1011,8 +998,14 @@ class LiteralNode extends Node {
1011
998
  super(props.type, props.location, props.errors);
1012
999
  this.content = convertToUTF8(props.content);
1013
1000
  }
1001
+ accept(visitor) {
1002
+ visitor.visitLiteralNode(this);
1003
+ }
1014
1004
  childNodes() {
1015
- return [].filter(node => node !== null && node !== undefined);
1005
+ return [];
1006
+ }
1007
+ compactChildNodes() {
1008
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1016
1009
  }
1017
1010
  recursiveErrors() {
1018
1011
  return [
@@ -1061,10 +1054,16 @@ class HTMLOpenTagNode extends Node {
1061
1054
  this.children = props.children;
1062
1055
  this.is_void = props.is_void;
1063
1056
  }
1057
+ accept(visitor) {
1058
+ visitor.visitHTMLOpenTagNode(this);
1059
+ }
1064
1060
  childNodes() {
1065
1061
  return [
1066
1062
  ...this.children,
1067
- ].filter(node => node !== null && node !== undefined);
1063
+ ];
1064
+ }
1065
+ compactChildNodes() {
1066
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1068
1067
  }
1069
1068
  recursiveErrors() {
1070
1069
  return [
@@ -1116,8 +1115,14 @@ class HTMLCloseTagNode extends Node {
1116
1115
  this.tag_name = props.tag_name;
1117
1116
  this.tag_closing = props.tag_closing;
1118
1117
  }
1118
+ accept(visitor) {
1119
+ visitor.visitHTMLCloseTagNode(this);
1120
+ }
1119
1121
  childNodes() {
1120
- return [].filter(node => node !== null && node !== undefined);
1122
+ return [];
1123
+ }
1124
+ compactChildNodes() {
1125
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1121
1126
  }
1122
1127
  recursiveErrors() {
1123
1128
  return [
@@ -1170,10 +1175,16 @@ class HTMLSelfCloseTagNode extends Node {
1170
1175
  this.tag_closing = props.tag_closing;
1171
1176
  this.is_void = props.is_void;
1172
1177
  }
1178
+ accept(visitor) {
1179
+ visitor.visitHTMLSelfCloseTagNode(this);
1180
+ }
1173
1181
  childNodes() {
1174
1182
  return [
1175
1183
  ...this.attributes,
1176
- ].filter(node => node !== null && node !== undefined);
1184
+ ];
1185
+ }
1186
+ compactChildNodes() {
1187
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1177
1188
  }
1178
1189
  recursiveErrors() {
1179
1190
  return [
@@ -1231,12 +1242,18 @@ class HTMLElementNode extends Node {
1231
1242
  this.close_tag = props.close_tag;
1232
1243
  this.is_void = props.is_void;
1233
1244
  }
1245
+ accept(visitor) {
1246
+ visitor.visitHTMLElementNode(this);
1247
+ }
1234
1248
  childNodes() {
1235
1249
  return [
1236
1250
  this.open_tag,
1237
1251
  ...this.body,
1238
1252
  this.close_tag,
1239
- ].filter(node => node !== null && node !== undefined);
1253
+ ];
1254
+ }
1255
+ compactChildNodes() {
1256
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1240
1257
  }
1241
1258
  recursiveErrors() {
1242
1259
  return [
@@ -1293,10 +1310,16 @@ class HTMLAttributeValueNode extends Node {
1293
1310
  this.close_quote = props.close_quote;
1294
1311
  this.quoted = props.quoted;
1295
1312
  }
1313
+ accept(visitor) {
1314
+ visitor.visitHTMLAttributeValueNode(this);
1315
+ }
1296
1316
  childNodes() {
1297
1317
  return [
1298
1318
  ...this.children,
1299
- ].filter(node => node !== null && node !== undefined);
1319
+ ];
1320
+ }
1321
+ compactChildNodes() {
1322
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1300
1323
  }
1301
1324
  recursiveErrors() {
1302
1325
  return [
@@ -1340,8 +1363,14 @@ class HTMLAttributeNameNode extends Node {
1340
1363
  super(props.type, props.location, props.errors);
1341
1364
  this.name = props.name;
1342
1365
  }
1366
+ accept(visitor) {
1367
+ visitor.visitHTMLAttributeNameNode(this);
1368
+ }
1343
1369
  childNodes() {
1344
- return [].filter(node => node !== null && node !== undefined);
1370
+ return [];
1371
+ }
1372
+ compactChildNodes() {
1373
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1345
1374
  }
1346
1375
  recursiveErrors() {
1347
1376
  return [
@@ -1384,11 +1413,17 @@ class HTMLAttributeNode extends Node {
1384
1413
  this.equals = props.equals;
1385
1414
  this.value = props.value;
1386
1415
  }
1416
+ accept(visitor) {
1417
+ visitor.visitHTMLAttributeNode(this);
1418
+ }
1387
1419
  childNodes() {
1388
1420
  return [
1389
1421
  this.name,
1390
1422
  this.value,
1391
- ].filter(node => node !== null && node !== undefined);
1423
+ ];
1424
+ }
1425
+ compactChildNodes() {
1426
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1392
1427
  }
1393
1428
  recursiveErrors() {
1394
1429
  return [
@@ -1431,8 +1466,14 @@ class HTMLTextNode extends Node {
1431
1466
  super(props.type, props.location, props.errors);
1432
1467
  this.content = convertToUTF8(props.content);
1433
1468
  }
1469
+ accept(visitor) {
1470
+ visitor.visitHTMLTextNode(this);
1471
+ }
1434
1472
  childNodes() {
1435
- return [].filter(node => node !== null && node !== undefined);
1473
+ return [];
1474
+ }
1475
+ compactChildNodes() {
1476
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1436
1477
  }
1437
1478
  recursiveErrors() {
1438
1479
  return [
@@ -1475,10 +1516,16 @@ class HTMLCommentNode extends Node {
1475
1516
  this.children = props.children;
1476
1517
  this.comment_end = props.comment_end;
1477
1518
  }
1519
+ accept(visitor) {
1520
+ visitor.visitHTMLCommentNode(this);
1521
+ }
1478
1522
  childNodes() {
1479
1523
  return [
1480
1524
  ...this.children,
1481
- ].filter(node => node !== null && node !== undefined);
1525
+ ];
1526
+ }
1527
+ compactChildNodes() {
1528
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1482
1529
  }
1483
1530
  recursiveErrors() {
1484
1531
  return [
@@ -1526,10 +1573,16 @@ class HTMLDoctypeNode extends Node {
1526
1573
  this.children = props.children;
1527
1574
  this.tag_closing = props.tag_closing;
1528
1575
  }
1576
+ accept(visitor) {
1577
+ visitor.visitHTMLDoctypeNode(this);
1578
+ }
1529
1579
  childNodes() {
1530
1580
  return [
1531
1581
  ...this.children,
1532
- ].filter(node => node !== null && node !== undefined);
1582
+ ];
1583
+ }
1584
+ compactChildNodes() {
1585
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1533
1586
  }
1534
1587
  recursiveErrors() {
1535
1588
  return [
@@ -1571,8 +1624,14 @@ class WhitespaceNode extends Node {
1571
1624
  super(props.type, props.location, props.errors);
1572
1625
  this.value = props.value;
1573
1626
  }
1627
+ accept(visitor) {
1628
+ visitor.visitWhitespaceNode(this);
1629
+ }
1574
1630
  childNodes() {
1575
- return [].filter(node => node !== null && node !== undefined);
1631
+ return [];
1632
+ }
1633
+ compactChildNodes() {
1634
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1576
1635
  }
1577
1636
  recursiveErrors() {
1578
1637
  return [
@@ -1624,8 +1683,14 @@ class ERBContentNode extends Node {
1624
1683
  this.parsed = props.parsed;
1625
1684
  this.valid = props.valid;
1626
1685
  }
1686
+ accept(visitor) {
1687
+ visitor.visitERBContentNode(this);
1688
+ }
1627
1689
  childNodes() {
1628
- return [].filter(node => node !== null && node !== undefined);
1690
+ return [];
1691
+ }
1692
+ compactChildNodes() {
1693
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1629
1694
  }
1630
1695
  recursiveErrors() {
1631
1696
  return [
@@ -1678,8 +1743,14 @@ class ERBEndNode extends Node {
1678
1743
  this.content = props.content;
1679
1744
  this.tag_closing = props.tag_closing;
1680
1745
  }
1746
+ accept(visitor) {
1747
+ visitor.visitERBEndNode(this);
1748
+ }
1681
1749
  childNodes() {
1682
- return [].filter(node => node !== null && node !== undefined);
1750
+ return [];
1751
+ }
1752
+ compactChildNodes() {
1753
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1683
1754
  }
1684
1755
  recursiveErrors() {
1685
1756
  return [
@@ -1729,10 +1800,16 @@ class ERBElseNode extends Node {
1729
1800
  this.tag_closing = props.tag_closing;
1730
1801
  this.statements = props.statements;
1731
1802
  }
1803
+ accept(visitor) {
1804
+ visitor.visitERBElseNode(this);
1805
+ }
1732
1806
  childNodes() {
1733
1807
  return [
1734
1808
  ...this.statements,
1735
- ].filter(node => node !== null && node !== undefined);
1809
+ ];
1810
+ }
1811
+ compactChildNodes() {
1812
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1736
1813
  }
1737
1814
  recursiveErrors() {
1738
1815
  return [
@@ -1791,12 +1868,18 @@ class ERBIfNode extends Node {
1791
1868
  this.subsequent = props.subsequent;
1792
1869
  this.end_node = props.end_node;
1793
1870
  }
1871
+ accept(visitor) {
1872
+ visitor.visitERBIfNode(this);
1873
+ }
1794
1874
  childNodes() {
1795
1875
  return [
1796
1876
  ...this.statements,
1797
1877
  this.subsequent,
1798
1878
  this.end_node,
1799
- ].filter(node => node !== null && node !== undefined);
1879
+ ];
1880
+ }
1881
+ compactChildNodes() {
1882
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1800
1883
  }
1801
1884
  recursiveErrors() {
1802
1885
  return [
@@ -1858,11 +1941,17 @@ class ERBBlockNode extends Node {
1858
1941
  this.body = props.body;
1859
1942
  this.end_node = props.end_node;
1860
1943
  }
1944
+ accept(visitor) {
1945
+ visitor.visitERBBlockNode(this);
1946
+ }
1861
1947
  childNodes() {
1862
1948
  return [
1863
1949
  ...this.body,
1864
1950
  this.end_node,
1865
- ].filter(node => node !== null && node !== undefined);
1951
+ ];
1952
+ }
1953
+ compactChildNodes() {
1954
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1866
1955
  }
1867
1956
  recursiveErrors() {
1868
1957
  return [
@@ -1918,10 +2007,16 @@ class ERBWhenNode extends Node {
1918
2007
  this.tag_closing = props.tag_closing;
1919
2008
  this.statements = props.statements;
1920
2009
  }
2010
+ accept(visitor) {
2011
+ visitor.visitERBWhenNode(this);
2012
+ }
1921
2013
  childNodes() {
1922
2014
  return [
1923
2015
  ...this.statements,
1924
- ].filter(node => node !== null && node !== undefined);
2016
+ ];
2017
+ }
2018
+ compactChildNodes() {
2019
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1925
2020
  }
1926
2021
  recursiveErrors() {
1927
2022
  return [
@@ -1983,13 +2078,19 @@ class ERBCaseNode extends Node {
1983
2078
  this.else_clause = props.else_clause;
1984
2079
  this.end_node = props.end_node;
1985
2080
  }
2081
+ accept(visitor) {
2082
+ visitor.visitERBCaseNode(this);
2083
+ }
1986
2084
  childNodes() {
1987
2085
  return [
1988
2086
  ...this.children,
1989
2087
  ...this.conditions,
1990
2088
  this.else_clause,
1991
2089
  this.end_node,
1992
- ].filter(node => node !== null && node !== undefined);
2090
+ ];
2091
+ }
2092
+ compactChildNodes() {
2093
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1993
2094
  }
1994
2095
  recursiveErrors() {
1995
2096
  return [
@@ -2028,6 +2129,89 @@ class ERBCaseNode extends Node {
2028
2129
  return output;
2029
2130
  }
2030
2131
  }
2132
+ class ERBCaseMatchNode extends Node {
2133
+ tag_opening;
2134
+ content;
2135
+ tag_closing;
2136
+ children;
2137
+ conditions;
2138
+ else_clause;
2139
+ end_node;
2140
+ static from(data) {
2141
+ return new ERBCaseMatchNode({
2142
+ type: data.type,
2143
+ location: Location.from(data.location),
2144
+ errors: (data.errors || []).map(error => HerbError.from(error)),
2145
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
2146
+ content: data.content ? Token.from(data.content) : null,
2147
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
2148
+ children: (data.children || []).map(node => fromSerializedNode(node)),
2149
+ conditions: (data.conditions || []).map(node => fromSerializedNode(node)),
2150
+ else_clause: data.else_clause ? fromSerializedNode(data.else_clause) : null,
2151
+ end_node: data.end_node ? fromSerializedNode(data.end_node) : null,
2152
+ });
2153
+ }
2154
+ constructor(props) {
2155
+ super(props.type, props.location, props.errors);
2156
+ this.tag_opening = props.tag_opening;
2157
+ this.content = props.content;
2158
+ this.tag_closing = props.tag_closing;
2159
+ this.children = props.children;
2160
+ this.conditions = props.conditions;
2161
+ this.else_clause = props.else_clause;
2162
+ this.end_node = props.end_node;
2163
+ }
2164
+ accept(visitor) {
2165
+ visitor.visitERBCaseMatchNode(this);
2166
+ }
2167
+ childNodes() {
2168
+ return [
2169
+ ...this.children,
2170
+ ...this.conditions,
2171
+ this.else_clause,
2172
+ this.end_node,
2173
+ ];
2174
+ }
2175
+ compactChildNodes() {
2176
+ return this.childNodes().filter(node => node !== null && node !== undefined);
2177
+ }
2178
+ recursiveErrors() {
2179
+ return [
2180
+ ...this.errors,
2181
+ ...this.children.map(node => node.recursiveErrors()),
2182
+ ...this.conditions.map(node => node.recursiveErrors()),
2183
+ this.else_clause ? this.else_clause.recursiveErrors() : [],
2184
+ this.end_node ? this.end_node.recursiveErrors() : [],
2185
+ ].flat();
2186
+ }
2187
+ toJSON() {
2188
+ return {
2189
+ ...super.toJSON(),
2190
+ type: "AST_ERB_CASE_MATCH_NODE",
2191
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
2192
+ content: this.content ? this.content.toJSON() : null,
2193
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
2194
+ children: this.children.map(node => node.toJSON()),
2195
+ conditions: this.conditions.map(node => node.toJSON()),
2196
+ else_clause: this.else_clause ? this.else_clause.toJSON() : null,
2197
+ end_node: this.end_node ? this.end_node.toJSON() : null,
2198
+ };
2199
+ }
2200
+ treeInspect() {
2201
+ let output = "";
2202
+ output += `@ ERBCaseMatchNode ${this.location.treeInspectWithLabel()}\n`;
2203
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
2204
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
2205
+ output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
2206
+ output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
2207
+ output += `├── children: ${this.inspectArray(this.children, "│ ")}`;
2208
+ output += `├── conditions: ${this.inspectArray(this.conditions, "│ ")}`;
2209
+ output += `├── else_clause: ${this.inspectNode(this.else_clause, "│ ")}`;
2210
+ output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
2211
+ // output += "\n";
2212
+ return output;
2213
+ }
2214
+ }
2031
2215
  class ERBWhileNode extends Node {
2032
2216
  tag_opening;
2033
2217
  content;
@@ -2054,11 +2238,17 @@ class ERBWhileNode extends Node {
2054
2238
  this.statements = props.statements;
2055
2239
  this.end_node = props.end_node;
2056
2240
  }
2241
+ accept(visitor) {
2242
+ visitor.visitERBWhileNode(this);
2243
+ }
2057
2244
  childNodes() {
2058
2245
  return [
2059
2246
  ...this.statements,
2060
2247
  this.end_node,
2061
- ].filter(node => node !== null && node !== undefined);
2248
+ ];
2249
+ }
2250
+ compactChildNodes() {
2251
+ return this.childNodes().filter(node => node !== null && node !== undefined);
2062
2252
  }
2063
2253
  recursiveErrors() {
2064
2254
  return [
@@ -2117,11 +2307,17 @@ class ERBUntilNode extends Node {
2117
2307
  this.statements = props.statements;
2118
2308
  this.end_node = props.end_node;
2119
2309
  }
2310
+ accept(visitor) {
2311
+ visitor.visitERBUntilNode(this);
2312
+ }
2120
2313
  childNodes() {
2121
2314
  return [
2122
2315
  ...this.statements,
2123
2316
  this.end_node,
2124
- ].filter(node => node !== null && node !== undefined);
2317
+ ];
2318
+ }
2319
+ compactChildNodes() {
2320
+ return this.childNodes().filter(node => node !== null && node !== undefined);
2125
2321
  }
2126
2322
  recursiveErrors() {
2127
2323
  return [
@@ -2180,11 +2376,17 @@ class ERBForNode extends Node {
2180
2376
  this.statements = props.statements;
2181
2377
  this.end_node = props.end_node;
2182
2378
  }
2379
+ accept(visitor) {
2380
+ visitor.visitERBForNode(this);
2381
+ }
2183
2382
  childNodes() {
2184
2383
  return [
2185
2384
  ...this.statements,
2186
2385
  this.end_node,
2187
- ].filter(node => node !== null && node !== undefined);
2386
+ ];
2387
+ }
2388
+ compactChildNodes() {
2389
+ return this.childNodes().filter(node => node !== null && node !== undefined);
2188
2390
  }
2189
2391
  recursiveErrors() {
2190
2392
  return [
@@ -2243,11 +2445,17 @@ class ERBRescueNode extends Node {
2243
2445
  this.statements = props.statements;
2244
2446
  this.subsequent = props.subsequent;
2245
2447
  }
2448
+ accept(visitor) {
2449
+ visitor.visitERBRescueNode(this);
2450
+ }
2246
2451
  childNodes() {
2247
2452
  return [
2248
2453
  ...this.statements,
2249
2454
  this.subsequent,
2250
- ].filter(node => node !== null && node !== undefined);
2455
+ ];
2456
+ }
2457
+ compactChildNodes() {
2458
+ return this.childNodes().filter(node => node !== null && node !== undefined);
2251
2459
  }
2252
2460
  recursiveErrors() {
2253
2461
  return [
@@ -2303,10 +2511,16 @@ class ERBEnsureNode extends Node {
2303
2511
  this.tag_closing = props.tag_closing;
2304
2512
  this.statements = props.statements;
2305
2513
  }
2514
+ accept(visitor) {
2515
+ visitor.visitERBEnsureNode(this);
2516
+ }
2306
2517
  childNodes() {
2307
2518
  return [
2308
2519
  ...this.statements,
2309
- ].filter(node => node !== null && node !== undefined);
2520
+ ];
2521
+ }
2522
+ compactChildNodes() {
2523
+ return this.childNodes().filter(node => node !== null && node !== undefined);
2310
2524
  }
2311
2525
  recursiveErrors() {
2312
2526
  return [
@@ -2371,6 +2585,9 @@ class ERBBeginNode extends Node {
2371
2585
  this.ensure_clause = props.ensure_clause;
2372
2586
  this.end_node = props.end_node;
2373
2587
  }
2588
+ accept(visitor) {
2589
+ visitor.visitERBBeginNode(this);
2590
+ }
2374
2591
  childNodes() {
2375
2592
  return [
2376
2593
  ...this.statements,
@@ -2378,7 +2595,10 @@ class ERBBeginNode extends Node {
2378
2595
  this.else_clause,
2379
2596
  this.ensure_clause,
2380
2597
  this.end_node,
2381
- ].filter(node => node !== null && node !== undefined);
2598
+ ];
2599
+ }
2600
+ compactChildNodes() {
2601
+ return this.childNodes().filter(node => node !== null && node !== undefined);
2382
2602
  }
2383
2603
  recursiveErrors() {
2384
2604
  return [
@@ -2449,12 +2669,18 @@ class ERBUnlessNode extends Node {
2449
2669
  this.else_clause = props.else_clause;
2450
2670
  this.end_node = props.end_node;
2451
2671
  }
2672
+ accept(visitor) {
2673
+ visitor.visitERBUnlessNode(this);
2674
+ }
2452
2675
  childNodes() {
2453
2676
  return [
2454
2677
  ...this.statements,
2455
2678
  this.else_clause,
2456
2679
  this.end_node,
2457
- ].filter(node => node !== null && node !== undefined);
2680
+ ];
2681
+ }
2682
+ compactChildNodes() {
2683
+ return this.childNodes().filter(node => node !== null && node !== undefined);
2458
2684
  }
2459
2685
  recursiveErrors() {
2460
2686
  return [
@@ -2490,16 +2716,156 @@ class ERBUnlessNode extends Node {
2490
2716
  return output;
2491
2717
  }
2492
2718
  }
2493
-
2494
- class HerbWarning {
2495
- message;
2496
- location;
2497
- static from(warning) {
2498
- return new HerbWarning(warning.message, Location.from(warning.location));
2719
+ class ERBYieldNode extends Node {
2720
+ tag_opening;
2721
+ content;
2722
+ tag_closing;
2723
+ static from(data) {
2724
+ return new ERBYieldNode({
2725
+ type: data.type,
2726
+ location: Location.from(data.location),
2727
+ errors: (data.errors || []).map(error => HerbError.from(error)),
2728
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
2729
+ content: data.content ? Token.from(data.content) : null,
2730
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
2731
+ });
2499
2732
  }
2500
- constructor(message, location) {
2501
- this.message = message;
2502
- this.location = location;
2733
+ constructor(props) {
2734
+ super(props.type, props.location, props.errors);
2735
+ this.tag_opening = props.tag_opening;
2736
+ this.content = props.content;
2737
+ this.tag_closing = props.tag_closing;
2738
+ }
2739
+ accept(visitor) {
2740
+ visitor.visitERBYieldNode(this);
2741
+ }
2742
+ childNodes() {
2743
+ return [];
2744
+ }
2745
+ compactChildNodes() {
2746
+ return this.childNodes().filter(node => node !== null && node !== undefined);
2747
+ }
2748
+ recursiveErrors() {
2749
+ return [
2750
+ ...this.errors,
2751
+ ].flat();
2752
+ }
2753
+ toJSON() {
2754
+ return {
2755
+ ...super.toJSON(),
2756
+ type: "AST_ERB_YIELD_NODE",
2757
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
2758
+ content: this.content ? this.content.toJSON() : null,
2759
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
2760
+ };
2761
+ }
2762
+ treeInspect() {
2763
+ let output = "";
2764
+ output += `@ ERBYieldNode ${this.location.treeInspectWithLabel()}\n`;
2765
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
2766
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
2767
+ output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
2768
+ output += `└── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
2769
+ // output += "\n";
2770
+ return output;
2771
+ }
2772
+ }
2773
+ class ERBInNode extends Node {
2774
+ tag_opening;
2775
+ content;
2776
+ tag_closing;
2777
+ statements;
2778
+ static from(data) {
2779
+ return new ERBInNode({
2780
+ type: data.type,
2781
+ location: Location.from(data.location),
2782
+ errors: (data.errors || []).map(error => HerbError.from(error)),
2783
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
2784
+ content: data.content ? Token.from(data.content) : null,
2785
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
2786
+ statements: (data.statements || []).map(node => fromSerializedNode(node)),
2787
+ });
2788
+ }
2789
+ constructor(props) {
2790
+ super(props.type, props.location, props.errors);
2791
+ this.tag_opening = props.tag_opening;
2792
+ this.content = props.content;
2793
+ this.tag_closing = props.tag_closing;
2794
+ this.statements = props.statements;
2795
+ }
2796
+ accept(visitor) {
2797
+ visitor.visitERBInNode(this);
2798
+ }
2799
+ childNodes() {
2800
+ return [
2801
+ ...this.statements,
2802
+ ];
2803
+ }
2804
+ compactChildNodes() {
2805
+ return this.childNodes().filter(node => node !== null && node !== undefined);
2806
+ }
2807
+ recursiveErrors() {
2808
+ return [
2809
+ ...this.errors,
2810
+ ...this.statements.map(node => node.recursiveErrors()),
2811
+ ].flat();
2812
+ }
2813
+ toJSON() {
2814
+ return {
2815
+ ...super.toJSON(),
2816
+ type: "AST_ERB_IN_NODE",
2817
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
2818
+ content: this.content ? this.content.toJSON() : null,
2819
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
2820
+ statements: this.statements.map(node => node.toJSON()),
2821
+ };
2822
+ }
2823
+ treeInspect() {
2824
+ let output = "";
2825
+ output += `@ ERBInNode ${this.location.treeInspectWithLabel()}\n`;
2826
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
2827
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
2828
+ output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
2829
+ output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
2830
+ output += `└── statements: ${this.inspectArray(this.statements, " ")}`;
2831
+ // output += "\n";
2832
+ return output;
2833
+ }
2834
+ }
2835
+ function fromSerializedNode(node) {
2836
+ switch (node.type) {
2837
+ case "AST_DOCUMENT_NODE": return DocumentNode.from(node);
2838
+ case "AST_LITERAL_NODE": return LiteralNode.from(node);
2839
+ case "AST_HTML_OPEN_TAG_NODE": return HTMLOpenTagNode.from(node);
2840
+ case "AST_HTML_CLOSE_TAG_NODE": return HTMLCloseTagNode.from(node);
2841
+ case "AST_HTML_SELF_CLOSE_TAG_NODE": return HTMLSelfCloseTagNode.from(node);
2842
+ case "AST_HTML_ELEMENT_NODE": return HTMLElementNode.from(node);
2843
+ case "AST_HTML_ATTRIBUTE_VALUE_NODE": return HTMLAttributeValueNode.from(node);
2844
+ case "AST_HTML_ATTRIBUTE_NAME_NODE": return HTMLAttributeNameNode.from(node);
2845
+ case "AST_HTML_ATTRIBUTE_NODE": return HTMLAttributeNode.from(node);
2846
+ case "AST_HTML_TEXT_NODE": return HTMLTextNode.from(node);
2847
+ case "AST_HTML_COMMENT_NODE": return HTMLCommentNode.from(node);
2848
+ case "AST_HTML_DOCTYPE_NODE": return HTMLDoctypeNode.from(node);
2849
+ case "AST_WHITESPACE_NODE": return WhitespaceNode.from(node);
2850
+ case "AST_ERB_CONTENT_NODE": return ERBContentNode.from(node);
2851
+ case "AST_ERB_END_NODE": return ERBEndNode.from(node);
2852
+ case "AST_ERB_ELSE_NODE": return ERBElseNode.from(node);
2853
+ case "AST_ERB_IF_NODE": return ERBIfNode.from(node);
2854
+ case "AST_ERB_BLOCK_NODE": return ERBBlockNode.from(node);
2855
+ case "AST_ERB_WHEN_NODE": return ERBWhenNode.from(node);
2856
+ case "AST_ERB_CASE_NODE": return ERBCaseNode.from(node);
2857
+ case "AST_ERB_CASE_MATCH_NODE": return ERBCaseMatchNode.from(node);
2858
+ case "AST_ERB_WHILE_NODE": return ERBWhileNode.from(node);
2859
+ case "AST_ERB_UNTIL_NODE": return ERBUntilNode.from(node);
2860
+ case "AST_ERB_FOR_NODE": return ERBForNode.from(node);
2861
+ case "AST_ERB_RESCUE_NODE": return ERBRescueNode.from(node);
2862
+ case "AST_ERB_ENSURE_NODE": return ERBEnsureNode.from(node);
2863
+ case "AST_ERB_BEGIN_NODE": return ERBBeginNode.from(node);
2864
+ case "AST_ERB_UNLESS_NODE": return ERBUnlessNode.from(node);
2865
+ case "AST_ERB_YIELD_NODE": return ERBYieldNode.from(node);
2866
+ case "AST_ERB_IN_NODE": return ERBInNode.from(node);
2867
+ default:
2868
+ throw new Error(`Unknown node type: ${node.type}`);
2503
2869
  }
2504
2870
  }
2505
2871
 
@@ -2533,7 +2899,7 @@ class ParseResult extends Result {
2533
2899
  * Determines if the parsing failed.
2534
2900
  * @returns `true` if there are errors, otherwise `false`.
2535
2901
  */
2536
- failed() {
2902
+ get failed() {
2537
2903
  // TODO: this should probably be recursive as noted in the Ruby version
2538
2904
  return this.errors.length > 0 || this.value.errors.length > 0;
2539
2905
  }
@@ -2541,8 +2907,8 @@ class ParseResult extends Result {
2541
2907
  * Determines if the parsing was successful.
2542
2908
  * @returns `true` if there are no errors, otherwise `false`.
2543
2909
  */
2544
- success() {
2545
- return !this.failed();
2910
+ get successful() {
2911
+ return this.errors.length === 0;
2546
2912
  }
2547
2913
  /**
2548
2914
  * Returns a pretty-printed JSON string of the errors.
@@ -2687,18 +3053,111 @@ class HerbBackend {
2687
3053
  }
2688
3054
  }
2689
3055
 
2690
- /**
2691
- * Represents a visitor that can traverse nodes.
2692
- */
3056
+ // NOTE: This file is generated by the templates/template.rb script and should not
3057
+ // be modified manually. See /Users/marcoroth/Development/herb-release/templates/javascript/packages/core/src/visitor.ts.erb
2693
3058
  class Visitor {
2694
- /**
2695
- * Visits a node and performs an action.
2696
- * @param node - The node to visit.
2697
- */
2698
3059
  visit(node) {
2699
- console.log("Node", node); // TODO: implement
3060
+ if (!node)
3061
+ return;
3062
+ node.accept(this);
3063
+ }
3064
+ visitAll(nodes) {
3065
+ nodes.forEach(node => node?.accept(this));
3066
+ }
3067
+ visitChildNodes(node) {
3068
+ node.compactChildNodes().forEach(node => node.accept(this));
3069
+ }
3070
+ visitDocumentNode(node) {
3071
+ this.visitChildNodes(node);
3072
+ }
3073
+ visitLiteralNode(node) {
3074
+ this.visitChildNodes(node);
3075
+ }
3076
+ visitHTMLOpenTagNode(node) {
3077
+ this.visitChildNodes(node);
3078
+ }
3079
+ visitHTMLCloseTagNode(node) {
3080
+ this.visitChildNodes(node);
3081
+ }
3082
+ visitHTMLSelfCloseTagNode(node) {
3083
+ this.visitChildNodes(node);
3084
+ }
3085
+ visitHTMLElementNode(node) {
3086
+ this.visitChildNodes(node);
3087
+ }
3088
+ visitHTMLAttributeValueNode(node) {
3089
+ this.visitChildNodes(node);
3090
+ }
3091
+ visitHTMLAttributeNameNode(node) {
3092
+ this.visitChildNodes(node);
3093
+ }
3094
+ visitHTMLAttributeNode(node) {
3095
+ this.visitChildNodes(node);
3096
+ }
3097
+ visitHTMLTextNode(node) {
3098
+ this.visitChildNodes(node);
3099
+ }
3100
+ visitHTMLCommentNode(node) {
3101
+ this.visitChildNodes(node);
3102
+ }
3103
+ visitHTMLDoctypeNode(node) {
3104
+ this.visitChildNodes(node);
3105
+ }
3106
+ visitWhitespaceNode(node) {
3107
+ this.visitChildNodes(node);
3108
+ }
3109
+ visitERBContentNode(node) {
3110
+ this.visitChildNodes(node);
3111
+ }
3112
+ visitERBEndNode(node) {
3113
+ this.visitChildNodes(node);
3114
+ }
3115
+ visitERBElseNode(node) {
3116
+ this.visitChildNodes(node);
3117
+ }
3118
+ visitERBIfNode(node) {
3119
+ this.visitChildNodes(node);
3120
+ }
3121
+ visitERBBlockNode(node) {
3122
+ this.visitChildNodes(node);
3123
+ }
3124
+ visitERBWhenNode(node) {
3125
+ this.visitChildNodes(node);
3126
+ }
3127
+ visitERBCaseNode(node) {
3128
+ this.visitChildNodes(node);
3129
+ }
3130
+ visitERBCaseMatchNode(node) {
3131
+ this.visitChildNodes(node);
3132
+ }
3133
+ visitERBWhileNode(node) {
3134
+ this.visitChildNodes(node);
3135
+ }
3136
+ visitERBUntilNode(node) {
3137
+ this.visitChildNodes(node);
3138
+ }
3139
+ visitERBForNode(node) {
3140
+ this.visitChildNodes(node);
3141
+ }
3142
+ visitERBRescueNode(node) {
3143
+ this.visitChildNodes(node);
3144
+ }
3145
+ visitERBEnsureNode(node) {
3146
+ this.visitChildNodes(node);
3147
+ }
3148
+ visitERBBeginNode(node) {
3149
+ this.visitChildNodes(node);
3150
+ }
3151
+ visitERBUnlessNode(node) {
3152
+ this.visitChildNodes(node);
3153
+ }
3154
+ visitERBYieldNode(node) {
3155
+ this.visitChildNodes(node);
3156
+ }
3157
+ visitERBInNode(node) {
3158
+ this.visitChildNodes(node);
2700
3159
  }
2701
3160
  }
2702
3161
 
2703
- export { ASTNode, DocumentNode, ERBBeginNode, ERBBlockNode, ERBCaseNode, ERBContentNode, ERBElseNode, ERBEndNode, ERBEnsureNode, ERBForNode, ERBIfNode, ERBRescueNode, ERBUnlessNode, ERBUntilNode, ERBWhenNode, ERBWhileNode, HTMLAttributeNameNode, HTMLAttributeNode, HTMLAttributeValueNode, HTMLCloseTagNode, HTMLCommentNode, HTMLDoctypeNode, HTMLElementNode, HTMLOpenTagNode, HTMLSelfCloseTagNode, HTMLTextNode, HerbBackend, LexResult, LiteralNode, Location, MissingClosingTagError, MissingOpeningTagError, ParseResult, Position, QuotesMismatchError, Range, Result, RubyParseError, TagNamesMismatchError, Token, TokenList, UnclosedElementError, UnexpectedError, UnexpectedTokenError, Visitor, VoidElementClosingTagError, WhitespaceNode, _TYPECHECK, convertToUTF8, ensureLibHerbBackend, ensureString, fromSerializedError, fromSerializedNode, isLibHerbBackend };
3162
+ export { DocumentNode, ERBBeginNode, ERBBlockNode, ERBCaseMatchNode, ERBCaseNode, ERBContentNode, ERBElseNode, ERBEndNode, ERBEnsureNode, ERBForNode, ERBIfNode, ERBInNode, ERBRescueNode, ERBUnlessNode, ERBUntilNode, ERBWhenNode, ERBWhileNode, ERBYieldNode, HTMLAttributeNameNode, HTMLAttributeNode, HTMLAttributeValueNode, HTMLCloseTagNode, HTMLCommentNode, HTMLDoctypeNode, HTMLElementNode, HTMLOpenTagNode, HTMLSelfCloseTagNode, HTMLTextNode, HerbBackend, HerbError, HerbWarning, LexResult, LiteralNode, Location, MissingClosingTagError, MissingOpeningTagError, Node, ParseResult, Position, QuotesMismatchError, Range, Result, RubyParseError, TagNamesMismatchError, Token, TokenList, UnclosedElementError, UnexpectedError, UnexpectedTokenError, Visitor, VoidElementClosingTagError, WhitespaceNode, _TYPECHECK, convertToUTF8, ensureLibHerbBackend, ensureString, fromSerializedError, fromSerializedNode, isLibHerbBackend };
2704
3163
  //# sourceMappingURL=herb-core.browser.js.map