@herb-tools/core 0.4.3 → 0.6.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,53 +1,3 @@
1
- const expectedFunctions = [
2
- "parse",
3
- "lex",
4
- "parseFile",
5
- "lexFile",
6
- "extractRuby",
7
- "extractHTML",
8
- "version",
9
- ];
10
- // NOTE: This function should never be called and is only for type checking
11
- // so we can make sure `expectedFunctions` matches the functions defined
12
- // in `LibHerbBackendFunctions` and the other way around.
13
- //
14
- function _TYPECHECK() {
15
- const checkFunctionsExist = true;
16
- const checkInterfaceComplete = true;
17
- return { checkFunctionsExist, checkInterfaceComplete };
18
- }
19
- function isLibHerbBackend(object, libherbpath = "unknown") {
20
- for (const expectedFunction of expectedFunctions) {
21
- if (object[expectedFunction] === undefined) {
22
- throw new Error(`Libherb at "${libherbpath}" doesn't expose function "${expectedFunction}".`);
23
- }
24
- if (typeof object[expectedFunction] !== "function") {
25
- throw new Error(`Libherb at "${libherbpath}" has "${expectedFunction}" but it's not a function.`);
26
- }
27
- }
28
- return true;
29
- }
30
- function ensureLibHerbBackend(object, libherbpath = "unknown") {
31
- isLibHerbBackend(object, libherbpath);
32
- return object;
33
- }
34
-
35
- /**
36
- * Converts a Diagnostic to Monaco/VSCode-compatible MonacoDiagnostic format
37
- */
38
- function toMonacoDiagnostic(diagnostic) {
39
- const { message, location } = diagnostic;
40
- const severity = diagnostic.severity === "hint" ? "info" : diagnostic.severity;
41
- return {
42
- line: location.start.line,
43
- column: location.start.column,
44
- endLine: location.end.line,
45
- endColumn: location.end.column,
46
- message,
47
- severity
48
- };
49
- }
50
-
51
1
  class Position {
52
2
  line;
53
3
  column;
@@ -179,7 +129,7 @@ class Token {
179
129
  }
180
130
 
181
131
  // NOTE: This file is generated by the templates/template.rb script and should not
182
- // be modified manually. See /Users/marcoroth/Development/herb-release-7/templates/javascript/packages/core/src/errors.ts.erb
132
+ // be modified manually. See /Users/marcoroth/Development/herb-release-0.6.0/templates/javascript/packages/core/src/errors.ts.erb
183
133
  class HerbError {
184
134
  type;
185
135
  message;
@@ -620,12 +570,6 @@ function fromSerializedError(error) {
620
570
  }
621
571
  }
622
572
 
623
- var name = "@herb-tools/core";
624
- var version = "0.4.3";
625
- var packageJSON = {
626
- name: name,
627
- version: version};
628
-
629
573
  function ensureString(object) {
630
574
  if (typeof object === "string") {
631
575
  return object;
@@ -641,139 +585,8 @@ function convertToUTF8(string) {
641
585
  return decoder.decode(new Uint8Array(bytes));
642
586
  }
643
587
 
644
- class Result {
645
- source;
646
- warnings;
647
- errors;
648
- constructor(source, warnings = [], errors = []) {
649
- this.source = source;
650
- this.warnings = warnings || [];
651
- this.errors = errors || [];
652
- }
653
- /**
654
- * Determines if the parsing was successful.
655
- * @returns `true` if there are no errors, otherwise `false`.
656
- */
657
- get successful() {
658
- return this.errors.length === 0;
659
- }
660
- /**
661
- * Determines if the parsing failed.
662
- * @returns `true` if there are errors, otherwise `false`.
663
- */
664
- get failed() {
665
- return this.errors.length > 0;
666
- }
667
- }
668
-
669
- class TokenList {
670
- list;
671
- static from(list) {
672
- return new TokenList(list.map((token) => Token.from(token)));
673
- }
674
- constructor(list) {
675
- this.list = list;
676
- }
677
- get length() {
678
- return this.list.length;
679
- }
680
- get tokens() {
681
- return this.list;
682
- }
683
- [Symbol.iterator]() {
684
- return this.list[Symbol.iterator]();
685
- }
686
- at(index) {
687
- return this.list.at(index);
688
- }
689
- forEach(callback) {
690
- this.list.forEach(callback);
691
- }
692
- map(callback) {
693
- return this.list.map(callback);
694
- }
695
- filter(predicate) {
696
- return this.list.filter(predicate);
697
- }
698
- __getobj__() {
699
- return this.list;
700
- }
701
- inspect() {
702
- return this.list.map((token) => token.inspect()).join("\n") + "\n";
703
- }
704
- toString() {
705
- return this.inspect();
706
- }
707
- }
708
-
709
- class HerbWarning {
710
- message;
711
- location;
712
- static from(warning) {
713
- return new HerbWarning(warning.message, Location.from(warning.location));
714
- }
715
- constructor(message, location) {
716
- this.message = message;
717
- this.location = location;
718
- }
719
- }
720
-
721
- /**
722
- * Represents the result of a lexical analysis, extending the base `Result` class.
723
- * It contains the token list, source code, warnings, and errors.
724
- */
725
- class LexResult extends Result {
726
- /** The list of tokens generated from the source code. */
727
- value;
728
- /**
729
- * Creates a `LexResult` instance from a serialized result.
730
- * @param result - The serialized lexical result containing tokens, source, warnings, and errors.
731
- * @returns A new `LexResult` instance.
732
- */
733
- static from(result) {
734
- return new LexResult(TokenList.from(result.tokens || []), result.source, result.warnings.map((warning) => HerbWarning.from(warning)), result.errors.map((error) => HerbError.from(error)));
735
- }
736
- /**
737
- * Constructs a new `LexResult`.
738
- * @param value - The list of tokens.
739
- * @param source - The source code that was lexed.
740
- * @param warnings - An array of warnings encountered during lexing.
741
- * @param errors - An array of errors encountered during lexing.
742
- */
743
- constructor(value, source, warnings = [], errors = []) {
744
- super(source, warnings, errors);
745
- this.value = value;
746
- }
747
- /**
748
- * Determines if the lexing was successful.
749
- * @returns `true` if there are no errors, otherwise `false`.
750
- */
751
- get successful() {
752
- return this.errors.length === 0;
753
- }
754
- /**
755
- * Determines if the lexing failed.
756
- * @returns `true` if there are errors, otherwise `false`.
757
- */
758
- get failed() {
759
- return this.errors.length > 0;
760
- }
761
- /**
762
- * Converts the `LexResult` to a JSON representation.
763
- * @returns An object containing the token list, source, warnings, and errors.
764
- */
765
- toJSON() {
766
- return {
767
- value: this.value,
768
- source: this.source,
769
- warnings: this.warnings,
770
- errors: this.errors,
771
- };
772
- }
773
- }
774
-
775
588
  // NOTE: This file is generated by the templates/template.rb script and should not
776
- // be modified manually. See /Users/marcoroth/Development/herb-release-7/templates/javascript/packages/core/src/nodes.ts.erb
589
+ // be modified manually. See /Users/marcoroth/Development/herb-release-0.6.0/templates/javascript/packages/core/src/nodes.ts.erb
777
590
  class Node {
778
591
  type;
779
592
  location;
@@ -878,7 +691,6 @@ class DocumentNode extends Node {
878
691
  output += `@ DocumentNode ${this.location.treeInspectWithLabel()}\n`;
879
692
  output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
880
693
  output += `└── children: ${this.inspectArray(this.children, " ")}`;
881
- // output += "\n";
882
694
  return output;
883
695
  }
884
696
  }
@@ -922,7 +734,6 @@ class LiteralNode extends Node {
922
734
  output += `@ LiteralNode ${this.location.treeInspectWithLabel()}\n`;
923
735
  output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
924
736
  output += `└── content: ${this.content ? JSON.stringify(this.content) : "∅"}\n`;
925
- // output += "\n";
926
737
  return output;
927
738
  }
928
739
  }
@@ -989,13 +800,13 @@ class HTMLOpenTagNode extends Node {
989
800
  output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
990
801
  output += `├── children: ${this.inspectArray(this.children, "│ ")}`;
991
802
  output += `└── is_void: ${typeof this.is_void === 'boolean' ? String(this.is_void) : "∅"}\n`;
992
- // output += "\n";
993
803
  return output;
994
804
  }
995
805
  }
996
806
  class HTMLCloseTagNode extends Node {
997
807
  tag_opening;
998
808
  tag_name;
809
+ children;
999
810
  tag_closing;
1000
811
  static from(data) {
1001
812
  return new HTMLCloseTagNode({
@@ -1004,6 +815,7 @@ class HTMLCloseTagNode extends Node {
1004
815
  errors: (data.errors || []).map(error => HerbError.from(error)),
1005
816
  tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
1006
817
  tag_name: data.tag_name ? Token.from(data.tag_name) : null,
818
+ children: (data.children || []).map(node => fromSerializedNode(node)),
1007
819
  tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
1008
820
  });
1009
821
  }
@@ -1011,13 +823,16 @@ class HTMLCloseTagNode extends Node {
1011
823
  super(props.type, props.location, props.errors);
1012
824
  this.tag_opening = props.tag_opening;
1013
825
  this.tag_name = props.tag_name;
826
+ this.children = props.children;
1014
827
  this.tag_closing = props.tag_closing;
1015
828
  }
1016
829
  accept(visitor) {
1017
830
  visitor.visitHTMLCloseTagNode(this);
1018
831
  }
1019
832
  childNodes() {
1020
- return [];
833
+ return [
834
+ ...this.children,
835
+ ];
1021
836
  }
1022
837
  compactChildNodes() {
1023
838
  return this.childNodes().filter(node => node !== null && node !== undefined);
@@ -1025,6 +840,7 @@ class HTMLCloseTagNode extends Node {
1025
840
  recursiveErrors() {
1026
841
  return [
1027
842
  ...this.errors,
843
+ ...this.children.map(node => node.recursiveErrors()),
1028
844
  ].flat();
1029
845
  }
1030
846
  toJSON() {
@@ -1033,6 +849,7 @@ class HTMLCloseTagNode extends Node {
1033
849
  type: "AST_HTML_CLOSE_TAG_NODE",
1034
850
  tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
1035
851
  tag_name: this.tag_name ? this.tag_name.toJSON() : null,
852
+ children: this.children.map(node => node.toJSON()),
1036
853
  tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
1037
854
  };
1038
855
  }
@@ -1042,75 +859,8 @@ class HTMLCloseTagNode extends Node {
1042
859
  output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
1043
860
  output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
1044
861
  output += `├── tag_name: ${this.tag_name ? this.tag_name.treeInspect() : "∅"}\n`;
862
+ output += `├── children: ${this.inspectArray(this.children, "│ ")}`;
1045
863
  output += `└── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
1046
- // output += "\n";
1047
- return output;
1048
- }
1049
- }
1050
- class HTMLSelfCloseTagNode extends Node {
1051
- tag_opening;
1052
- tag_name;
1053
- attributes;
1054
- tag_closing;
1055
- is_void;
1056
- static from(data) {
1057
- return new HTMLSelfCloseTagNode({
1058
- type: data.type,
1059
- location: Location.from(data.location),
1060
- errors: (data.errors || []).map(error => HerbError.from(error)),
1061
- tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
1062
- tag_name: data.tag_name ? Token.from(data.tag_name) : null,
1063
- attributes: (data.attributes || []).map(node => fromSerializedNode(node)),
1064
- tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
1065
- is_void: data.is_void,
1066
- });
1067
- }
1068
- constructor(props) {
1069
- super(props.type, props.location, props.errors);
1070
- this.tag_opening = props.tag_opening;
1071
- this.tag_name = props.tag_name;
1072
- this.attributes = props.attributes;
1073
- this.tag_closing = props.tag_closing;
1074
- this.is_void = props.is_void;
1075
- }
1076
- accept(visitor) {
1077
- visitor.visitHTMLSelfCloseTagNode(this);
1078
- }
1079
- childNodes() {
1080
- return [
1081
- ...this.attributes,
1082
- ];
1083
- }
1084
- compactChildNodes() {
1085
- return this.childNodes().filter(node => node !== null && node !== undefined);
1086
- }
1087
- recursiveErrors() {
1088
- return [
1089
- ...this.errors,
1090
- ...this.attributes.map(node => node.recursiveErrors()),
1091
- ].flat();
1092
- }
1093
- toJSON() {
1094
- return {
1095
- ...super.toJSON(),
1096
- type: "AST_HTML_SELF_CLOSE_TAG_NODE",
1097
- tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
1098
- tag_name: this.tag_name ? this.tag_name.toJSON() : null,
1099
- attributes: this.attributes.map(node => node.toJSON()),
1100
- tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
1101
- is_void: this.is_void,
1102
- };
1103
- }
1104
- treeInspect() {
1105
- let output = "";
1106
- output += `@ HTMLSelfCloseTagNode ${this.location.treeInspectWithLabel()}\n`;
1107
- output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
1108
- output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
1109
- output += `├── tag_name: ${this.tag_name ? this.tag_name.treeInspect() : "∅"}\n`;
1110
- output += `├── attributes: ${this.inspectArray(this.attributes, "│ ")}`;
1111
- output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
1112
- output += `└── is_void: ${typeof this.is_void === 'boolean' ? String(this.is_void) : "∅"}\n`;
1113
- // output += "\n";
1114
864
  return output;
1115
865
  }
1116
866
  }
@@ -1125,10 +875,10 @@ class HTMLElementNode extends Node {
1125
875
  type: data.type,
1126
876
  location: Location.from(data.location),
1127
877
  errors: (data.errors || []).map(error => HerbError.from(error)),
1128
- open_tag: data.open_tag ? fromSerializedNode(data.open_tag) : null,
878
+ open_tag: data.open_tag ? fromSerializedNode((data.open_tag)) : null,
1129
879
  tag_name: data.tag_name ? Token.from(data.tag_name) : null,
1130
880
  body: (data.body || []).map(node => fromSerializedNode(node)),
1131
- close_tag: data.close_tag ? fromSerializedNode(data.close_tag) : null,
881
+ close_tag: data.close_tag ? fromSerializedNode((data.close_tag)) : null,
1132
882
  is_void: data.is_void,
1133
883
  });
1134
884
  }
@@ -1181,7 +931,6 @@ class HTMLElementNode extends Node {
1181
931
  output += `├── body: ${this.inspectArray(this.body, "│ ")}`;
1182
932
  output += `├── close_tag: ${this.inspectNode(this.close_tag, "│ ")}`;
1183
933
  output += `└── is_void: ${typeof this.is_void === 'boolean' ? String(this.is_void) : "∅"}\n`;
1184
- // output += "\n";
1185
934
  return output;
1186
935
  }
1187
936
  }
@@ -1243,29 +992,30 @@ class HTMLAttributeValueNode extends Node {
1243
992
  output += `├── children: ${this.inspectArray(this.children, "│ ")}`;
1244
993
  output += `├── close_quote: ${this.close_quote ? this.close_quote.treeInspect() : "∅"}\n`;
1245
994
  output += `└── quoted: ${typeof this.quoted === 'boolean' ? String(this.quoted) : "∅"}\n`;
1246
- // output += "\n";
1247
995
  return output;
1248
996
  }
1249
997
  }
1250
998
  class HTMLAttributeNameNode extends Node {
1251
- name;
999
+ children;
1252
1000
  static from(data) {
1253
1001
  return new HTMLAttributeNameNode({
1254
1002
  type: data.type,
1255
1003
  location: Location.from(data.location),
1256
1004
  errors: (data.errors || []).map(error => HerbError.from(error)),
1257
- name: data.name ? Token.from(data.name) : null,
1005
+ children: (data.children || []).map(node => fromSerializedNode(node)),
1258
1006
  });
1259
1007
  }
1260
1008
  constructor(props) {
1261
1009
  super(props.type, props.location, props.errors);
1262
- this.name = props.name;
1010
+ this.children = props.children;
1263
1011
  }
1264
1012
  accept(visitor) {
1265
1013
  visitor.visitHTMLAttributeNameNode(this);
1266
1014
  }
1267
1015
  childNodes() {
1268
- return [];
1016
+ return [
1017
+ ...this.children,
1018
+ ];
1269
1019
  }
1270
1020
  compactChildNodes() {
1271
1021
  return this.childNodes().filter(node => node !== null && node !== undefined);
@@ -1273,21 +1023,21 @@ class HTMLAttributeNameNode extends Node {
1273
1023
  recursiveErrors() {
1274
1024
  return [
1275
1025
  ...this.errors,
1026
+ ...this.children.map(node => node.recursiveErrors()),
1276
1027
  ].flat();
1277
1028
  }
1278
1029
  toJSON() {
1279
1030
  return {
1280
1031
  ...super.toJSON(),
1281
1032
  type: "AST_HTML_ATTRIBUTE_NAME_NODE",
1282
- name: this.name ? this.name.toJSON() : null,
1033
+ children: this.children.map(node => node.toJSON()),
1283
1034
  };
1284
1035
  }
1285
1036
  treeInspect() {
1286
1037
  let output = "";
1287
1038
  output += `@ HTMLAttributeNameNode ${this.location.treeInspectWithLabel()}\n`;
1288
1039
  output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
1289
- output += `└── name: ${this.name ? this.name.treeInspect() : ""}\n`;
1290
- // output += "\n";
1040
+ output += `└── children: ${this.inspectArray(this.children, " ")}`;
1291
1041
  return output;
1292
1042
  }
1293
1043
  }
@@ -1300,9 +1050,9 @@ class HTMLAttributeNode extends Node {
1300
1050
  type: data.type,
1301
1051
  location: Location.from(data.location),
1302
1052
  errors: (data.errors || []).map(error => HerbError.from(error)),
1303
- name: data.name ? fromSerializedNode(data.name) : null,
1053
+ name: data.name ? fromSerializedNode((data.name)) : null,
1304
1054
  equals: data.equals ? Token.from(data.equals) : null,
1305
- value: data.value ? fromSerializedNode(data.value) : null,
1055
+ value: data.value ? fromSerializedNode((data.value)) : null,
1306
1056
  });
1307
1057
  }
1308
1058
  constructor(props) {
@@ -1346,7 +1096,6 @@ class HTMLAttributeNode extends Node {
1346
1096
  output += `├── name: ${this.inspectNode(this.name, "│ ")}`;
1347
1097
  output += `├── equals: ${this.equals ? this.equals.treeInspect() : "∅"}\n`;
1348
1098
  output += `└── value: ${this.inspectNode(this.value, " ")}`;
1349
- // output += "\n";
1350
1099
  return output;
1351
1100
  }
1352
1101
  }
@@ -1390,7 +1139,6 @@ class HTMLTextNode extends Node {
1390
1139
  output += `@ HTMLTextNode ${this.location.treeInspectWithLabel()}\n`;
1391
1140
  output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
1392
1141
  output += `└── content: ${this.content ? JSON.stringify(this.content) : "∅"}\n`;
1393
- // output += "\n";
1394
1142
  return output;
1395
1143
  }
1396
1144
  }
@@ -1447,7 +1195,6 @@ class HTMLCommentNode extends Node {
1447
1195
  output += `├── comment_start: ${this.comment_start ? this.comment_start.treeInspect() : "∅"}\n`;
1448
1196
  output += `├── children: ${this.inspectArray(this.children, "│ ")}`;
1449
1197
  output += `└── comment_end: ${this.comment_end ? this.comment_end.treeInspect() : "∅"}\n`;
1450
- // output += "\n";
1451
1198
  return output;
1452
1199
  }
1453
1200
  }
@@ -1504,7 +1251,118 @@ class HTMLDoctypeNode extends Node {
1504
1251
  output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
1505
1252
  output += `├── children: ${this.inspectArray(this.children, "│ ")}`;
1506
1253
  output += `└── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
1507
- // output += "\n";
1254
+ return output;
1255
+ }
1256
+ }
1257
+ class XMLDeclarationNode extends Node {
1258
+ tag_opening;
1259
+ children;
1260
+ tag_closing;
1261
+ static from(data) {
1262
+ return new XMLDeclarationNode({
1263
+ type: data.type,
1264
+ location: Location.from(data.location),
1265
+ errors: (data.errors || []).map(error => HerbError.from(error)),
1266
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
1267
+ children: (data.children || []).map(node => fromSerializedNode(node)),
1268
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
1269
+ });
1270
+ }
1271
+ constructor(props) {
1272
+ super(props.type, props.location, props.errors);
1273
+ this.tag_opening = props.tag_opening;
1274
+ this.children = props.children;
1275
+ this.tag_closing = props.tag_closing;
1276
+ }
1277
+ accept(visitor) {
1278
+ visitor.visitXMLDeclarationNode(this);
1279
+ }
1280
+ childNodes() {
1281
+ return [
1282
+ ...this.children,
1283
+ ];
1284
+ }
1285
+ compactChildNodes() {
1286
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1287
+ }
1288
+ recursiveErrors() {
1289
+ return [
1290
+ ...this.errors,
1291
+ ...this.children.map(node => node.recursiveErrors()),
1292
+ ].flat();
1293
+ }
1294
+ toJSON() {
1295
+ return {
1296
+ ...super.toJSON(),
1297
+ type: "AST_XML_DECLARATION_NODE",
1298
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
1299
+ children: this.children.map(node => node.toJSON()),
1300
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
1301
+ };
1302
+ }
1303
+ treeInspect() {
1304
+ let output = "";
1305
+ output += `@ XMLDeclarationNode ${this.location.treeInspectWithLabel()}\n`;
1306
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
1307
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
1308
+ output += `├── children: ${this.inspectArray(this.children, "│ ")}`;
1309
+ output += `└── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
1310
+ return output;
1311
+ }
1312
+ }
1313
+ class CDATANode extends Node {
1314
+ tag_opening;
1315
+ children;
1316
+ tag_closing;
1317
+ static from(data) {
1318
+ return new CDATANode({
1319
+ type: data.type,
1320
+ location: Location.from(data.location),
1321
+ errors: (data.errors || []).map(error => HerbError.from(error)),
1322
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
1323
+ children: (data.children || []).map(node => fromSerializedNode(node)),
1324
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
1325
+ });
1326
+ }
1327
+ constructor(props) {
1328
+ super(props.type, props.location, props.errors);
1329
+ this.tag_opening = props.tag_opening;
1330
+ this.children = props.children;
1331
+ this.tag_closing = props.tag_closing;
1332
+ }
1333
+ accept(visitor) {
1334
+ visitor.visitCDATANode(this);
1335
+ }
1336
+ childNodes() {
1337
+ return [
1338
+ ...this.children,
1339
+ ];
1340
+ }
1341
+ compactChildNodes() {
1342
+ return this.childNodes().filter(node => node !== null && node !== undefined);
1343
+ }
1344
+ recursiveErrors() {
1345
+ return [
1346
+ ...this.errors,
1347
+ ...this.children.map(node => node.recursiveErrors()),
1348
+ ].flat();
1349
+ }
1350
+ toJSON() {
1351
+ return {
1352
+ ...super.toJSON(),
1353
+ type: "AST_CDATA_NODE",
1354
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
1355
+ children: this.children.map(node => node.toJSON()),
1356
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
1357
+ };
1358
+ }
1359
+ treeInspect() {
1360
+ let output = "";
1361
+ output += `@ CDATANode ${this.location.treeInspectWithLabel()}\n`;
1362
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
1363
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
1364
+ output += `├── children: ${this.inspectArray(this.children, "│ ")}`;
1365
+ output += `└── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
1508
1366
  return output;
1509
1367
  }
1510
1368
  }
@@ -1548,7 +1406,6 @@ class WhitespaceNode extends Node {
1548
1406
  output += `@ WhitespaceNode ${this.location.treeInspectWithLabel()}\n`;
1549
1407
  output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
1550
1408
  output += `└── value: ${this.value ? this.value.treeInspect() : "∅"}\n`;
1551
- // output += "\n";
1552
1409
  return output;
1553
1410
  }
1554
1411
  }
@@ -1617,7 +1474,6 @@ class ERBContentNode extends Node {
1617
1474
  // no-op for analyzed_ruby
1618
1475
  output += `├── parsed: ${typeof this.parsed === 'boolean' ? String(this.parsed) : "∅"}\n`;
1619
1476
  output += `└── valid: ${typeof this.valid === 'boolean' ? String(this.valid) : "∅"}\n`;
1620
- // output += "\n";
1621
1477
  return output;
1622
1478
  }
1623
1479
  }
@@ -1671,7 +1527,6 @@ class ERBEndNode extends Node {
1671
1527
  output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
1672
1528
  output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
1673
1529
  output += `└── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
1674
- // output += "\n";
1675
1530
  return output;
1676
1531
  }
1677
1532
  }
@@ -1733,7 +1588,6 @@ class ERBElseNode extends Node {
1733
1588
  output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
1734
1589
  output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
1735
1590
  output += `└── statements: ${this.inspectArray(this.statements, " ")}`;
1736
- // output += "\n";
1737
1591
  return output;
1738
1592
  }
1739
1593
  }
@@ -1753,8 +1607,8 @@ class ERBIfNode extends Node {
1753
1607
  content: data.content ? Token.from(data.content) : null,
1754
1608
  tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
1755
1609
  statements: (data.statements || []).map(node => fromSerializedNode(node)),
1756
- subsequent: data.subsequent ? fromSerializedNode(data.subsequent) : null,
1757
- end_node: data.end_node ? fromSerializedNode(data.end_node) : null,
1610
+ subsequent: data.subsequent ? fromSerializedNode((data.subsequent)) : null,
1611
+ end_node: data.end_node ? fromSerializedNode((data.end_node)) : null,
1758
1612
  });
1759
1613
  }
1760
1614
  constructor(props) {
@@ -1809,7 +1663,6 @@ class ERBIfNode extends Node {
1809
1663
  output += `├── statements: ${this.inspectArray(this.statements, "│ ")}`;
1810
1664
  output += `├── subsequent: ${this.inspectNode(this.subsequent, "│ ")}`;
1811
1665
  output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
1812
- // output += "\n";
1813
1666
  return output;
1814
1667
  }
1815
1668
  }
@@ -1828,7 +1681,7 @@ class ERBBlockNode extends Node {
1828
1681
  content: data.content ? Token.from(data.content) : null,
1829
1682
  tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
1830
1683
  body: (data.body || []).map(node => fromSerializedNode(node)),
1831
- end_node: data.end_node ? fromSerializedNode(data.end_node) : null,
1684
+ end_node: data.end_node ? fromSerializedNode((data.end_node)) : null,
1832
1685
  });
1833
1686
  }
1834
1687
  constructor(props) {
@@ -1878,7 +1731,6 @@ class ERBBlockNode extends Node {
1878
1731
  output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
1879
1732
  output += `├── body: ${this.inspectArray(this.body, "│ ")}`;
1880
1733
  output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
1881
- // output += "\n";
1882
1734
  return output;
1883
1735
  }
1884
1736
  }
@@ -1940,7 +1792,6 @@ class ERBWhenNode extends Node {
1940
1792
  output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
1941
1793
  output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
1942
1794
  output += `└── statements: ${this.inspectArray(this.statements, " ")}`;
1943
- // output += "\n";
1944
1795
  return output;
1945
1796
  }
1946
1797
  }
@@ -1962,8 +1813,8 @@ class ERBCaseNode extends Node {
1962
1813
  tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
1963
1814
  children: (data.children || []).map(node => fromSerializedNode(node)),
1964
1815
  conditions: (data.conditions || []).map(node => fromSerializedNode(node)),
1965
- else_clause: data.else_clause ? fromSerializedNode(data.else_clause) : null,
1966
- end_node: data.end_node ? fromSerializedNode(data.end_node) : null,
1816
+ else_clause: data.else_clause ? fromSerializedNode((data.else_clause)) : null,
1817
+ end_node: data.end_node ? fromSerializedNode((data.end_node)) : null,
1967
1818
  });
1968
1819
  }
1969
1820
  constructor(props) {
@@ -2023,7 +1874,6 @@ class ERBCaseNode extends Node {
2023
1874
  output += `├── conditions: ${this.inspectArray(this.conditions, "│ ")}`;
2024
1875
  output += `├── else_clause: ${this.inspectNode(this.else_clause, "│ ")}`;
2025
1876
  output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
2026
- // output += "\n";
2027
1877
  return output;
2028
1878
  }
2029
1879
  }
@@ -2045,8 +1895,8 @@ class ERBCaseMatchNode extends Node {
2045
1895
  tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
2046
1896
  children: (data.children || []).map(node => fromSerializedNode(node)),
2047
1897
  conditions: (data.conditions || []).map(node => fromSerializedNode(node)),
2048
- else_clause: data.else_clause ? fromSerializedNode(data.else_clause) : null,
2049
- end_node: data.end_node ? fromSerializedNode(data.end_node) : null,
1898
+ else_clause: data.else_clause ? fromSerializedNode((data.else_clause)) : null,
1899
+ end_node: data.end_node ? fromSerializedNode((data.end_node)) : null,
2050
1900
  });
2051
1901
  }
2052
1902
  constructor(props) {
@@ -2106,7 +1956,6 @@ class ERBCaseMatchNode extends Node {
2106
1956
  output += `├── conditions: ${this.inspectArray(this.conditions, "│ ")}`;
2107
1957
  output += `├── else_clause: ${this.inspectNode(this.else_clause, "│ ")}`;
2108
1958
  output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
2109
- // output += "\n";
2110
1959
  return output;
2111
1960
  }
2112
1961
  }
@@ -2125,7 +1974,7 @@ class ERBWhileNode extends Node {
2125
1974
  content: data.content ? Token.from(data.content) : null,
2126
1975
  tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
2127
1976
  statements: (data.statements || []).map(node => fromSerializedNode(node)),
2128
- end_node: data.end_node ? fromSerializedNode(data.end_node) : null,
1977
+ end_node: data.end_node ? fromSerializedNode((data.end_node)) : null,
2129
1978
  });
2130
1979
  }
2131
1980
  constructor(props) {
@@ -2175,7 +2024,6 @@ class ERBWhileNode extends Node {
2175
2024
  output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
2176
2025
  output += `├── statements: ${this.inspectArray(this.statements, "│ ")}`;
2177
2026
  output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
2178
- // output += "\n";
2179
2027
  return output;
2180
2028
  }
2181
2029
  }
@@ -2194,7 +2042,7 @@ class ERBUntilNode extends Node {
2194
2042
  content: data.content ? Token.from(data.content) : null,
2195
2043
  tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
2196
2044
  statements: (data.statements || []).map(node => fromSerializedNode(node)),
2197
- end_node: data.end_node ? fromSerializedNode(data.end_node) : null,
2045
+ end_node: data.end_node ? fromSerializedNode((data.end_node)) : null,
2198
2046
  });
2199
2047
  }
2200
2048
  constructor(props) {
@@ -2244,7 +2092,6 @@ class ERBUntilNode extends Node {
2244
2092
  output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
2245
2093
  output += `├── statements: ${this.inspectArray(this.statements, "│ ")}`;
2246
2094
  output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
2247
- // output += "\n";
2248
2095
  return output;
2249
2096
  }
2250
2097
  }
@@ -2263,7 +2110,7 @@ class ERBForNode extends Node {
2263
2110
  content: data.content ? Token.from(data.content) : null,
2264
2111
  tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
2265
2112
  statements: (data.statements || []).map(node => fromSerializedNode(node)),
2266
- end_node: data.end_node ? fromSerializedNode(data.end_node) : null,
2113
+ end_node: data.end_node ? fromSerializedNode((data.end_node)) : null,
2267
2114
  });
2268
2115
  }
2269
2116
  constructor(props) {
@@ -2313,7 +2160,6 @@ class ERBForNode extends Node {
2313
2160
  output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
2314
2161
  output += `├── statements: ${this.inspectArray(this.statements, "│ ")}`;
2315
2162
  output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
2316
- // output += "\n";
2317
2163
  return output;
2318
2164
  }
2319
2165
  }
@@ -2332,7 +2178,7 @@ class ERBRescueNode extends Node {
2332
2178
  content: data.content ? Token.from(data.content) : null,
2333
2179
  tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
2334
2180
  statements: (data.statements || []).map(node => fromSerializedNode(node)),
2335
- subsequent: data.subsequent ? fromSerializedNode(data.subsequent) : null,
2181
+ subsequent: data.subsequent ? fromSerializedNode((data.subsequent)) : null,
2336
2182
  });
2337
2183
  }
2338
2184
  constructor(props) {
@@ -2382,7 +2228,6 @@ class ERBRescueNode extends Node {
2382
2228
  output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
2383
2229
  output += `├── statements: ${this.inspectArray(this.statements, "│ ")}`;
2384
2230
  output += `└── subsequent: ${this.inspectNode(this.subsequent, " ")}`;
2385
- // output += "\n";
2386
2231
  return output;
2387
2232
  }
2388
2233
  }
@@ -2444,7 +2289,6 @@ class ERBEnsureNode extends Node {
2444
2289
  output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
2445
2290
  output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
2446
2291
  output += `└── statements: ${this.inspectArray(this.statements, " ")}`;
2447
- // output += "\n";
2448
2292
  return output;
2449
2293
  }
2450
2294
  }
@@ -2466,10 +2310,10 @@ class ERBBeginNode extends Node {
2466
2310
  content: data.content ? Token.from(data.content) : null,
2467
2311
  tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
2468
2312
  statements: (data.statements || []).map(node => fromSerializedNode(node)),
2469
- rescue_clause: data.rescue_clause ? fromSerializedNode(data.rescue_clause) : null,
2470
- else_clause: data.else_clause ? fromSerializedNode(data.else_clause) : null,
2471
- ensure_clause: data.ensure_clause ? fromSerializedNode(data.ensure_clause) : null,
2472
- end_node: data.end_node ? fromSerializedNode(data.end_node) : null,
2313
+ rescue_clause: data.rescue_clause ? fromSerializedNode((data.rescue_clause)) : null,
2314
+ else_clause: data.else_clause ? fromSerializedNode((data.else_clause)) : null,
2315
+ ensure_clause: data.ensure_clause ? fromSerializedNode((data.ensure_clause)) : null,
2316
+ end_node: data.end_node ? fromSerializedNode((data.end_node)) : null,
2473
2317
  });
2474
2318
  }
2475
2319
  constructor(props) {
@@ -2534,7 +2378,6 @@ class ERBBeginNode extends Node {
2534
2378
  output += `├── else_clause: ${this.inspectNode(this.else_clause, "│ ")}`;
2535
2379
  output += `├── ensure_clause: ${this.inspectNode(this.ensure_clause, "│ ")}`;
2536
2380
  output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
2537
- // output += "\n";
2538
2381
  return output;
2539
2382
  }
2540
2383
  }
@@ -2554,8 +2397,8 @@ class ERBUnlessNode extends Node {
2554
2397
  content: data.content ? Token.from(data.content) : null,
2555
2398
  tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
2556
2399
  statements: (data.statements || []).map(node => fromSerializedNode(node)),
2557
- else_clause: data.else_clause ? fromSerializedNode(data.else_clause) : null,
2558
- end_node: data.end_node ? fromSerializedNode(data.end_node) : null,
2400
+ else_clause: data.else_clause ? fromSerializedNode((data.else_clause)) : null,
2401
+ end_node: data.end_node ? fromSerializedNode((data.end_node)) : null,
2559
2402
  });
2560
2403
  }
2561
2404
  constructor(props) {
@@ -2610,7 +2453,6 @@ class ERBUnlessNode extends Node {
2610
2453
  output += `├── statements: ${this.inspectArray(this.statements, "│ ")}`;
2611
2454
  output += `├── else_clause: ${this.inspectNode(this.else_clause, "│ ")}`;
2612
2455
  output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
2613
- // output += "\n";
2614
2456
  return output;
2615
2457
  }
2616
2458
  }
@@ -2664,7 +2506,6 @@ class ERBYieldNode extends Node {
2664
2506
  output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
2665
2507
  output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
2666
2508
  output += `└── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
2667
- // output += "\n";
2668
2509
  return output;
2669
2510
  }
2670
2511
  }
@@ -2726,7 +2567,6 @@ class ERBInNode extends Node {
2726
2567
  output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
2727
2568
  output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
2728
2569
  output += `└── statements: ${this.inspectArray(this.statements, " ")}`;
2729
- // output += "\n";
2730
2570
  return output;
2731
2571
  }
2732
2572
  }
