@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.
@@ -4,13 +4,6 @@
4
4
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Herb = {}));
5
5
  })(this, (function (exports) { 'use strict';
6
6
 
7
- class ASTNode {
8
- errors;
9
- constructor() {
10
- this.errors = [];
11
- }
12
- }
13
-
14
7
  const expectedFunctions = [
15
8
  "parse",
16
9
  "lex",
@@ -175,6 +168,8 @@
175
168
  }
176
169
  }
177
170
 
171
+ // NOTE: This file is generated by the templates/template.rb script and should not
172
+ // be modified manually. See /Users/marcoroth/Development/herb-release/templates/javascript/packages/core/src/errors.ts.erb
178
173
  class HerbError {
179
174
  type;
180
175
  message;
@@ -198,24 +193,6 @@
198
193
  return this.treeInspect(0);
199
194
  }
200
195
  }
201
-
202
- // NOTE: This file is generated by the templates/template.rb script and should not
203
- // be modified manually. See /Users/marcoroth/Development/herb-release/templates/javascript/packages/core/src/errors.ts.erb
204
- function fromSerializedError(error) {
205
- switch (error.type) {
206
- case "UNEXPECTED_ERROR": return UnexpectedError.from(error);
207
- case "UNEXPECTED_TOKEN_ERROR": return UnexpectedTokenError.from(error);
208
- case "MISSING_OPENING_TAG_ERROR": return MissingOpeningTagError.from(error);
209
- case "MISSING_CLOSING_TAG_ERROR": return MissingClosingTagError.from(error);
210
- case "TAG_NAMES_MISMATCH_ERROR": return TagNamesMismatchError.from(error);
211
- case "QUOTES_MISMATCH_ERROR": return QuotesMismatchError.from(error);
212
- case "VOID_ELEMENT_CLOSING_TAG_ERROR": return VoidElementClosingTagError.from(error);
213
- case "UNCLOSED_ELEMENT_ERROR": return UnclosedElementError.from(error);
214
- case "RUBY_PARSE_ERROR": return RubyParseError.from(error);
215
- default:
216
- throw new Error(`Unknown node type: ${error.type}`);
217
- }
218
- }
219
196
  class UnexpectedError extends HerbError {
220
197
  description;
221
198
  expected;
@@ -738,9 +715,24 @@
738
715
  return output;
739
716
  }
740
717
  }
718
+ function fromSerializedError(error) {
719
+ switch (error.type) {
720
+ case "UNEXPECTED_ERROR": return UnexpectedError.from(error);
721
+ case "UNEXPECTED_TOKEN_ERROR": return UnexpectedTokenError.from(error);
722
+ case "MISSING_OPENING_TAG_ERROR": return MissingOpeningTagError.from(error);
723
+ case "MISSING_CLOSING_TAG_ERROR": return MissingClosingTagError.from(error);
724
+ case "TAG_NAMES_MISMATCH_ERROR": return TagNamesMismatchError.from(error);
725
+ case "QUOTES_MISMATCH_ERROR": return QuotesMismatchError.from(error);
726
+ case "VOID_ELEMENT_CLOSING_TAG_ERROR": return VoidElementClosingTagError.from(error);
727
+ case "UNCLOSED_ELEMENT_ERROR": return UnclosedElementError.from(error);
728
+ case "RUBY_PARSE_ERROR": return RubyParseError.from(error);
729
+ default:
730
+ throw new Error(`Unknown node type: ${error.type}`);
731
+ }
732
+ }
741
733
 
742
734
  var name = "@herb-tools/core";
743
- var version = "0.1.1";
735
+ var version = "0.3.0";
744
736
  var packageJSON = {
745
737
  name: name,
746
738
  version: version};
@@ -769,11 +761,19 @@
769
761
  this.warnings = warnings || [];
770
762
  this.errors = errors || [];
771
763
  }
772
- success() {
773
- return false;
764
+ /**
765
+ * Determines if the parsing was successful.
766
+ * @returns `true` if there are no errors, otherwise `false`.
767
+ */
768
+ get successful() {
769
+ return this.errors.length === 0;
774
770
  }
775
- failed() {
776
- return true;
771
+ /**
772
+ * Determines if the parsing failed.
773
+ * @returns `true` if there are errors, otherwise `false`.
774
+ */
775
+ get failed() {
776
+ return this.errors.length > 0;
777
777
  }
778
778
  }
779
779
 
@@ -814,6 +814,18 @@
814
814
  }
815
815
  }
816
816
 
817
+ class HerbWarning {
818
+ message;
819
+ location;
820
+ static from(warning) {
821
+ return new HerbWarning(warning.message, Location.from(warning.location));
822
+ }
823
+ constructor(message, location) {
824
+ this.message = message;
825
+ this.location = location;
826
+ }
827
+ }
828
+
817
829
  /**
818
830
  * Represents the result of a lexical analysis, extending the base `Result` class.
819
831
  * It contains the token list, source code, warnings, and errors.
@@ -827,7 +839,7 @@
827
839
  * @returns A new `LexResult` instance.
828
840
  */
829
841
  static from(result) {
830
- return new LexResult(TokenList.from(result.tokens || []), result.source, result.warnings, result.errors);
842
+ return new LexResult(TokenList.from(result.tokens || []), result.source, result.warnings.map((warning) => HerbWarning.from(warning)), result.errors.map((error) => HerbError.from(error)));
831
843
  }
832
844
  /**
833
845
  * Constructs a new `LexResult`.
@@ -844,14 +856,14 @@
844
856
  * Determines if the lexing was successful.
845
857
  * @returns `true` if there are no errors, otherwise `false`.
846
858
  */