@@ -2736,7 +2576,6 @@ function fromSerializedNode(node) {
2736
2576
  case "AST_LITERAL_NODE": return LiteralNode.from(node);
2737
2577
  case "AST_HTML_OPEN_TAG_NODE": return HTMLOpenTagNode.from(node);
2738
2578
  case "AST_HTML_CLOSE_TAG_NODE": return HTMLCloseTagNode.from(node);
2739
- case "AST_HTML_SELF_CLOSE_TAG_NODE": return HTMLSelfCloseTagNode.from(node);
2740
2579
  case "AST_HTML_ELEMENT_NODE": return HTMLElementNode.from(node);
2741
2580
  case "AST_HTML_ATTRIBUTE_VALUE_NODE": return HTMLAttributeValueNode.from(node);
2742
2581
  case "AST_HTML_ATTRIBUTE_NAME_NODE": return HTMLAttributeNameNode.from(node);
@@ -2744,6 +2583,8 @@ function fromSerializedNode(node) {
2744
2583
  case "AST_HTML_TEXT_NODE": return HTMLTextNode.from(node);
2745
2584
  case "AST_HTML_COMMENT_NODE": return HTMLCommentNode.from(node);
2746
2585
  case "AST_HTML_DOCTYPE_NODE": return HTMLDoctypeNode.from(node);
2586
+ case "AST_XML_DECLARATION_NODE": return XMLDeclarationNode.from(node);
2587
+ case "AST_CDATA_NODE": return CDATANode.from(node);
2747
2588
  case "AST_WHITESPACE_NODE": return WhitespaceNode.from(node);
2748
2589
  case "AST_ERB_CONTENT_NODE": return ERBContentNode.from(node);
2749
2590
  case "AST_ERB_END_NODE": return ERBEndNode.from(node);
@@ -2785,8 +2626,42 @@ const ERBNodeClasses = [
2785
2626
  ERBYieldNode,
2786
2627
  ERBInNode,
2787
2628
  ];
2788
- function isERBNode(node) {
2789
- return node.constructor.name.startsWith("ERB");
2629
+
2630
+ class Result {
2631
+ source;
2632
+ warnings;
2633
+ errors;
2634
+ constructor(source, warnings = [], errors = []) {
2635
+ this.source = source;
2636
+ this.warnings = warnings || [];
2637
+ this.errors = errors || [];
2638
+ }
2639
+ /**
2640
+ * Determines if the parsing was successful.
2641
+ * @returns `true` if there are no errors, otherwise `false`.
2642
+ */
2643
+ get successful() {
2644
+ return this.errors.length === 0;
2645
+ }
2646
+ /**
2647
+ * Determines if the parsing failed.
2648
+ * @returns `true` if there are errors, otherwise `false`.
2649
+ */
2650
+ get failed() {
2651
+ return this.errors.length > 0;
2652
+ }
2653
+ }
2654
+
2655
+ class HerbWarning {
2656
+ message;
2657
+ location;
2658
+ static from(warning) {
2659
+ return new HerbWarning(warning.message, Location.from(warning.location));
2660
+ }
2661
+ constructor(message, location) {
2662
+ this.message = message;
2663
+ this.location = location;
2664
+ }
2790
2665
  }
2791
2666
 
2792
2667
  /**
@@ -2856,125 +2731,1038 @@ class ParseResult extends Result {
2856
2731
  }
2857
2732
  }
2858
2733
 
2734
+ // NOTE: This file is generated by the templates/template.rb script and should not
2735
+ // be modified manually. See /Users/marcoroth/Development/herb-release-0.6.0/templates/javascript/packages/core/src/node-type-guards.ts.erb
2859
2736
  /**
2860
- * The main Herb parser interface, providing methods to lex and parse input.
2737
+ * Type guard functions for AST nodes.
2738
+ * These functions provide type checking by combining both instanceof
2739
+ * checks and type string comparisons for maximum reliability across different
2740
+ * runtime scenarios (e.g., serialized/deserialized nodes).
2861
2741
  */
2862
- class HerbBackend {
2863
- /** The backend instance handling lexing and parsing. */
2864
- backend = undefined;
2865
- backendPromise;
2866
- /**
2867
- * Creates a new Herb instance.
2868
- * @param backendPromise - A promise resolving to a `LibHerbBackend` implementation for lexing and parsing.
2869
- * @throws Error if no valid backend is provided.
2870
- */
2871
- constructor(backendPromise) {
2872
- if (!backendPromise) {
2873
- throw new Error("No LibHerb backend provided");
2874
- }
2875
- this.backendPromise = backendPromise;
2876
- }
2877
- /**
2878
- * Loads the backend by resolving the backend promise.
2879
- * @returns A promise containing the resolved `HerbBackend` instance after loading it.
2880
- */
2881
- async load() {
2882
- const backend = await this.backendPromise();
2883
- this.backend = backend;
2884
- return this;
2885
- }
2886
- /**
2887
- * Lexes the given source string into a `LexResult`.
2888
- * @param source - The source code to lex.
2889
- * @returns A `LexResult` instance.
2890
- * @throws Error if the backend is not loaded.
2891
- */
2892
- lex(source) {
2893
- this.ensureBackend();
2894
- return LexResult.from(this.backend.lex(ensureString(source)));
2895
- }
2896
- /**
2897
- * Lexes a file.
2898
- * @param path - The file path to lex.
2899
- * @returns A `LexResult` instance.
2900
- * @throws Error if the backend is not loaded.
2901
- */
2902
- lexFile(path) {
2903
- this.ensureBackend();
2904
- return LexResult.from(this.backend.lexFile(ensureString(path)));
2905
- }
2906
- /**
2907
- * Parses the given source string into a `ParseResult`.
2908
- * @param source - The source code to parse.
2909
- * @returns A `ParseResult` instance.
2910
- * @throws Error if the backend is not loaded.
2911
- */
2912
- parse(source) {
2913
- this.ensureBackend();
2914
- return ParseResult.from(this.backend.parse(ensureString(source)));
2915
- }
2916
- /**
2917
- * Parses a file.
2918
- * @param path - The file path to parse.
2919
- * @returns A `ParseResult` instance.
2920
- * @throws Error if the backend is not loaded.
2921
- */
2922
- parseFile(path) {
2923
- this.ensureBackend();
2924
- return ParseResult.from(this.backend.parseFile(ensureString(path)));
2925
- }
2926
- /**
2927
- * Extracts embedded Ruby code from the given source.
2928
- * @param source - The source code to extract Ruby from.
2929
- * @returns The extracted Ruby code as a string.
2930
- * @throws Error if the backend is not loaded.
2931
- */
2932
- extractRuby(source) {
2933
- this.ensureBackend();
2934
- return this.backend.extractRuby(ensureString(source));
2935
- }
2936
- /**
2937
- * Extracts HTML from the given source.
2938
- * @param source - The source code to extract HTML from.
2939
- * @returns The extracted HTML as a string.
2940
- * @throws Error if the backend is not loaded.
2941
- */
2942
- extractHTML(source) {
2943
- this.ensureBackend();
2944
- return this.backend.extractHTML(ensureString(source));
2945
- }
2946
- /**
2947
- * Gets the Herb version information, including the core and backend versions.
2948
- * @returns A version string containing backend, core, and libherb versions.
2949
- * @throws Error if the backend is not loaded.
2950
- */
2951
- get version() {
2952
- this.ensureBackend();
2953
- const backend = this.backendVersion();
2954
- const core = `${packageJSON.name}@${packageJSON.version}`;
2955
- const libherb = this.backend.version();
2956
- return `${backend}, ${core}, ${libherb}`;
2957
- }
2958
- /**
2959
- * Ensures that the backend is loaded.
2960
- * @throws Error if the backend is not loaded.
2961
- */
2962
- ensureBackend() {
2963
- if (!this.isLoaded) {
2964
- throw new Error("Herb backend is not loaded. Call `await Herb.load()` first.");
2965
- }
2966
- }
2967
- /**
2968
- * Checks if the backend is loaded.
2969
- * @returns True if the backend is loaded, false otherwise.
2970
- */
2971
- get isLoaded() {
2742
+ /**
2743
+ * Checks if a node is a DocumentNode
2744
+ */
2745
+ function isDocumentNode(node) {
2746
+ return node instanceof DocumentNode || node.type === "AST_DOCUMENT_NODE";
2747
+ }
2748
+ /**
2749
+ * Checks if a node is a LiteralNode
2750
+ */
2751
+ function isLiteralNode(node) {
2752
+ return node instanceof LiteralNode || node.type === "AST_LITERAL_NODE";
2753
+ }
2754
+ /**
2755
+ * Checks if a node is a HTMLOpenTagNode
2756
+ */
2757
+ function isHTMLOpenTagNode(node) {
2758
+ return node instanceof HTMLOpenTagNode || node.type === "AST_HTML_OPEN_TAG_NODE";
2759
+ }
2760
+ /**
2761
+ * Checks if a node is a HTMLCloseTagNode
2762
+ */
2763
+ function isHTMLCloseTagNode(node) {
2764
+ return node instanceof HTMLCloseTagNode || node.type === "AST_HTML_CLOSE_TAG_NODE";
2765
+ }
2766
+ /**
2767
+ * Checks if a node is a HTMLElementNode
2768
+ */
2769
+ function isHTMLElementNode(node) {
2770
+ return node instanceof HTMLElementNode || node.type === "AST_HTML_ELEMENT_NODE";
2771
+ }
2772
+ /**
2773
+ * Checks if a node is a HTMLAttributeValueNode
2774
+ */
2775
+ function isHTMLAttributeValueNode(node) {
2776
+ return node instanceof HTMLAttributeValueNode || node.type === "AST_HTML_ATTRIBUTE_VALUE_NODE";
2777
+ }
2778
+ /**
2779
+ * Checks if a node is a HTMLAttributeNameNode
2780
+ */
2781
+ function isHTMLAttributeNameNode(node) {
2782
+ return node instanceof HTMLAttributeNameNode || node.type === "AST_HTML_ATTRIBUTE_NAME_NODE";
2783
+ }
2784
+ /**
2785
+ * Checks if a node is a HTMLAttributeNode
2786
+ */
2787
+ function isHTMLAttributeNode(node) {
2788
+ return node instanceof HTMLAttributeNode || node.type === "AST_HTML_ATTRIBUTE_NODE";
2789
+ }
2790
+ /**
2791
+ * Checks if a node is a HTMLTextNode
2792
+ */
2793
+ function isHTMLTextNode(node) {
2794
+ return node instanceof HTMLTextNode || node.type === "AST_HTML_TEXT_NODE";
2795
+ }
2796
+ /**
2797
+ * Checks if a node is a HTMLCommentNode
2798
+ */
2799
+ function isHTMLCommentNode(node) {
2800
+ return node instanceof HTMLCommentNode || node.type === "AST_HTML_COMMENT_NODE";
2801
+ }
2802
+ /**
2803
+ * Checks if a node is a HTMLDoctypeNode
2804
+ */
2805
+ function isHTMLDoctypeNode(node) {
2806
+ return node instanceof HTMLDoctypeNode || node.type === "AST_HTML_DOCTYPE_NODE";
2807
+ }
2808
+ /**
2809
+ * Checks if a node is a XMLDeclarationNode
2810
+ */
2811
+ function isXMLDeclarationNode(node) {
2812
+ return node instanceof XMLDeclarationNode || node.type === "AST_XML_DECLARATION_NODE";
2813
+ }
2814
+ /**
2815
+ * Checks if a node is a CDATANode
2816
+ */
2817
+ function isCDATANode(node) {
2818
+ return node instanceof CDATANode || node.type === "AST_CDATA_NODE";
2819
+ }
2820
+ /**
2821
+ * Checks if a node is a WhitespaceNode
2822
+ */
2823
+ function isWhitespaceNode(node) {
2824
+ return node instanceof WhitespaceNode || node.type === "AST_WHITESPACE_NODE";
2825
+ }
2826
+ /**
2827
+ * Checks if a node is a ERBContentNode
2828
+ */
2829
+ function isERBContentNode(node) {
2830
+ return node instanceof ERBContentNode || node.type === "AST_ERB_CONTENT_NODE";
2831
+ }
2832
+ /**
2833
+ * Checks if a node is a ERBEndNode
2834
+ */
2835
+ function isERBEndNode(node) {
2836
+ return node instanceof ERBEndNode || node.type === "AST_ERB_END_NODE";
2837
+ }
2838
+ /**
2839
+ * Checks if a node is a ERBElseNode
2840
+ */
2841
+ function isERBElseNode(node) {
2842
+ return node instanceof ERBElseNode || node.type === "AST_ERB_ELSE_NODE";
2843
+ }
2844
+ /**
2845
+ * Checks if a node is a ERBIfNode
2846
+ */
2847
+ function isERBIfNode(node) {
2848
+ return node instanceof ERBIfNode || node.type === "AST_ERB_IF_NODE";
2849
+ }
2850
+ /**
2851
+ * Checks if a node is a ERBBlockNode
2852
+ */
2853
+ function isERBBlockNode(node) {
2854
+ return node instanceof ERBBlockNode || node.type === "AST_ERB_BLOCK_NODE";
2855
+ }
2856
+ /**
2857
+ * Checks if a node is a ERBWhenNode
2858
+ */
2859
+ function isERBWhenNode(node) {
2860
+ return node instanceof ERBWhenNode || node.type === "AST_ERB_WHEN_NODE";
2861
+ }
2862
+ /**
2863
+ * Checks if a node is a ERBCaseNode
2864
+ */
2865
+ function isERBCaseNode(node) {
2866
+ return node instanceof ERBCaseNode || node.type === "AST_ERB_CASE_NODE";
2867
+ }
2868
+ /**
2869
+ * Checks if a node is a ERBCaseMatchNode
2870
+ */
2871
+ function isERBCaseMatchNode(node) {
2872
+ return node instanceof ERBCaseMatchNode || node.type === "AST_ERB_CASE_MATCH_NODE";
2873
+ }
2874
+ /**
2875
+ * Checks if a node is a ERBWhileNode
2876
+ */
2877
+ function isERBWhileNode(node) {
2878
+ return node instanceof ERBWhileNode || node.type === "AST_ERB_WHILE_NODE";
2879
+ }
2880
+ /**
2881
+ * Checks if a node is a ERBUntilNode
2882
+ */
2883
+ function isERBUntilNode(node) {
2884
+ return node instanceof ERBUntilNode || node.type === "AST_ERB_UNTIL_NODE";
2885
+ }
2886
+ /**
2887
+ * Checks if a node is a ERBForNode
2888
+ */
2889
+ function isERBForNode(node) {
2890
+ return node instanceof ERBForNode || node.type === "AST_ERB_FOR_NODE";
2891
+ }
2892
+ /**
2893
+ * Checks if a node is a ERBRescueNode
2894
+ */
2895
+ function isERBRescueNode(node) {
2896
+ return node instanceof ERBRescueNode || node.type === "AST_ERB_RESCUE_NODE";
2897
+ }
2898
+ /**
2899
+ * Checks if a node is a ERBEnsureNode
2900
+ */
2901
+ function isERBEnsureNode(node) {
2902
+ return node instanceof ERBEnsureNode || node.type === "AST_ERB_ENSURE_NODE";
2903
+ }
2904
+ /**
2905
+ * Checks if a node is a ERBBeginNode
2906
+ */
2907
+ function isERBBeginNode(node) {
2908
+ return node instanceof ERBBeginNode || node.type === "AST_ERB_BEGIN_NODE";
2909
+ }
2910
+ /**
2911
+ * Checks if a node is a ERBUnlessNode
2912
+ */
2913
+ function isERBUnlessNode(node) {
2914
+ return node instanceof ERBUnlessNode || node.type === "AST_ERB_UNLESS_NODE";
2915
+ }
2916
+ /**
2917
+ * Checks if a node is a ERBYieldNode
2918
+ */
2919
+ function isERBYieldNode(node) {
2920
+ return node instanceof ERBYieldNode || node.type === "AST_ERB_YIELD_NODE";
2921
+ }
2922
+ /**
2923
+ * Checks if a node is a ERBInNode
2924
+ */
2925
+ function isERBInNode(node) {
2926
+ return node instanceof ERBInNode || node.type === "AST_ERB_IN_NODE";
2927
+ }
2928
+ /**
2929
+ * Convenience type guards for common node categories
2930
+ */
2931
+ /**
2932
+ * Checks if a node is any HTML node type
2933
+ */
2934
+ function isHTMLNode(node) {
2935
+ return isHTMLOpenTagNode(node) ||
2936
+ isHTMLCloseTagNode(node) ||
2937
+ isHTMLElementNode(node) ||
2938
+ isHTMLAttributeValueNode(node) ||
2939
+ isHTMLAttributeNameNode(node) ||
2940
+ isHTMLAttributeNode(node) ||
2941
+ isHTMLTextNode(node) ||
2942
+ isHTMLCommentNode(node) ||
2943
+ isHTMLDoctypeNode(node);
2944
+ }
2945
+ /**
2946
+ * Checks if a node is any ERB node type
2947
+ */
2948
+ function isERBNode(node) {
2949
+ return isERBContentNode(node) ||
2950
+ isERBEndNode(node) ||
2951
+ isERBElseNode(node) ||
2952
+ isERBIfNode(node) ||
2953
+ isERBBlockNode(node) ||
2954
+ isERBWhenNode(node) ||
2955
+ isERBCaseNode(node) ||
2956
+ isERBCaseMatchNode(node) ||
2957
+ isERBWhileNode(node) ||
2958
+ isERBUntilNode(node) ||
2959
+ isERBForNode(node) ||
2960
+ isERBRescueNode(node) ||
2961
+ isERBEnsureNode(node) ||
2962
+ isERBBeginNode(node) ||
2963
+ isERBUnlessNode(node) ||
2964
+ isERBYieldNode(node) ||
2965
+ isERBInNode(node);
2966
+ }
2967
+ /**
2968
+ * Map of node classes to their corresponding type guard functions
2969
+ *
2970
+ * @example
2971
+ * const guard = NODE_TYPE_GUARDS[HTMLTextNode]
2972
+ *
2973
+ * if (guard(node)) {
2974
+ * // node is HTMLTextNode
2975
+ * }
2976
+ */
2977
+ const NODE_TYPE_GUARDS = new Map([
2978
+ [DocumentNode, isDocumentNode],
2979
+ [LiteralNode, isLiteralNode],
2980
+ [HTMLOpenTagNode, isHTMLOpenTagNode],
2981
+ [HTMLCloseTagNode, isHTMLCloseTagNode],
2982
+ [HTMLElementNode, isHTMLElementNode],
2983
+ [HTMLAttributeValueNode, isHTMLAttributeValueNode],
2984
+ [HTMLAttributeNameNode, isHTMLAttributeNameNode],
2985
+ [HTMLAttributeNode, isHTMLAttributeNode],
2986
+ [HTMLTextNode, isHTMLTextNode],
2987
+ [HTMLCommentNode, isHTMLCommentNode],
2988
+ [HTMLDoctypeNode, isHTMLDoctypeNode],
2989
+ [XMLDeclarationNode, isXMLDeclarationNode],
2990
+ [CDATANode, isCDATANode],
2991
+ [WhitespaceNode, isWhitespaceNode],
2992
+ [ERBContentNode, isERBContentNode],
2993
+ [ERBEndNode, isERBEndNode],
2994
+ [ERBElseNode, isERBElseNode],
2995
+ [ERBIfNode, isERBIfNode],
2996
+ [ERBBlockNode, isERBBlockNode],
2997
+ [ERBWhenNode, isERBWhenNode],
2998
+ [ERBCaseNode, isERBCaseNode],
2999
+ [ERBCaseMatchNode, isERBCaseMatchNode],
3000
+ [ERBWhileNode, isERBWhileNode],
3001
+ [ERBUntilNode, isERBUntilNode],
3002
+ [ERBForNode, isERBForNode],
3003
+ [ERBRescueNode, isERBRescueNode],
3004
+ [ERBEnsureNode, isERBEnsureNode],
3005
+ [ERBBeginNode, isERBBeginNode],
3006
+ [ERBUnlessNode, isERBUnlessNode],
3007
+ [ERBYieldNode, isERBYieldNode],
3008
+ [ERBInNode, isERBInNode],
3009
+ ]);
3010
+ /**
3011
+ * Map of AST node type strings to their corresponding type guard functions
3012
+ *
3013
+ * @example
3014
+ * const guard = AST_TYPE_GUARDS["AST_HTML_TEXT_NODE"]
3015
+ *
3016
+ * if (guard(node)) {
3017
+ * // node is HTMLTextNode
3018
+ * }
3019
+ */
3020
+ const AST_TYPE_GUARDS = new Map([
3021
+ ["AST_DOCUMENT_NODE", isDocumentNode],
3022
+ ["AST_LITERAL_NODE", isLiteralNode],
3023
+ ["AST_HTML_OPEN_TAG_NODE", isHTMLOpenTagNode],
3024
+ ["AST_HTML_CLOSE_TAG_NODE", isHTMLCloseTagNode],
3025
+ ["AST_HTML_ELEMENT_NODE", isHTMLElementNode],
3026
+ ["AST_HTML_ATTRIBUTE_VALUE_NODE", isHTMLAttributeValueNode],
3027
+ ["AST_HTML_ATTRIBUTE_NAME_NODE", isHTMLAttributeNameNode],
3028
+ ["AST_HTML_ATTRIBUTE_NODE", isHTMLAttributeNode],
3029
+ ["AST_HTML_TEXT_NODE", isHTMLTextNode],
3030
+ ["AST_HTML_COMMENT_NODE", isHTMLCommentNode],
3031
+ ["AST_HTML_DOCTYPE_NODE", isHTMLDoctypeNode],
3032
+ ["AST_XML_DECLARATION_NODE", isXMLDeclarationNode],
3033
+ ["AST_CDATA_NODE", isCDATANode],
3034
+ ["AST_WHITESPACE_NODE", isWhitespaceNode],
3035
+ ["AST_ERB_CONTENT_NODE", isERBContentNode],
3036
+ ["AST_ERB_END_NODE", isERBEndNode],
3037
+ ["AST_ERB_ELSE_NODE", isERBElseNode],
3038
+ ["AST_ERB_IF_NODE", isERBIfNode],
3039
+ ["AST_ERB_BLOCK_NODE", isERBBlockNode],
3040
+ ["AST_ERB_WHEN_NODE", isERBWhenNode],
3041
+ ["AST_ERB_CASE_NODE", isERBCaseNode],
3042
+ ["AST_ERB_CASE_MATCH_NODE", isERBCaseMatchNode],
3043
+ ["AST_ERB_WHILE_NODE", isERBWhileNode],
3044
+ ["AST_ERB_UNTIL_NODE", isERBUntilNode],
3045
+ ["AST_ERB_FOR_NODE", isERBForNode],
3046
+ ["AST_ERB_RESCUE_NODE", isERBRescueNode],
3047
+ ["AST_ERB_ENSURE_NODE", isERBEnsureNode],
3048
+ ["AST_ERB_BEGIN_NODE", isERBBeginNode],
3049
+ ["AST_ERB_UNLESS_NODE", isERBUnlessNode],
3050
+ ["AST_ERB_YIELD_NODE", isERBYieldNode],
3051
+ ["AST_ERB_IN_NODE", isERBInNode],
3052
+ ]);
3053
+ /**
3054
+ * Checks if a node matches any of the provided type identifiers with proper type narrowing
3055
+ * Supports AST type strings, node classes, or type guard functions
3056
+ *
3057
+ * @example
3058
+ * if (isAnyOf(node, "AST_HTML_TEXT_NODE", "AST_LITERAL_NODE")) {
3059
+ * // node is narrowed to HTMLTextNode | LiteralNode
3060
+ * }
3061
+ *
3062
+ * @example
3063
+ * if (isAnyOf(node, HTMLTextNode, LiteralNode)) {
3064
+ * // node is narrowed to HTMLTextNode | LiteralNode
3065
+ * }
3066
+ */
3067
+ function isAnyOf(node, ...types) {
3068
+ return types.some(type => {
3069
+ if (typeof type === 'string') {
3070
+ return isNode(node, type);
3071
+ }
3072
+ else if (typeof type === 'function' && type.prototype && type.prototype.constructor === type && NODE_TYPE_GUARDS.has(type)) {
3073
+ return isNode(node, type);
3074
+ }
3075
+ else if (typeof type === 'function') {
3076
+ return type(node);
3077
+ }
3078
+ else {
3079
+ return false;
3080
+ }
3081
+ });
3082
+ }
3083
+ /**
3084
+ * Checks if a node does NOT match any of the provided type identifiers
3085
+ * Supports AST type strings, node classes, or type guard functions
3086
+ * This is the logical inverse of isAnyOf
3087
+ *
3088
+ * @example
3089
+ * if (isNoneOf(node, "AST_HTML_TEXT_NODE", "AST_LITERAL_NODE")) {
3090
+ * // node is neither HTMLTextNode nor LiteralNode
3091
+ * }
3092
+ *
3093
+ * @example
3094
+ * if (isNoneOf(node, HTMLTextNode, LiteralNode)) {
3095
+ * // node is neither HTMLTextNode nor LiteralNode
3096
+ * }
3097
+ *
3098
+ * @example
3099
+ * if (isNoneOf(node, isHTMLTextNode, isLiteralNode)) {
3100
+ * // node is neither HTMLTextNode nor LiteralNode
3101
+ * }
3102
+ */
3103
+ function isNoneOf(node, ...types) {
3104
+ return !isAnyOf(node, ...types);
3105
+ }
3106
+ function areAllOfType(nodes, ...types) {
3107
+ return nodes.every(node => isAnyOf(node, ...types));
3108
+ }
3109
+ function filterNodes(nodes, ...types) {
3110
+ if (!nodes)
3111
+ return [];
3112
+ return nodes.filter(node => isAnyOf(node, ...types));
3113
+ }
3114
+ function isNode(node, type) {
3115
+ if (typeof type === 'string') {
3116
+ const guard = AST_TYPE_GUARDS.get(type);
3117
+ return guard ? guard(node) : false;
3118
+ }
3119
+ else if (typeof type === 'function') {
3120
+ const guard = NODE_TYPE_GUARDS.get(type);
3121
+ return guard ? guard(node) : false;
3122
+ }
3123
+ else {
3124
+ return false;
3125
+ }
3126
+ }
3127
+ function isToken(object) {
3128
+ return (object instanceof Token) || (object?.constructor?.name === "Token" && "value" in object) || object.type?.startsWith('TOKEN_');
3129
+ }
3130
+ function isParseResult(object) {
3131
+ return (object instanceof ParseResult) || (object?.constructor?.name === "ParseResult" && "value" in object);
3132
+ }
3133
+ /**
3134
+ * Checks if a node has children (contains other nodes)
3135
+ */
3136
+ function hasChildren(node) {
3137
+ return isDocumentNode(node) ||
3138
+ isHTMLOpenTagNode(node) ||
3139
+ isHTMLCloseTagNode(node) ||
3140
+ isHTMLElementNode(node) ||
3141
+ isHTMLAttributeValueNode(node) ||
3142
+ isHTMLAttributeNameNode(node) ||
3143
+ isHTMLCommentNode(node) ||
3144
+ isHTMLDoctypeNode(node) ||
3145
+ isERBElseNode(node) ||
3146
+ isERBIfNode(node) ||
3147
+ isERBBlockNode(node) ||
3148
+ isERBWhenNode(node) ||
3149
+ isERBCaseNode(node) ||
3150
+ isERBCaseMatchNode(node) ||
3151
+ isERBWhileNode(node) ||
3152
+ isERBUntilNode(node) ||
3153
+ isERBForNode(node) ||
3154
+ isERBRescueNode(node) ||
3155
+ isERBEnsureNode(node) ||
3156
+ isERBBeginNode(node) ||
3157
+ isERBUnlessNode(node) ||
3158
+ isERBInNode(node);
3159
+ }
3160
+ /**
3161
+ * Filter functions for extracting specific node types from arrays
3162
+ */
3163
+ /**
3164
+ * Filters an array of nodes to only include DocumentNode nodes
3165
+ */
3166
+ function filterDocumentNodes(nodes) {
3167
+ return nodes.filter(isDocumentNode);
3168
+ }
3169
+ /**
3170
+ * Filters an array of nodes to only include LiteralNode nodes
3171
+ */
3172
+ function filterLiteralNodes(nodes) {
3173
+ return nodes.filter(isLiteralNode);
3174
+ }
3175
+ /**
3176
+ * Filters an array of nodes to only include HTMLOpenTagNode nodes
3177
+ */
3178
+ function filterHTMLOpenTagNodes(nodes) {
3179
+ return nodes.filter(isHTMLOpenTagNode);
3180
+ }
3181
+ /**
3182
+ * Filters an array of nodes to only include HTMLCloseTagNode nodes
3183
+ */
3184
+ function filterHTMLCloseTagNodes(nodes) {
3185
+ return nodes.filter(isHTMLCloseTagNode);
3186
+ }
3187
+ /**
3188
+ * Filters an array of nodes to only include HTMLElementNode nodes
3189
+ */
3190
+ function filterHTMLElementNodes(nodes) {
3191
+ return nodes.filter(isHTMLElementNode);
3192
+ }
3193
+ /**
3194
+ * Filters an array of nodes to only include HTMLAttributeValueNode nodes
3195
+ */
3196
+ function filterHTMLAttributeValueNodes(nodes) {
3197
+ return nodes.filter(isHTMLAttributeValueNode);
3198
+ }
3199
+ /**
3200
+ * Filters an array of nodes to only include HTMLAttributeNameNode nodes
3201
+ */
3202
+ function filterHTMLAttributeNameNodes(nodes) {
3203
+ return nodes.filter(isHTMLAttributeNameNode);
3204
+ }
3205
+ /**
3206
+ * Filters an array of nodes to only include HTMLAttributeNode nodes
3207
+ */
3208
+ function filterHTMLAttributeNodes(nodes) {
3209
+ return nodes.filter(isHTMLAttributeNode);
3210
+ }
3211
+ /**
3212
+ * Filters an array of nodes to only include HTMLTextNode nodes
3213
+ */
3214
+ function filterHTMLTextNodes(nodes) {
3215
+ return nodes.filter(isHTMLTextNode);
3216
+ }
3217
+ /**
3218
+ * Filters an array of nodes to only include HTMLCommentNode nodes
3219
+ */
3220
+ function filterHTMLCommentNodes(nodes) {
3221
+ return nodes.filter(isHTMLCommentNode);
3222
+ }
3223
+ /**
3224
+ * Filters an array of nodes to only include HTMLDoctypeNode nodes
3225
+ */
3226
+ function filterHTMLDoctypeNodes(nodes) {
3227
+ return nodes.filter(isHTMLDoctypeNode);
3228
+ }
3229
+ /**
3230
+ * Filters an array of nodes to only include XMLDeclarationNode nodes
3231
+ */
3232
+ function filterXMLDeclarationNodes(nodes) {
3233
+ return nodes.filter(isXMLDeclarationNode);
3234
+ }
3235
+ /**
3236
+ * Filters an array of nodes to only include CDATANode nodes
3237
+ */
3238
+ function filterCDATANodes(nodes) {
3239
+ return nodes.filter(isCDATANode);
3240
+ }
3241
+ /**
3242
+ * Filters an array of nodes to only include WhitespaceNode nodes
3243
+ */
3244
+ function filterWhitespaceNodes(nodes) {
3245
+ return nodes.filter(isWhitespaceNode);
3246
+ }
3247
+ /**
3248
+ * Filters an array of nodes to only include ERBContentNode nodes
3249
+ */
3250
+ function filterERBContentNodes(nodes) {
3251
+ return nodes.filter(isERBContentNode);
3252
+ }
3253
+ /**
3254
+ * Filters an array of nodes to only include ERBEndNode nodes
3255
+ */
3256
+ function filterERBEndNodes(nodes) {
3257
+ return nodes.filter(isERBEndNode);
3258
+ }
3259
+ /**
3260
+ * Filters an array of nodes to only include ERBElseNode nodes
3261
+ */
3262
+ function filterERBElseNodes(nodes) {
3263
+ return nodes.filter(isERBElseNode);
3264
+ }
3265
+ /**
3266
+ * Filters an array of nodes to only include ERBIfNode nodes
3267
+ */
3268
+ function filterERBIfNodes(nodes) {
3269
+ return nodes.filter(isERBIfNode);
3270
+ }
3271
+ /**
3272
+ * Filters an array of nodes to only include ERBBlockNode nodes
3273
+ */
3274
+ function filterERBBlockNodes(nodes) {
3275
+ return nodes.filter(isERBBlockNode);
3276
+ }
3277
+ /**
3278
+ * Filters an array of nodes to only include ERBWhenNode nodes
3279
+ */
3280
+ function filterERBWhenNodes(nodes) {
3281
+ return nodes.filter(isERBWhenNode);
3282
+ }
3283
+ /**
3284
+ * Filters an array of nodes to only include ERBCaseNode nodes
3285
+ */
3286
+ function filterERBCaseNodes(nodes) {
3287
+ return nodes.filter(isERBCaseNode);
3288
+ }
3289
+ /**
3290
+ * Filters an array of nodes to only include ERBCaseMatchNode nodes
3291
+ */
3292
+ function filterERBCaseMatchNodes(nodes) {
3293
+ return nodes.filter(isERBCaseMatchNode);
3294
+ }
3295
+ /**
3296
+ * Filters an array of nodes to only include ERBWhileNode nodes
3297
+ */
3298
+ function filterERBWhileNodes(nodes) {
3299
+ return nodes.filter(isERBWhileNode);
3300
+ }
3301
+ /**
3302
+ * Filters an array of nodes to only include ERBUntilNode nodes
3303
+ */
3304
+ function filterERBUntilNodes(nodes) {
3305
+ return nodes.filter(isERBUntilNode);
3306
+ }
3307
+ /**
3308
+ * Filters an array of nodes to only include ERBForNode nodes
3309
+ */
3310
+ function filterERBForNodes(nodes) {
3311
+ return nodes.filter(isERBForNode);
3312
+ }
3313
+ /**
3314
+ * Filters an array of nodes to only include ERBRescueNode nodes
3315
+ */
3316
+ function filterERBRescueNodes(nodes) {
3317
+ return nodes.filter(isERBRescueNode);
3318
+ }
3319
+ /**
3320
+ * Filters an array of nodes to only include ERBEnsureNode nodes
3321
+ */
3322
+ function filterERBEnsureNodes(nodes) {
3323
+ return nodes.filter(isERBEnsureNode);
3324
+ }
3325
+ /**
3326
+ * Filters an array of nodes to only include ERBBeginNode nodes
3327
+ */
3328
+ function filterERBBeginNodes(nodes) {
3329
+ return nodes.filter(isERBBeginNode);
3330
+ }
3331
+ /**
3332
+ * Filters an array of nodes to only include ERBUnlessNode nodes
3333
+ */
3334
+ function filterERBUnlessNodes(nodes) {
3335
+ return nodes.filter(isERBUnlessNode);
3336
+ }
3337
+ /**
3338
+ * Filters an array of nodes to only include ERBYieldNode nodes
3339
+ */
3340
+ function filterERBYieldNodes(nodes) {
3341
+ return nodes.filter(isERBYieldNode);
3342
+ }
3343
+ /**
3344
+ * Filters an array of nodes to only include ERBInNode nodes
3345
+ */
3346
+ function filterERBInNodes(nodes) {
3347
+ return nodes.filter(isERBInNode);
3348
+ }
3349
+
3350
+ /**
3351
+ * Checks if a node is an ERB output node (generates content: <%= %> or <%== %>)
3352
+ */
3353
+ function isERBOutputNode(node) {
3354
+ return isNode(node, ERBContentNode) && ["<%=", "<%=="].includes(node.tag_opening?.value);
3355
+ }
3356
+ /**
3357
+ * Checks if a node is a non-output ERB node (control flow: <% %>)
3358
+ */
3359
+ function isERBControlFlowNode(node) {
3360
+ return isAnyOf(node, ERBIfNode, ERBUnlessNode, ERBBlockNode, ERBCaseNode, ERBCaseMatchNode, ERBWhileNode, ERBForNode, ERBBeginNode);
3361
+ }
3362
+ /**
3363
+ * Checks if an array of nodes contains any ERB content nodes
3364
+ */
3365
+ function hasERBContent(nodes) {
3366
+ return nodes.some(isERBContentNode);
3367
+ }
3368
+ /**
3369
+ * Checks if an array of nodes contains any ERB output nodes (dynamic content)
3370
+ */
3371
+ function hasERBOutput(nodes) {
3372
+ return nodes.some(isERBOutputNode);
3373
+ }
3374
+ /**
3375
+ * Extracts a static string from an array of literal nodes
3376
+ * Returns null if any node is not a literal node
3377
+ */
3378
+ function getStaticStringFromNodes(nodes) {
3379
+ if (!areAllOfType(nodes, LiteralNode)) {
3380
+ return null;
3381
+ }
3382
+ return nodes.map(node => node.content).join("");
3383
+ }
3384
+ /**
3385
+ * Extracts static content from nodes, including mixed literal/ERB content
3386
+ * Returns the concatenated literal content, or null if no literal nodes exist
3387
+ */
3388
+ function getStaticContentFromNodes(nodes) {
3389
+ const literalNodes = filterLiteralNodes(nodes);
3390
+ if (literalNodes.length === 0) {
3391
+ return null;
3392
+ }
3393
+ return literalNodes.map(node => node.content).join("");
3394
+ }
3395
+ /**
3396
+ * Checks if nodes contain any literal content (for static validation)
3397
+ */
3398
+ function hasStaticContent(nodes) {
3399
+ return nodes.some(isLiteralNode);
3400
+ }
3401
+ /**
3402
+ * Checks if nodes are effectively static (only literals and non-output ERB)
3403
+ * Non-output ERB like <% if %> doesn't affect static validation
3404
+ */
3405
+ function isEffectivelyStatic(nodes) {
3406
+ return !hasERBOutput(nodes);
3407
+ }
3408
+ /**
3409
+ * Gets static-validatable content from nodes (ignores control ERB, includes literals)
3410
+ * Returns concatenated literal content for validation, or null if contains output ERB
3411
+ */
3412
+ function getValidatableStaticContent(nodes) {
3413
+ if (hasERBOutput(nodes)) {
3414
+ return null;
3415
+ }
3416
+ return filterLiteralNodes(nodes).map(node => node.content).join("");
3417
+ }
3418
+ /**
3419
+ * Extracts a combined string from nodes, including ERB content
3420
+ * For ERB nodes, includes the full tag syntax (e.g., "<%= foo %>")
3421
+ * This is useful for debugging or displaying the full attribute name
3422
+ */
3423
+ function getCombinedStringFromNodes(nodes) {
3424
+ return nodes.map(node => {
3425
+ if (isLiteralNode(node)) {
3426
+ return node.content;
3427
+ }
3428
+ else if (isERBContentNode(node)) {
3429
+ const opening = node.tag_opening?.value || "";
3430
+ const content = node.content?.value || "";
3431
+ const closing = node.tag_closing?.value || "";
3432
+ return `${opening}${content}${closing}`;
3433
+ }
3434
+ else {
3435
+ // For other node types, return a placeholder or empty string
3436
+ return `[${node.type}]`;
3437
+ }
3438
+ }).join("");
3439
+ }
3440
+ /**
3441
+ * Checks if an HTML attribute name node has a static (literal-only) name
3442
+ */
3443
+ function hasStaticAttributeName(attributeNameNode) {
3444
+ if (!attributeNameNode.children) {
3445
+ return false;
3446
+ }
3447
+ return areAllOfType(attributeNameNode.children, LiteralNode);
3448
+ }
3449
+ /**
3450
+ * Checks if an HTML attribute name node has dynamic content (contains ERB)
3451
+ */
3452
+ function hasDynamicAttributeName(attributeNameNode) {
3453
+ if (!attributeNameNode.children) {
3454
+ return false;
3455
+ }
3456
+ return hasERBContent(attributeNameNode.children);
3457
+ }
3458
+ /**
3459
+ * Gets the static string value of an HTML attribute name node
3460
+ * Returns null if the attribute name contains dynamic content (ERB)
3461
+ */
3462
+ function getStaticAttributeName(attributeNameNode) {
3463
+ if (!attributeNameNode.children) {
3464
+ return null;
3465
+ }
3466
+ return getStaticStringFromNodes(attributeNameNode.children);
3467
+ }
3468
+ /**
3469
+ * Gets the combined string representation of an HTML attribute name node
3470
+ * This includes both static and dynamic content, useful for debugging
3471
+ */
3472
+ function getCombinedAttributeName(attributeNameNode) {
3473
+ if (!attributeNameNode.children) {
3474
+ return "";
3475
+ }
3476
+ return getCombinedStringFromNodes(attributeNameNode.children);
3477
+ }
3478
+ /**
3479
+ * Gets the tag name of an HTML element node
3480
+ */
3481
+ function getTagName(node) {
3482
+ return node.tag_name?.value ?? "";
3483
+ }
3484
+ /**
3485
+ * Check if a node is a comment (HTML comment or ERB comment)
3486
+ */
3487
+ function isCommentNode(node) {
3488
+ return isNode(node, HTMLCommentNode) || (isERBNode(node) && !isERBControlFlowNode(node));
3489
+ }
3490
+
3491
+ const expectedFunctions = [
3492
+ "parse",
3493
+ "lex",
3494
+ "parseFile",
3495
+ "lexFile",
3496
+ "extractRuby",
3497
+ "extractHTML",
3498
+ "version",
3499
+ ];
3500
+ // NOTE: This function should never be called and is only for type checking
3501
+ // so we can make sure `expectedFunctions` matches the functions defined
3502
+ // in `LibHerbBackendFunctions` and the other way around.
3503
+ //
3504
+ function _TYPECHECK() {
3505
+ const checkFunctionsExist = true;
3506
+ const checkInterfaceComplete = true;
3507
+ return { checkFunctionsExist, checkInterfaceComplete };
3508
+ }
3509
+ function isLibHerbBackend(object, libherbpath = "unknown") {
3510
+ for (const expectedFunction of expectedFunctions) {
3511
+ if (object[expectedFunction] === undefined) {
3512
+ throw new Error(`Libherb at "${libherbpath}" doesn't expose function "${expectedFunction}".`);
3513
+ }
3514
+ if (typeof object[expectedFunction] !== "function") {
3515
+ throw new Error(`Libherb at "${libherbpath}" has "${expectedFunction}" but it's not a function.`);
3516
+ }
3517
+ }
3518
+ return true;
3519
+ }
3520
+ function ensureLibHerbBackend(object, libherbpath = "unknown") {
3521
+ isLibHerbBackend(object, libherbpath);
3522
+ return object;
3523
+ }
3524
+
3525
+ /**
3526
+ * Converts a Diagnostic to Monaco/VSCode-compatible MonacoDiagnostic format
3527
+ */
3528
+ function toMonacoDiagnostic(diagnostic) {
3529
+ const { message, location } = diagnostic;
3530
+ const severity = diagnostic.severity === "hint" ? "info" : diagnostic.severity;
3531
+ return {
3532
+ line: location.start.line,
3533
+ column: location.start.column,
3534
+ endLine: location.end.line,
3535
+ endColumn: location.end.column,
3536
+ message,
3537
+ severity
3538
+ };
3539
+ }
3540
+
3541
+ var name = "@herb-tools/core";
3542
+ var version = "0.6.0";
3543
+ var packageJSON = {
3544
+ name: name,
3545
+ version: version};
3546
+
3547
+ class TokenList {
3548
+ list;
3549
+ static from(list) {
3550
+ return new TokenList(list.map((token) => Token.from(token)));
3551
+ }
3552
+ constructor(list) {
3553
+ this.list = list;
3554
+ }
3555
+ get length() {
3556
+ return this.list.length;
3557
+ }
3558
+ get tokens() {
3559
+ return this.list;
3560
+ }
3561
+ [Symbol.iterator]() {
3562
+ return this.list[Symbol.iterator]();
3563
+ }
3564
+ at(index) {
3565
+ return this.list.at(index);
3566
+ }
3567
+ forEach(callback) {
3568
+ this.list.forEach(callback);
3569
+ }
3570
+ map(callback) {
3571
+ return this.list.map(callback);
3572
+ }
3573
+ filter(predicate) {
3574
+ return this.list.filter(predicate);
3575
+ }
3576
+ __getobj__() {
3577
+ return this.list;
3578
+ }
3579
+ inspect() {
3580
+ return this.list.map((token) => token.inspect()).join("\n") + "\n";
3581
+ }
3582
+ toString() {
3583
+ return this.inspect();
3584
+ }
3585
+ }
3586
+
3587
+ /**
3588
+ * Represents the result of a lexical analysis, extending the base `Result` class.
3589
+ * It contains the token list, source code, warnings, and errors.
3590
+ */
3591
+ class LexResult extends Result {
3592
+ /** The list of tokens generated from the source code. */
3593
+ value;
3594
+ /**
3595
+ * Creates a `LexResult` instance from a serialized result.
3596
+ * @param result - The serialized lexical result containing tokens, source, warnings, and errors.
3597
+ * @returns A new `LexResult` instance.
3598
+ */
3599
+ static from(result) {
3600
+ return new LexResult(TokenList.from(result.tokens || []), result.source, result.warnings.map((warning) => HerbWarning.from(warning)), result.errors.map((error) => HerbError.from(error)));
3601
+ }
3602
+ /**
3603
+ * Constructs a new `LexResult`.
3604
+ * @param value - The list of tokens.
3605
+ * @param source - The source code that was lexed.
3606
+ * @param warnings - An array of warnings encountered during lexing.
3607
+ * @param errors - An array of errors encountered during lexing.
3608
+ */
3609
+ constructor(value, source, warnings = [], errors = []) {
3610
+ super(source, warnings, errors);
3611
+ this.value = value;
3612
+ }
3613
+ /**
3614
+ * Determines if the lexing was successful.
3615
+ * @returns `true` if there are no errors, otherwise `false`.
3616
+ */
3617
+ get successful() {
3618
+ return this.errors.length === 0;
3619
+ }
3620
+ /**
3621
+ * Determines if the lexing failed.
3622
+ * @returns `true` if there are errors, otherwise `false`.
3623
+ */
3624
+ get failed() {
3625
+ return this.errors.length > 0;
3626
+ }
3627
+ /**
3628
+ * Converts the `LexResult` to a JSON representation.
3629
+ * @returns An object containing the token list, source, warnings, and errors.
3630
+ */
3631
+ toJSON() {
3632
+ return {
3633
+ value: this.value,
3634
+ source: this.source,
3635
+ warnings: this.warnings,
3636
+ errors: this.errors,
3637
+ };
3638
+ }
3639
+ }
3640
+
3641
+ const DEFAULT_PARSER_OPTIONS = {
3642
+ track_whitespace: false,
3643
+ };
3644
+
3645
+ /**
3646
+ * The main Herb parser interface, providing methods to lex and parse input.
3647
+ */
3648
+ class HerbBackend {
3649
+ /** The backend instance handling lexing and parsing. */
3650
+ backend = undefined;
3651
+ backendPromise;
3652
+ /**
3653
+ * Creates a new Herb instance.
3654
+ * @param backendPromise - A promise resolving to a `LibHerbBackend` implementation for lexing and parsing.
3655
+ * @throws Error if no valid backend is provided.
3656
+ */
3657
+ constructor(backendPromise) {
3658
+ if (!backendPromise) {
3659
+ throw new Error("No LibHerb backend provided");
3660
+ }
3661
+ this.backendPromise = backendPromise;
3662
+ }
3663
+ /**
3664
+ * Loads the backend by resolving the backend promise.
3665
+ * @returns A promise containing the resolved `HerbBackend` instance after loading it.
3666
+ */
3667
+ async load() {
3668
+ const backend = await this.backendPromise();
3669
+ this.backend = backend;
3670
+ return this;
3671
+ }
3672
+ /**
3673
+ * Lexes the given source string into a `LexResult`.
3674
+ * @param source - The source code to lex.
3675
+ * @returns A `LexResult` instance.
3676
+ * @throws Error if the backend is not loaded.
3677
+ */
3678
+ lex(source) {
3679
+ this.ensureBackend();
3680
+ return LexResult.from(this.backend.lex(ensureString(source)));
3681
+ }
3682
+ /**
3683
+ * Lexes a file.
3684
+ * @param path - The file path to lex.
3685
+ * @returns A `LexResult` instance.
3686
+ * @throws Error if the backend is not loaded.
3687
+ */
3688
+ lexFile(path) {
3689
+ this.ensureBackend();
3690
+ return LexResult.from(this.backend.lexFile(ensureString(path)));
3691
+ }
3692
+ /**
3693
+ * Parses the given source string into a `ParseResult`.
3694
+ * @param source - The source code to parse.
3695
+ * @param options - Optional parsing options.
3696
+ * @returns A `ParseResult` instance.
3697
+ * @throws Error if the backend is not loaded.
3698
+ */
3699
+ parse(source, options) {
3700
+ this.ensureBackend();
3701
+ const mergedOptions = { ...DEFAULT_PARSER_OPTIONS, ...options };
3702
+ return ParseResult.from(this.backend.parse(ensureString(source), mergedOptions));
3703
+ }
3704
+ /**
3705
+ * Parses a file.
3706
+ * @param path - The file path to parse.
3707
+ * @returns A `ParseResult` instance.
3708
+ * @throws Error if the backend is not loaded.
3709
+ */
3710
+ parseFile(path) {
3711
+ this.ensureBackend();
3712
+ return ParseResult.from(this.backend.parseFile(ensureString(path)));
3713
+ }
3714
+ /**
3715
+ * Extracts embedded Ruby code from the given source.
3716
+ * @param source - The source code to extract Ruby from.
3717
+ * @returns The extracted Ruby code as a string.
3718
+ * @throws Error if the backend is not loaded.
3719
+ */
3720
+ extractRuby(source) {
3721
+ this.ensureBackend();
3722
+ return this.backend.extractRuby(ensureString(source));
3723
+ }
3724
+ /**
3725
+ * Extracts HTML from the given source.
3726
+ * @param source - The source code to extract HTML from.
3727
+ * @returns The extracted HTML as a string.
3728
+ * @throws Error if the backend is not loaded.
3729
+ */
3730
+ extractHTML(source) {
3731
+ this.ensureBackend();
3732
+ return this.backend.extractHTML(ensureString(source));
3733
+ }
3734
+ /**
3735
+ * Gets the Herb version information, including the core and backend versions.
3736
+ * @returns A version string containing backend, core, and libherb versions.
3737
+ * @throws Error if the backend is not loaded.
3738
+ */
3739
+ get version() {
3740
+ this.ensureBackend();
3741
+ const backend = this.backendVersion();
3742
+ const core = `${packageJSON.name}@${packageJSON.version}`;
3743
+ const libherb = this.backend.version();
3744
+ return `${backend}, ${core}, ${libherb}`;
3745
+ }
3746
+ /**
3747
+ * Ensures that the backend is loaded.
3748
+ * @throws Error if the backend is not loaded.
3749
+ */
3750
+ ensureBackend() {
3751
+ if (!this.isLoaded) {
3752
+ throw new Error("Herb backend is not loaded. Call `await Herb.load()` first.");
3753
+ }
3754
+ }
3755
+ /**
3756
+ * Checks if the backend is loaded.
3757
+ * @returns True if the backend is loaded, false otherwise.
3758
+ */
3759
+ get isLoaded() {
2972
3760
  return this.backend !== undefined;
2973
3761
  }
2974
3762
  }
2975
3763
 
2976
3764
  // NOTE: This file is generated by the templates/template.rb script and should not
2977
- // be modified manually. See /Users/marcoroth/Development/herb-release-7/templates/javascript/packages/core/src/visitor.ts.erb
3765
+ // be modified manually. See /Users/marcoroth/Development/herb-release-0.6.0/templates/javascript/packages/core/src/visitor.ts.erb
2978
3766
  class Visitor {
2979
3767
  visit(node) {
2980
3768
  if (!node)
@@ -2999,9 +3787,6 @@ class Visitor {
2999
3787
  visitHTMLCloseTagNode(node) {
3000
3788
  this.visitChildNodes(node);
3001
3789
  }
3002
- visitHTMLSelfCloseTagNode(node) {
3003
- this.visitChildNodes(node);
3004
- }
3005
3790
  visitHTMLElementNode(node) {
3006
3791
  this.visitChildNodes(node);
3007
3792
  }
@@ -3023,6 +3808,12 @@ class Visitor {
3023
3808
  visitHTMLDoctypeNode(node) {
3024
3809
  this.visitChildNodes(node);
3025
3810
  }
3811
+ visitXMLDeclarationNode(node) {
3812
+ this.visitChildNodes(node);
3813
+ }
3814
+ visitCDATANode(node) {
3815
+ this.visitChildNodes(node);
3816
+ }
3026
3817
  visitWhitespaceNode(node) {
3027
3818
  this.visitChildNodes(node);
3028
3819
  }
@@ -3079,5 +3870,5 @@ class Visitor {
3079
3870
  }
3080
3871
  }
3081
3872
 
3082
- export { DocumentNode, ERBBeginNode, ERBBlockNode, ERBCaseMatchNode, ERBCaseNode, ERBContentNode, ERBElseNode, ERBEndNode, ERBEnsureNode, ERBForNode, ERBIfNode, ERBInNode, ERBNodeClasses, 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, isERBNode, isLibHerbBackend, toMonacoDiagnostic };
3873
+ export { AST_TYPE_GUARDS, CDATANode, DEFAULT_PARSER_OPTIONS, DocumentNode, ERBBeginNode, ERBBlockNode, ERBCaseMatchNode, ERBCaseNode, ERBContentNode, ERBElseNode, ERBEndNode, ERBEnsureNode, ERBForNode, ERBIfNode, ERBInNode, ERBNodeClasses, ERBRescueNode, ERBUnlessNode, ERBUntilNode, ERBWhenNode, ERBWhileNode, ERBYieldNode, HTMLAttributeNameNode, HTMLAttributeNode, HTMLAttributeValueNode, HTMLCloseTagNode, HTMLCommentNode, HTMLDoctypeNode, HTMLElementNode, HTMLOpenTagNode, HTMLTextNode, HerbBackend, HerbError, HerbWarning, LexResult, LiteralNode, Location, MissingClosingTagError, MissingOpeningTagError, NODE_TYPE_GUARDS, Node, ParseResult, Position, QuotesMismatchError, Range, Result, RubyParseError, TagNamesMismatchError, Token, TokenList, UnclosedElementError, UnexpectedError, UnexpectedTokenError, Visitor, VoidElementClosingTagError, WhitespaceNode, XMLDeclarationNode, _TYPECHECK, areAllOfType, convertToUTF8, ensureLibHerbBackend, ensureString, filterCDATANodes, filterDocumentNodes, filterERBBeginNodes, filterERBBlockNodes, filterERBCaseMatchNodes, filterERBCaseNodes, filterERBContentNodes, filterERBElseNodes, filterERBEndNodes, filterERBEnsureNodes, filterERBForNodes, filterERBIfNodes, filterERBInNodes, filterERBRescueNodes, filterERBUnlessNodes, filterERBUntilNodes, filterERBWhenNodes, filterERBWhileNodes, filterERBYieldNodes, filterHTMLAttributeNameNodes, filterHTMLAttributeNodes, filterHTMLAttributeValueNodes, filterHTMLCloseTagNodes, filterHTMLCommentNodes, filterHTMLDoctypeNodes, filterHTMLElementNodes, filterHTMLOpenTagNodes, filterHTMLTextNodes, filterLiteralNodes, filterNodes, filterWhitespaceNodes, filterXMLDeclarationNodes, fromSerializedError, fromSerializedNode, getCombinedAttributeName, getCombinedStringFromNodes, getStaticAttributeName, getStaticContentFromNodes, getStaticStringFromNodes, getTagName, getValidatableStaticContent, hasChildren, hasDynamicAttributeName, hasERBContent, hasERBOutput, hasStaticAttributeName, hasStaticContent, isAnyOf, isCDATANode, isCommentNode, isDocumentNode, isERBBeginNode, isERBBlockNode, isERBCaseMatchNode, isERBCaseNode, isERBContentNode, isERBControlFlowNode, isERBElseNode, isERBEndNode, isERBEnsureNode, isERBForNode, isERBIfNode, isERBInNode, isERBNode, isERBOutputNode, isERBRescueNode, isERBUnlessNode, isERBUntilNode, isERBWhenNode, isERBWhileNode, isERBYieldNode, isEffectivelyStatic, isHTMLAttributeNameNode, isHTMLAttributeNode, isHTMLAttributeValueNode, isHTMLCloseTagNode, isHTMLCommentNode, isHTMLDoctypeNode, isHTMLElementNode, isHTMLNode, isHTMLOpenTagNode, isHTMLTextNode, isLibHerbBackend, isLiteralNode, isNode, isNoneOf, isParseResult, isToken, isWhitespaceNode, isXMLDeclarationNode, toMonacoDiagnostic };
3083
3874
  //# sourceMappingURL=herb-core.browser.js.map