847
- success() {
859
+ get successful() {
848
860
  return this.errors.length === 0;
849
861
  }
850
862
  /**
851
863
  * Determines if the lexing failed.
852
864
  * @returns `true` if there are errors, otherwise `false`.
853
865
  */
854
- failed() {
866
+ get failed() {
855
867
  return this.errors.length > 0;
856
868
  }
857
869
  /**
@@ -868,6 +880,8 @@
868
880
  }
869
881
  }
870
882
 
883
+ // NOTE: This file is generated by the templates/template.rb script and should not
884
+ // be modified manually. See /Users/marcoroth/Development/herb-release/templates/javascript/packages/core/src/nodes.ts.erb
871
885
  class Node {
872
886
  type;
873
887
  location;
@@ -890,6 +904,9 @@
890
904
  inspect() {
891
905
  return this.treeInspect(0);
892
906
  }
907
+ get isSingleLine() {
908
+ return this.location.start.line === this.location.end.line;
909
+ }
893
910
  inspectArray(array, prefix) {
894
911
  if (!array)
895
912
  return "∅\n";
@@ -926,42 +943,6 @@
926
943
  return output;
927
944
  }
928
945
  }
929
-
930
- // NOTE: This file is generated by the templates/template.rb script and should not
931
- // be modified manually. See /Users/marcoroth/Development/herb-release/templates/javascript/packages/core/src/nodes.ts.erb
932
- function fromSerializedNode(node) {
933
- switch (node.type) {
934
- case "AST_DOCUMENT_NODE": return DocumentNode.from(node);
935
- case "AST_LITERAL_NODE": return LiteralNode.from(node);
936
- case "AST_HTML_OPEN_TAG_NODE": return HTMLOpenTagNode.from(node);
937
- case "AST_HTML_CLOSE_TAG_NODE": return HTMLCloseTagNode.from(node);
938
- case "AST_HTML_SELF_CLOSE_TAG_NODE": return HTMLSelfCloseTagNode.from(node);
939
- case "AST_HTML_ELEMENT_NODE": return HTMLElementNode.from(node);
940
- case "AST_HTML_ATTRIBUTE_VALUE_NODE": return HTMLAttributeValueNode.from(node);
941
- case "AST_HTML_ATTRIBUTE_NAME_NODE": return HTMLAttributeNameNode.from(node);
942
- case "AST_HTML_ATTRIBUTE_NODE": return HTMLAttributeNode.from(node);
943
- case "AST_HTML_TEXT_NODE": return HTMLTextNode.from(node);
944
- case "AST_HTML_COMMENT_NODE": return HTMLCommentNode.from(node);
945
- case "AST_HTML_DOCTYPE_NODE": return HTMLDoctypeNode.from(node);
946
- case "AST_WHITESPACE_NODE": return WhitespaceNode.from(node);
947
- case "AST_ERB_CONTENT_NODE": return ERBContentNode.from(node);
948
- case "AST_ERB_END_NODE": return ERBEndNode.from(node);
949
- case "AST_ERB_ELSE_NODE": return ERBElseNode.from(node);
950
- case "AST_ERB_IF_NODE": return ERBIfNode.from(node);
951
- case "AST_ERB_BLOCK_NODE": return ERBBlockNode.from(node);
952
- case "AST_ERB_WHEN_NODE": return ERBWhenNode.from(node);
953
- case "AST_ERB_CASE_NODE": return ERBCaseNode.from(node);
954
- case "AST_ERB_WHILE_NODE": return ERBWhileNode.from(node);
955
- case "AST_ERB_UNTIL_NODE": return ERBUntilNode.from(node);
956
- case "AST_ERB_FOR_NODE": return ERBForNode.from(node);
957
- case "AST_ERB_RESCUE_NODE": return ERBRescueNode.from(node);
958
- case "AST_ERB_ENSURE_NODE": return ERBEnsureNode.from(node);
959
- case "AST_ERB_BEGIN_NODE": return ERBBeginNode.from(node);
960
- case "AST_ERB_UNLESS_NODE": return ERBUnlessNode.from(node);
961
- default:
962
- throw new Error(`Unknown node type: ${node.type}`);
963
- }
964
- }
965
946
  class DocumentNode extends Node {
966
947
  children;
967
948
  static from(data) {
@@ -976,10 +957,16 @@
976
957
  super(props.type, props.location, props.errors);
977
958
  this.children = props.children;
978
959
  }
960
+ accept(visitor) {
961
+ visitor.visitDocumentNode(this);
962
+ }
979
963
  childNodes() {
980
964
  return [
981
965
  ...this.children,
982
- ].filter(node => node !== null && node !== undefined);
966
+ ];
967
+ }
968
+ compactChildNodes() {
969
+ return this.childNodes().filter(node => node !== null && node !== undefined);
983
970
  }
984
971
  recursiveErrors() {
985
972
  return [
@@ -1017,8 +1004,14 @@
1017
1004
  super(props.type, props.location, props.errors);
1018
1005
  this.content = convertToUTF8(props.content);
1019
1006
  }
1007
+ accept(visitor) {
1008
+ visitor.visitLiteralNode(this);
1009
+ }
1020
1010
  childNodes() {
1021
- return [].filter(node => node !== null && node !== undefined);
1011
+ return [];
1012
+ }
1013
+ compactChildNodes() {
1014
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1022
1015
  }
1023
1016
  recursiveErrors() {
1024
1017
  return [
@@ -1067,10 +1060,16 @@
1067
1060
  this.children = props.children;
1068
1061
  this.is_void = props.is_void;
1069
1062
  }
1063
+ accept(visitor) {
1064
+ visitor.visitHTMLOpenTagNode(this);
1065
+ }
1070
1066
  childNodes() {
1071
1067
  return [
1072
1068
  ...this.children,
1073
- ].filter(node => node !== null && node !== undefined);
1069
+ ];
1070
+ }
1071
+ compactChildNodes() {
1072
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1074
1073
  }
1075
1074
  recursiveErrors() {
1076
1075
  return [
@@ -1122,8 +1121,14 @@
1122
1121
  this.tag_name = props.tag_name;
1123
1122
  this.tag_closing = props.tag_closing;
1124
1123
  }
1124
+ accept(visitor) {
1125
+ visitor.visitHTMLCloseTagNode(this);
1126
+ }
1125
1127
  childNodes() {
1126
- return [].filter(node => node !== null && node !== undefined);
1128
+ return [];
1129
+ }
1130
+ compactChildNodes() {
1131
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1127
1132
  }
1128
1133
  recursiveErrors() {
1129
1134
  return [
@@ -1176,10 +1181,16 @@
1176
1181
  this.tag_closing = props.tag_closing;
1177
1182
  this.is_void = props.is_void;
1178
1183
  }
1184
+ accept(visitor) {
1185
+ visitor.visitHTMLSelfCloseTagNode(this);
1186
+ }
1179
1187
  childNodes() {
1180
1188
  return [
1181
1189
  ...this.attributes,
1182
- ].filter(node => node !== null && node !== undefined);
1190
+ ];
1191
+ }
1192
+ compactChildNodes() {
1193
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1183
1194
  }
1184
1195
  recursiveErrors() {
1185
1196
  return [
@@ -1237,12 +1248,18 @@
1237
1248
  this.close_tag = props.close_tag;
1238
1249
  this.is_void = props.is_void;
1239
1250
  }
1251
+ accept(visitor) {
1252
+ visitor.visitHTMLElementNode(this);
1253
+ }
1240
1254
  childNodes() {
1241
1255
  return [
1242
1256
  this.open_tag,
1243
1257
  ...this.body,
1244
1258
  this.close_tag,
1245
- ].filter(node => node !== null && node !== undefined);
1259
+ ];
1260
+ }
1261
+ compactChildNodes() {
1262
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1246
1263
  }
1247
1264
  recursiveErrors() {
1248
1265
  return [
@@ -1299,10 +1316,16 @@
1299
1316
  this.close_quote = props.close_quote;
1300
1317
  this.quoted = props.quoted;
1301
1318
  }
1319
+ accept(visitor) {
1320
+ visitor.visitHTMLAttributeValueNode(this);
1321
+ }
1302
1322
  childNodes() {
1303
1323
  return [
1304
1324
  ...this.children,
1305
- ].filter(node => node !== null && node !== undefined);
1325
+ ];
1326
+ }
1327
+ compactChildNodes() {
1328
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1306
1329
  }
1307
1330
  recursiveErrors() {
1308
1331
  return [
@@ -1346,8 +1369,14 @@
1346
1369
  super(props.type, props.location, props.errors);
1347
1370
  this.name = props.name;
1348
1371
  }
1372
+ accept(visitor) {
1373
+ visitor.visitHTMLAttributeNameNode(this);
1374
+ }
1349
1375
  childNodes() {
1350
- return [].filter(node => node !== null && node !== undefined);
1376
+ return [];
1377
+ }
1378
+ compactChildNodes() {
1379
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1351
1380
  }
1352
1381
  recursiveErrors() {
1353
1382
  return [
@@ -1390,11 +1419,17 @@
1390
1419
  this.equals = props.equals;
1391
1420
  this.value = props.value;
1392
1421
  }
1422
+ accept(visitor) {
1423
+ visitor.visitHTMLAttributeNode(this);
1424
+ }
1393
1425
  childNodes() {
1394
1426
  return [
1395
1427
  this.name,
1396
1428
  this.value,
1397
- ].filter(node => node !== null && node !== undefined);
1429
+ ];
1430
+ }
1431
+ compactChildNodes() {
1432
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1398
1433
  }
1399
1434
  recursiveErrors() {
1400
1435
  return [
@@ -1437,8 +1472,14 @@
1437
1472
  super(props.type, props.location, props.errors);
1438
1473
  this.content = convertToUTF8(props.content);
1439
1474
  }
1475
+ accept(visitor) {
1476
+ visitor.visitHTMLTextNode(this);
1477
+ }
1440
1478
  childNodes() {
1441
- return [].filter(node => node !== null && node !== undefined);
1479
+ return [];
1480
+ }
1481
+ compactChildNodes() {
1482
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1442
1483
  }
1443
1484
  recursiveErrors() {
1444
1485
  return [
@@ -1481,10 +1522,16 @@
1481
1522
  this.children = props.children;
1482
1523
  this.comment_end = props.comment_end;
1483
1524
  }
1525
+ accept(visitor) {
1526
+ visitor.visitHTMLCommentNode(this);
1527
+ }
1484
1528
  childNodes() {
1485
1529
  return [
1486
1530
  ...this.children,
1487
- ].filter(node => node !== null && node !== undefined);
1531
+ ];
1532
+ }
1533
+ compactChildNodes() {
1534
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1488
1535
  }
1489
1536
  recursiveErrors() {
1490
1537
  return [
@@ -1532,10 +1579,16 @@
1532
1579
  this.children = props.children;
1533
1580
  this.tag_closing = props.tag_closing;
1534
1581
  }
1582
+ accept(visitor) {
1583
+ visitor.visitHTMLDoctypeNode(this);
1584
+ }
1535
1585
  childNodes() {
1536
1586
  return [
1537
1587
  ...this.children,
1538
- ].filter(node => node !== null && node !== undefined);
1588
+ ];
1589
+ }
1590
+ compactChildNodes() {
1591
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1539
1592
  }
1540
1593
  recursiveErrors() {
1541
1594
  return [
@@ -1577,8 +1630,14 @@
1577
1630
  super(props.type, props.location, props.errors);
1578
1631
  this.value = props.value;
1579
1632
  }
1633
+ accept(visitor) {
1634
+ visitor.visitWhitespaceNode(this);
1635
+ }
1580
1636
  childNodes() {
1581
- return [].filter(node => node !== null && node !== undefined);
1637
+ return [];
1638
+ }
1639
+ compactChildNodes() {
1640
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1582
1641
  }
1583
1642
  recursiveErrors() {
1584
1643
  return [
@@ -1630,8 +1689,14 @@
1630
1689
  this.parsed = props.parsed;
1631
1690
  this.valid = props.valid;
1632
1691
  }
1692
+ accept(visitor) {
1693
+ visitor.visitERBContentNode(this);
1694
+ }
1633
1695
  childNodes() {
1634
- return [].filter(node => node !== null && node !== undefined);
1696
+ return [];
1697
+ }
1698
+ compactChildNodes() {
1699
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1635
1700
  }
1636
1701
  recursiveErrors() {
1637
1702
  return [
@@ -1684,8 +1749,14 @@
1684
1749
  this.content = props.content;
1685
1750
  this.tag_closing = props.tag_closing;
1686
1751
  }
1752
+ accept(visitor) {
1753
+ visitor.visitERBEndNode(this);
1754
+ }
1687
1755
  childNodes() {
1688
- return [].filter(node => node !== null && node !== undefined);
1756
+ return [];
1757
+ }
1758
+ compactChildNodes() {
1759
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1689
1760
  }
1690
1761
  recursiveErrors() {
1691
1762
  return [
@@ -1735,10 +1806,16 @@
1735
1806
  this.tag_closing = props.tag_closing;
1736
1807
  this.statements = props.statements;
1737
1808
  }
1809
+ accept(visitor) {
1810
+ visitor.visitERBElseNode(this);
1811
+ }
1738
1812
  childNodes() {
1739
1813
  return [
1740
1814
  ...this.statements,
1741
- ].filter(node => node !== null && node !== undefined);
1815
+ ];
1816
+ }
1817
+ compactChildNodes() {
1818
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1742
1819
  }
1743
1820
  recursiveErrors() {
1744
1821
  return [
@@ -1797,12 +1874,18 @@
1797
1874
  this.subsequent = props.subsequent;
1798
1875
  this.end_node = props.end_node;
1799
1876
  }
1877
+ accept(visitor) {
1878
+ visitor.visitERBIfNode(this);
1879
+ }
1800
1880
  childNodes() {
1801
1881
  return [
1802
1882
  ...this.statements,
1803
1883
  this.subsequent,
1804
1884
  this.end_node,
1805
- ].filter(node => node !== null && node !== undefined);
1885
+ ];
1886
+ }
1887
+ compactChildNodes() {
1888
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1806
1889
  }
1807
1890
  recursiveErrors() {
1808
1891
  return [
@@ -1864,11 +1947,17 @@
1864
1947
  this.body = props.body;
1865
1948
  this.end_node = props.end_node;
1866
1949
  }
1950
+ accept(visitor) {
1951
+ visitor.visitERBBlockNode(this);
1952
+ }
1867
1953
  childNodes() {
1868
1954
  return [
1869
1955
  ...this.body,
1870
1956
  this.end_node,
1871
- ].filter(node => node !== null && node !== undefined);
1957
+ ];
1958
+ }
1959
+ compactChildNodes() {
1960
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1872
1961
  }
1873
1962
  recursiveErrors() {
1874
1963
  return [
@@ -1924,10 +2013,16 @@
1924
2013
  this.tag_closing = props.tag_closing;
1925
2014
  this.statements = props.statements;
1926
2015
  }
2016
+ accept(visitor) {
2017
+ visitor.visitERBWhenNode(this);
2018
+ }
1927
2019
  childNodes() {
1928
2020
  return [
1929
2021
  ...this.statements,
1930
- ].filter(node => node !== null && node !== undefined);
2022
+ ];
2023
+ }
2024
+ compactChildNodes() {
2025
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1931
2026
  }
1932
2027
  recursiveErrors() {
1933
2028
  return [
@@ -1989,13 +2084,19 @@
1989
2084
  this.else_clause = props.else_clause;
1990
2085
  this.end_node = props.end_node;
1991
2086
  }
2087
+ accept(visitor) {
2088
+ visitor.visitERBCaseNode(this);
2089
+ }
1992
2090
  childNodes() {
1993
2091
  return [
1994
2092
  ...this.children,
1995
2093
  ...this.conditions,
1996
2094
  this.else_clause,
1997
2095
  this.end_node,
1998
- ].filter(node => node !== null && node !== undefined);
2096
+ ];
2097
+ }
2098
+ compactChildNodes() {
2099
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1999
2100
  }
2000
2101
  recursiveErrors() {
2001
2102
  return [
@@ -2034,6 +2135,89 @@
2034
2135
  return output;
2035
2136
  }
2036
2137
  }
2138
+ class ERBCaseMatchNode extends Node {
2139
+ tag_opening;
2140
+ content;
2141
+ tag_closing;
2142
+ children;
2143
+ conditions;
2144
+ else_clause;
2145
+ end_node;
2146
+ static from(data) {
2147
+ return new ERBCaseMatchNode({
2148
+ type: data.type,
2149
+ location: Location.from(data.location),
2150
+ errors: (data.errors || []).map(error => HerbError.from(error)),
2151
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
2152
+ content: data.content ? Token.from(data.content) : null,
2153
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
2154
+ children: (data.children || []).map(node => fromSerializedNode(node)),
2155
+ conditions: (data.conditions || []).map(node => fromSerializedNode(node)),
2156
+ else_clause: data.else_clause ? fromSerializedNode(data.else_clause) : null,
2157
+ end_node: data.end_node ? fromSerializedNode(data.end_node) : null,
2158
+ });
2159
+ }
2160
+ constructor(props) {
2161
+ super(props.type, props.location, props.errors);
2162
+ this.tag_opening = props.tag_opening;
2163
+ this.content = props.content;
2164
+ this.tag_closing = props.tag_closing;
2165
+ this.children = props.children;
2166
+ this.conditions = props.conditions;
2167
+ this.else_clause = props.else_clause;
2168
+ this.end_node = props.end_node;
2169
+ }
2170
+ accept(visitor) {
2171
+ visitor.visitERBCaseMatchNode(this);
2172
+ }
2173
+ childNodes() {
2174
+ return [
2175
+ ...this.children,
2176
+ ...this.conditions,
2177
+ this.else_clause,
2178
+ this.end_node,
2179
+ ];
2180
+ }
2181
+ compactChildNodes() {
2182
+ return this.childNodes().filter(node => node !== null && node !== undefined);
2183
+ }
2184
+ recursiveErrors() {
2185
+ return [
2186
+ ...this.errors,
2187
+ ...this.children.map(node => node.recursiveErrors()),
2188
+ ...this.conditions.map(node => node.recursiveErrors()),
2189
+ this.else_clause ? this.else_clause.recursiveErrors() : [],
2190
+ this.end_node ? this.end_node.recursiveErrors() : [],
2191
+ ].flat();
2192
+ }
2193
+ toJSON() {
2194
+ return {
2195
+ ...super.toJSON(),
2196
+ type: "AST_ERB_CASE_MATCH_NODE",
2197
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
2198
+ content: this.content ? this.content.toJSON() : null,
2199
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
2200
+ children: this.children.map(node => node.toJSON()),
2201
+ conditions: this.conditions.map(node => node.toJSON()),
2202
+ else_clause: this.else_clause ? this.else_clause.toJSON() : null,
2203
+ end_node: this.end_node ? this.end_node.toJSON() : null,
2204
+ };
2205
+ }
2206
+ treeInspect() {
2207
+ let output = "";
2208
+ output += `@ ERBCaseMatchNode ${this.location.treeInspectWithLabel()}\n`;
2209
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
2210
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
2211
+ output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
2212
+ output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
2213
+ output += `├── children: ${this.inspectArray(this.children, "│ ")}`;
2214
+ output += `├── conditions: ${this.inspectArray(this.conditions, "│ ")}`;
2215
+ output += `├── else_clause: ${this.inspectNode(this.else_clause, "│ ")}`;
2216
+ output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
2217
+ // output += "\n";
2218
+ return output;
2219
+ }
2220
+ }
2037
2221
  class ERBWhileNode extends Node {
2038
2222
  tag_opening;
2039
2223
  content;
@@ -2060,11 +2244,17 @@
2060
2244
  this.statements = props.statements;
2061
2245
  this.end_node = props.end_node;
2062
2246
  }
2247
+ accept(visitor) {
2248
+ visitor.visitERBWhileNode(this);
2249
+ }
2063
2250
  childNodes() {
2064
2251
  return [
2065
2252
  ...this.statements,
2066
2253
  this.end_node,
2067
- ].filter(node => node !== null && node !== undefined);
2254
+ ];
2255
+ }
2256
+ compactChildNodes() {
2257
+ return this.childNodes().filter(node => node !== null && node !== undefined);
2068
2258
  }
2069
2259
  recursiveErrors() {
2070
2260
  return [
@@ -2123,11 +2313,17 @@
2123
2313
  this.statements = props.statements;
2124
2314
  this.end_node = props.end_node;
2125
2315
  }
2316
+ accept(visitor) {
2317
+ visitor.visitERBUntilNode(this);
2318
+ }
2126
2319
  childNodes() {
2127
2320
  return [
2128
2321
  ...this.statements,
2129
2322
  this.end_node,
2130
- ].filter(node => node !== null && node !== undefined);
2323
+ ];
2324
+ }
2325
+ compactChildNodes() {
2326
+ return this.childNodes().filter(node => node !== null && node !== undefined);
2131
2327
  }
2132
2328
  recursiveErrors() {
2133
2329
  return [
@@ -2186,11 +2382,17 @@
2186
2382
  this.statements = props.statements;
2187
2383
  this.end_node = props.end_node;
2188
2384
  }
2385
+ accept(visitor) {
2386
+ visitor.visitERBForNode(this);
2387
+ }
2189
2388
  childNodes() {
2190
2389
  return [
2191
2390
  ...this.statements,
2192
2391
  this.end_node,
2193
- ].filter(node => node !== null && node !== undefined);
2392
+ ];
2393
+ }
2394
+ compactChildNodes() {
2395
+ return this.childNodes().filter(node => node !== null && node !== undefined);
2194
2396
  }
2195
2397
  recursiveErrors() {
2196
2398
  return [
@@ -2249,11 +2451,17 @@
2249
2451
  this.statements = props.statements;
2250
2452
  this.subsequent = props.subsequent;
2251
2453
  }
2454
+ accept(visitor) {
2455
+ visitor.visitERBRescueNode(this);
2456
+ }
2252
2457
  childNodes() {
2253
2458
  return [
2254
2459
  ...this.statements,
2255
2460
  this.subsequent,
2256
- ].filter(node => node !== null && node !== undefined);
2461
+ ];
2462
+ }
2463
+ compactChildNodes() {
2464
+ return this.childNodes().filter(node => node !== null && node !== undefined);
2257
2465
  }
2258
2466
  recursiveErrors() {
2259
2467
  return [
@@ -2309,10 +2517,16 @@
2309
2517
  this.tag_closing = props.tag_closing;
2310
2518
  this.statements = props.statements;
2311
2519
  }
2520
+ accept(visitor) {
2521
+ visitor.visitERBEnsureNode(this);
2522
+ }
2312
2523
  childNodes() {
2313
2524
  return [
2314
2525
  ...this.statements,
2315
- ].filter(node => node !== null && node !== undefined);
2526
+ ];
2527
+ }
2528
+ compactChildNodes() {
2529
+ return this.childNodes().filter(node => node !== null && node !== undefined);
2316
2530
  }
2317
2531
  recursiveErrors() {
2318
2532
  return [
@@ -2377,6 +2591,9 @@
2377
2591
  this.ensure_clause = props.ensure_clause;
2378
2592
  this.end_node = props.end_node;
2379
2593
  }
2594
+ accept(visitor) {
2595
+ visitor.visitERBBeginNode(this);
2596
+ }
2380
2597
  childNodes() {
2381
2598
  return [
2382
2599
  ...this.statements,
@@ -2384,7 +2601,10 @@
2384
2601
  this.else_clause,
2385
2602
  this.ensure_clause,
2386
2603
  this.end_node,
2387
- ].filter(node => node !== null && node !== undefined);
2604
+ ];
2605
+ }
2606
+ compactChildNodes() {
2607
+ return this.childNodes().filter(node => node !== null && node !== undefined);
2388
2608
  }
2389
2609
  recursiveErrors() {
2390
2610
  return [
@@ -2455,12 +2675,18 @@
2455
2675
  this.else_clause = props.else_clause;
2456
2676
  this.end_node = props.end_node;
2457
2677
  }
2678
+ accept(visitor) {
2679
+ visitor.visitERBUnlessNode(this);
2680
+ }
2458
2681
  childNodes() {
2459
2682
  return [
2460
2683
  ...this.statements,
2461
2684
  this.else_clause,
2462
2685
  this.end_node,
2463
- ].filter(node => node !== null && node !== undefined);
2686
+ ];
2687
+ }
2688
+ compactChildNodes() {
2689
+ return this.childNodes().filter(node => node !== null && node !== undefined);
2464
2690
  }
2465
2691
  recursiveErrors() {
2466
2692
  return [
@@ -2496,16 +2722,156 @@
2496
2722
  return output;
2497
2723
  }
2498
2724
  }
2499
-
2500
- class HerbWarning {
2501
- message;
2502
- location;
2503
- static from(warning) {
2504
- return new HerbWarning(warning.message, Location.from(warning.location));
2725
+ class ERBYieldNode extends Node {
2726
+ tag_opening;
2727
+ content;
2728
+ tag_closing;
2729
+ static from(data) {
2730
+ return new ERBYieldNode({
2731
+ type: data.type,
2732
+ location: Location.from(data.location),
2733
+ errors: (data.errors || []).map(error => HerbError.from(error)),
2734
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
2735
+ content: data.content ? Token.from(data.content) : null,
2736
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
2737
+ });
2505
2738
  }
2506
- constructor(message, location) {
2507
- this.message = message;
2508
- this.location = location;
2739
+ constructor(props) {
2740
+ super(props.type, props.location, props.errors);
2741
+ this.tag_opening = props.tag_opening;
2742
+ this.content = props.content;
2743
+ this.tag_closing = props.tag_closing;
2744
+ }
2745
+ accept(visitor) {
2746
+ visitor.visitERBYieldNode(this);
2747
+ }
2748
+ childNodes() {
2749
+ return [];
2750
+ }
2751
+ compactChildNodes() {
2752
+ return this.childNodes().filter(node => node !== null && node !== undefined);
2753
+ }
2754
+ recursiveErrors() {
2755
+ return [
2756
+ ...this.errors,
2757
+ ].flat();
2758
+ }
2759
+ toJSON() {
2760
+ return {
2761
+ ...super.toJSON(),
2762
+ type: "AST_ERB_YIELD_NODE",
2763
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
2764
+ content: this.content ? this.content.toJSON() : null,
2765
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
2766
+ };
2767
+ }
2768
+ treeInspect() {
2769
+ let output = "";
2770
+ output += `@ ERBYieldNode ${this.location.treeInspectWithLabel()}\n`;
2771
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
2772
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
2773
+ output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
2774
+ output += `└── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
2775
+ // output += "\n";
2776
+ return output;
2777
+ }
2778
+ }
2779
+ class ERBInNode extends Node {
2780
+ tag_opening;
2781
+ content;
2782
+ tag_closing;
2783
+ statements;
2784
+ static from(data) {
2785
+ return new ERBInNode({
2786
+ type: data.type,
2787
+ location: Location.from(data.location),
2788
+ errors: (data.errors || []).map(error => HerbError.from(error)),
2789
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
2790
+ content: data.content ? Token.from(data.content) : null,
2791
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
2792
+ statements: (data.statements || []).map(node => fromSerializedNode(node)),
2793
+ });
2794
+ }
2795
+ constructor(props) {
2796
+ super(props.type, props.location, props.errors);
2797
+ this.tag_opening = props.tag_opening;
2798
+ this.content = props.content;
2799
+ this.tag_closing = props.tag_closing;
2800
+ this.statements = props.statements;
2801
+ }
2802
+ accept(visitor) {
2803
+ visitor.visitERBInNode(this);
2804
+ }
2805
+ childNodes() {
2806
+ return [
2807
+ ...this.statements,
2808
+ ];
2809
+ }
2810
+ compactChildNodes() {
2811
+ return this.childNodes().filter(node => node !== null && node !== undefined);
2812
+ }
2813
+ recursiveErrors() {
2814
+ return [
2815
+ ...this.errors,
2816
+ ...this.statements.map(node => node.recursiveErrors()),
2817
+ ].flat();
2818
+ }
2819
+ toJSON() {
2820
+ return {
2821
+ ...super.toJSON(),
2822
+ type: "AST_ERB_IN_NODE",
2823
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
2824
+ content: this.content ? this.content.toJSON() : null,
2825
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
2826
+ statements: this.statements.map(node => node.toJSON()),
2827
+ };
2828
+ }
2829
+ treeInspect() {
2830
+ let output = "";
2831
+ output += `@ ERBInNode ${this.location.treeInspectWithLabel()}\n`;
2832
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
2833
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
2834
+ output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
2835
+ output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
2836
+ output += `└── statements: ${this.inspectArray(this.statements, " ")}`;
2837
+ // output += "\n";
2838
+ return output;
2839
+ }
2840
+ }
2841
+ function fromSerializedNode(node) {
2842
+ switch (node.type) {
2843
+ case "AST_DOCUMENT_NODE": return DocumentNode.from(node);
2844
+ case "AST_LITERAL_NODE": return LiteralNode.from(node);
2845
+ case "AST_HTML_OPEN_TAG_NODE": return HTMLOpenTagNode.from(node);
2846
+ case "AST_HTML_CLOSE_TAG_NODE": return HTMLCloseTagNode.from(node);
2847
+ case "AST_HTML_SELF_CLOSE_TAG_NODE": return HTMLSelfCloseTagNode.from(node);
2848
+ case "AST_HTML_ELEMENT_NODE": return HTMLElementNode.from(node);
2849
+ case "AST_HTML_ATTRIBUTE_VALUE_NODE": return HTMLAttributeValueNode.from(node);
2850
+ case "AST_HTML_ATTRIBUTE_NAME_NODE": return HTMLAttributeNameNode.from(node);
2851
+ case "AST_HTML_ATTRIBUTE_NODE": return HTMLAttributeNode.from(node);
2852
+ case "AST_HTML_TEXT_NODE": return HTMLTextNode.from(node);
2853
+ case "AST_HTML_COMMENT_NODE": return HTMLCommentNode.from(node);
2854
+ case "AST_HTML_DOCTYPE_NODE": return HTMLDoctypeNode.from(node);
2855
+ case "AST_WHITESPACE_NODE": return WhitespaceNode.from(node);
2856
+ case "AST_ERB_CONTENT_NODE": return ERBContentNode.from(node);
2857
+ case "AST_ERB_END_NODE": return ERBEndNode.from(node);
2858
+ case "AST_ERB_ELSE_NODE": return ERBElseNode.from(node);
2859
+ case "AST_ERB_IF_NODE": return ERBIfNode.from(node);
2860
+ case "AST_ERB_BLOCK_NODE": return ERBBlockNode.from(node);
2861
+ case "AST_ERB_WHEN_NODE": return ERBWhenNode.from(node);
2862
+ case "AST_ERB_CASE_NODE": return ERBCaseNode.from(node);
2863
+ case "AST_ERB_CASE_MATCH_NODE": return ERBCaseMatchNode.from(node);
2864
+ case "AST_ERB_WHILE_NODE": return ERBWhileNode.from(node);
2865
+ case "AST_ERB_UNTIL_NODE": return ERBUntilNode.from(node);
2866
+ case "AST_ERB_FOR_NODE": return ERBForNode.from(node);
2867
+ case "AST_ERB_RESCUE_NODE": return ERBRescueNode.from(node);
2868
+ case "AST_ERB_ENSURE_NODE": return ERBEnsureNode.from(node);
2869
+ case "AST_ERB_BEGIN_NODE": return ERBBeginNode.from(node);
2870
+ case "AST_ERB_UNLESS_NODE": return ERBUnlessNode.from(node);
2871
+ case "AST_ERB_YIELD_NODE": return ERBYieldNode.from(node);
2872
+ case "AST_ERB_IN_NODE": return ERBInNode.from(node);
2873
+ default:
2874
+ throw new Error(`Unknown node type: ${node.type}`);
2509
2875
  }
2510
2876
  }
2511
2877
 
@@ -2539,7 +2905,7 @@
2539
2905
  * Determines if the parsing failed.
2540
2906
  * @returns `true` if there are errors, otherwise `false`.
2541
2907
  */
2542
- failed() {
2908
+ get failed() {
2543
2909
  // TODO: this should probably be recursive as noted in the Ruby version
2544
2910
  return this.errors.length > 0 || this.value.errors.length > 0;
2545
2911
  }
@@ -2547,8 +2913,8 @@
2547
2913
  * Determines if the parsing was successful.
2548
2914
  * @returns `true` if there are no errors, otherwise `false`.
2549
2915
  */
2550
- success() {
2551
- return !this.failed();
2916
+ get successful() {
2917
+ return this.errors.length === 0;
2552
2918
  }
2553
2919
  /**
2554
2920
  * Returns a pretty-printed JSON string of the errors.
@@ -2693,23 +3059,116 @@
2693
3059
  }
2694
3060
  }
2695
3061
 
2696
- /**
2697
- * Represents a visitor that can traverse nodes.
2698
- */
3062
+ // NOTE: This file is generated by the templates/template.rb script and should not
3063
+ // be modified manually. See /Users/marcoroth/Development/herb-release/templates/javascript/packages/core/src/visitor.ts.erb
2699
3064
  class Visitor {
2700
- /**
2701
- * Visits a node and performs an action.
2702
- * @param node - The node to visit.
2703
- */
2704
3065
  visit(node) {
2705
- console.log("Node", node); // TODO: implement
3066
+ if (!node)
3067
+ return;
3068
+ node.accept(this);
3069
+ }
3070
+ visitAll(nodes) {
3071
+ nodes.forEach(node => node?.accept(this));
3072
+ }
3073
+ visitChildNodes(node) {
3074
+ node.compactChildNodes().forEach(node => node.accept(this));
3075
+ }
3076
+ visitDocumentNode(node) {
3077
+ this.visitChildNodes(node);
3078
+ }
3079
+ visitLiteralNode(node) {
3080
+ this.visitChildNodes(node);
3081
+ }
3082
+ visitHTMLOpenTagNode(node) {
3083
+ this.visitChildNodes(node);
3084
+ }
3085
+ visitHTMLCloseTagNode(node) {
3086
+ this.visitChildNodes(node);
3087
+ }
3088
+ visitHTMLSelfCloseTagNode(node) {
3089
+ this.visitChildNodes(node);
3090
+ }
3091
+ visitHTMLElementNode(node) {
3092
+ this.visitChildNodes(node);
3093
+ }
3094
+ visitHTMLAttributeValueNode(node) {
3095
+ this.visitChildNodes(node);
3096
+ }
3097
+ visitHTMLAttributeNameNode(node) {
3098
+ this.visitChildNodes(node);
3099
+ }
3100
+ visitHTMLAttributeNode(node) {
3101
+ this.visitChildNodes(node);
3102
+ }
3103
+ visitHTMLTextNode(node) {
3104
+ this.visitChildNodes(node);
3105
+ }
3106
+ visitHTMLCommentNode(node) {
3107
+ this.visitChildNodes(node);
3108
+ }
3109
+ visitHTMLDoctypeNode(node) {
3110
+ this.visitChildNodes(node);
3111
+ }
3112
+ visitWhitespaceNode(node) {
3113
+ this.visitChildNodes(node);
3114
+ }
3115
+ visitERBContentNode(node) {
3116
+ this.visitChildNodes(node);
3117
+ }
3118
+ visitERBEndNode(node) {
3119
+ this.visitChildNodes(node);
3120
+ }
3121
+ visitERBElseNode(node) {
3122
+ this.visitChildNodes(node);
3123
+ }
3124
+ visitERBIfNode(node) {
3125
+ this.visitChildNodes(node);
3126
+ }
3127
+ visitERBBlockNode(node) {
3128
+ this.visitChildNodes(node);
3129
+ }
3130
+ visitERBWhenNode(node) {
3131
+ this.visitChildNodes(node);
3132
+ }
3133
+ visitERBCaseNode(node) {
3134
+ this.visitChildNodes(node);
3135
+ }
3136
+ visitERBCaseMatchNode(node) {
3137
+ this.visitChildNodes(node);
3138
+ }
3139
+ visitERBWhileNode(node) {
3140
+ this.visitChildNodes(node);
3141
+ }
3142
+ visitERBUntilNode(node) {
3143
+ this.visitChildNodes(node);
3144
+ }
3145
+ visitERBForNode(node) {
3146
+ this.visitChildNodes(node);
3147
+ }
3148
+ visitERBRescueNode(node) {
3149
+ this.visitChildNodes(node);
3150
+ }
3151
+ visitERBEnsureNode(node) {
3152
+ this.visitChildNodes(node);
3153
+ }
3154
+ visitERBBeginNode(node) {
3155
+ this.visitChildNodes(node);
3156
+ }
3157
+ visitERBUnlessNode(node) {
3158
+ this.visitChildNodes(node);
3159
+ }
3160
+ visitERBYieldNode(node) {
3161
+ this.visitChildNodes(node);
3162
+ }
3163
+ visitERBInNode(node) {
3164
+ this.visitChildNodes(node);
2706
3165
  }
2707
3166
  }
2708
3167
 
2709
- exports.ASTNode = ASTNode;
2710
3168
  exports.DocumentNode = DocumentNode;
2711
3169
  exports.ERBBeginNode = ERBBeginNode;
2712
3170
  exports.ERBBlockNode = ERBBlockNode;
3171
+ exports.ERBCaseMatchNode = ERBCaseMatchNode;
2713
3172
  exports.ERBCaseNode = ERBCaseNode;
2714
3173
  exports.ERBContentNode = ERBContentNode;
2715
3174
  exports.ERBElseNode = ERBElseNode;
@@ -2717,11 +3176,13 @@
2717
3176
  exports.ERBEnsureNode = ERBEnsureNode;
2718
3177
  exports.ERBForNode = ERBForNode;
2719
3178
  exports.ERBIfNode = ERBIfNode;
3179
+ exports.ERBInNode = ERBInNode;
2720
3180
  exports.ERBRescueNode = ERBRescueNode;
2721
3181
  exports.ERBUnlessNode = ERBUnlessNode;
2722
3182
  exports.ERBUntilNode = ERBUntilNode;
2723
3183
  exports.ERBWhenNode = ERBWhenNode;
2724
3184
  exports.ERBWhileNode = ERBWhileNode;
3185
+ exports.ERBYieldNode = ERBYieldNode;
2725
3186
  exports.HTMLAttributeNameNode = HTMLAttributeNameNode;
2726
3187
  exports.HTMLAttributeNode = HTMLAttributeNode;
2727
3188
  exports.HTMLAttributeValueNode = HTMLAttributeValueNode;
@@ -2733,11 +3194,14 @@
2733
3194
  exports.HTMLSelfCloseTagNode = HTMLSelfCloseTagNode;
2734
3195
  exports.HTMLTextNode = HTMLTextNode;
2735
3196
  exports.HerbBackend = HerbBackend;
3197
+ exports.HerbError = HerbError;
3198
+ exports.HerbWarning = HerbWarning;
2736
3199
  exports.LexResult = LexResult;
2737
3200
  exports.LiteralNode = LiteralNode;
2738
3201
  exports.Location = Location;
2739
3202
  exports.MissingClosingTagError = MissingClosingTagError;
2740
3203
  exports.MissingOpeningTagError = MissingOpeningTagError;
3204
+ exports.Node = Node;
2741
3205
  exports.ParseResult = ParseResult;
2742
3206
  exports.Position = Position;
2743
3207
  exports.QuotesMismatchError = QuotesMismatchError;