@herb-tools/core 0.5.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/herb-core.browser.js +1344 -368
- package/dist/herb-core.browser.js.map +1 -1
- package/dist/herb-core.cjs +1443 -368
- package/dist/herb-core.cjs.map +1 -1
- package/dist/herb-core.esm.js +1344 -368
- package/dist/herb-core.esm.js.map +1 -1
- package/dist/herb-core.umd.js +1443 -368
- package/dist/herb-core.umd.js.map +1 -1
- package/dist/types/ast-utils.d.ts +124 -0
- package/dist/types/backend.d.ts +2 -1
- package/dist/types/herb-backend.d.ts +3 -1
- package/dist/types/index.d.ts +3 -0
- package/dist/types/node-type-guards.d.ts +434 -0
- package/dist/types/nodes.d.ts +187 -97
- package/dist/types/parser-options.d.ts +4 -0
- package/dist/types/visitor.d.ts +3 -2
- package/package.json +1 -1
- package/src/ast-utils.ts +291 -0
- package/src/backend.ts +2 -1
- package/src/errors.ts +1 -1
- package/src/herb-backend.ts +7 -2
- package/src/index.ts +3 -0
- package/src/node-type-guards.ts +878 -0
- package/src/nodes.ts +436 -251
- package/src/parser-options.ts +7 -0
- package/src/visitor.ts +11 -6
package/dist/herb-core.esm.js
CHANGED
|
@@ -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-0.
|
|
132
|
+
// be modified manually. See /Users/marcoroth/Development/herb-release-0.6.1/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.5.0";
|
|
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-0.
|
|
589
|
+
// be modified manually. See /Users/marcoroth/Development/herb-release-0.6.1/templates/javascript/packages/core/src/nodes.ts.erb
|
|
777
590
|
class Node {
|
|
778
591
|
type;
|
|
779
592
|
location;
|
|
@@ -781,6 +594,9 @@ class Node {
|
|
|
781
594
|
static from(node) {
|
|
782
595
|
return fromSerializedNode(node);
|
|
783
596
|
}
|
|
597
|
+
static get type() {
|
|
598
|
+
throw new Error("AST_NODE");
|
|
599
|
+
}
|
|
784
600
|
constructor(type, location, errors) {
|
|
785
601
|
this.type = type;
|
|
786
602
|
this.location = location;
|
|
@@ -796,6 +612,12 @@ class Node {
|
|
|
796
612
|
inspect() {
|
|
797
613
|
return this.treeInspect(0);
|
|
798
614
|
}
|
|
615
|
+
is(nodeClass) {
|
|
616
|
+
return this.type === nodeClass.type;
|
|
617
|
+
}
|
|
618
|
+
isOfType(type) {
|
|
619
|
+
return this.type === type;
|
|
620
|
+
}
|
|
799
621
|
get isSingleLine() {
|
|
800
622
|
return this.location.start.line === this.location.end.line;
|
|
801
623
|
}
|
|
@@ -837,6 +659,9 @@ class Node {
|
|
|
837
659
|
}
|
|
838
660
|
class DocumentNode extends Node {
|
|
839
661
|
children;
|
|
662
|
+
static get type() {
|
|
663
|
+
return "AST_DOCUMENT_NODE";
|
|
664
|
+
}
|
|
840
665
|
static from(data) {
|
|
841
666
|
return new DocumentNode({
|
|
842
667
|
type: data.type,
|
|
@@ -878,12 +703,14 @@ class DocumentNode extends Node {
|
|
|
878
703
|
output += `@ DocumentNode ${this.location.treeInspectWithLabel()}\n`;
|
|
879
704
|
output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
|
|
880
705
|
output += `└── children: ${this.inspectArray(this.children, " ")}`;
|
|
881
|
-
// output += "\n";
|
|
882
706
|
return output;
|
|
883
707
|
}
|
|
884
708
|
}
|
|
885
709
|
class LiteralNode extends Node {
|
|
886
710
|
content;
|
|
711
|
+
static get type() {
|
|
712
|
+
return "AST_LITERAL_NODE";
|
|
713
|
+
}
|
|
887
714
|
static from(data) {
|
|
888
715
|
return new LiteralNode({
|
|
889
716
|
type: data.type,
|
|
@@ -922,7 +749,6 @@ class LiteralNode extends Node {
|
|
|
922
749
|
output += `@ LiteralNode ${this.location.treeInspectWithLabel()}\n`;
|
|
923
750
|
output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
|
|
924
751
|
output += `└── content: ${this.content ? JSON.stringify(this.content) : "∅"}\n`;
|
|
925
|
-
// output += "\n";
|
|
926
752
|
return output;
|
|
927
753
|
}
|
|
928
754
|
}
|
|
@@ -932,6 +758,9 @@ class HTMLOpenTagNode extends Node {
|
|
|
932
758
|
tag_closing;
|
|
933
759
|
children;
|
|
934
760
|
is_void;
|
|
761
|
+
static get type() {
|
|
762
|
+
return "AST_HTML_OPEN_TAG_NODE";
|
|
763
|
+
}
|
|
935
764
|
static from(data) {
|
|
936
765
|
return new HTMLOpenTagNode({
|
|
937
766
|
type: data.type,
|
|
@@ -989,14 +818,17 @@ class HTMLOpenTagNode extends Node {
|
|
|
989
818
|
output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
|
|
990
819
|
output += `├── children: ${this.inspectArray(this.children, "│ ")}`;
|
|
991
820
|
output += `└── is_void: ${typeof this.is_void === 'boolean' ? String(this.is_void) : "∅"}\n`;
|
|
992
|
-
// output += "\n";
|
|
993
821
|
return output;
|
|
994
822
|
}
|
|
995
823
|
}
|
|
996
824
|
class HTMLCloseTagNode extends Node {
|
|
997
825
|
tag_opening;
|
|
998
826
|
tag_name;
|
|
827
|
+
children;
|
|
999
828
|
tag_closing;
|
|
829
|
+
static get type() {
|
|
830
|
+
return "AST_HTML_CLOSE_TAG_NODE";
|
|
831
|
+
}
|
|
1000
832
|
static from(data) {
|
|
1001
833
|
return new HTMLCloseTagNode({
|
|
1002
834
|
type: data.type,
|
|
@@ -1004,6 +836,7 @@ class HTMLCloseTagNode extends Node {
|
|
|
1004
836
|
errors: (data.errors || []).map(error => HerbError.from(error)),
|
|
1005
837
|
tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
|
|
1006
838
|
tag_name: data.tag_name ? Token.from(data.tag_name) : null,
|
|
839
|
+
children: (data.children || []).map(node => fromSerializedNode(node)),
|
|
1007
840
|
tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
|
|
1008
841
|
});
|
|
1009
842
|
}
|
|
@@ -1011,13 +844,16 @@ class HTMLCloseTagNode extends Node {
|
|
|
1011
844
|
super(props.type, props.location, props.errors);
|
|
1012
845
|
this.tag_opening = props.tag_opening;
|
|
1013
846
|
this.tag_name = props.tag_name;
|
|
847
|
+
this.children = props.children;
|
|
1014
848
|
this.tag_closing = props.tag_closing;
|
|
1015
849
|
}
|
|
1016
850
|
accept(visitor) {
|
|
1017
851
|
visitor.visitHTMLCloseTagNode(this);
|
|
1018
852
|
}
|
|
1019
853
|
childNodes() {
|
|
1020
|
-
return [
|
|
854
|
+
return [
|
|
855
|
+
...this.children,
|
|
856
|
+
];
|
|
1021
857
|
}
|
|
1022
858
|
compactChildNodes() {
|
|
1023
859
|
return this.childNodes().filter(node => node !== null && node !== undefined);
|
|
@@ -1025,6 +861,7 @@ class HTMLCloseTagNode extends Node {
|
|
|
1025
861
|
recursiveErrors() {
|
|
1026
862
|
return [
|
|
1027
863
|
...this.errors,
|
|
864
|
+
...this.children.map(node => node.recursiveErrors()),
|
|
1028
865
|
].flat();
|
|
1029
866
|
}
|
|
1030
867
|
toJSON() {
|
|
@@ -1033,6 +870,7 @@ class HTMLCloseTagNode extends Node {
|
|
|
1033
870
|
type: "AST_HTML_CLOSE_TAG_NODE",
|
|
1034
871
|
tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
|
|
1035
872
|
tag_name: this.tag_name ? this.tag_name.toJSON() : null,
|
|
873
|
+
children: this.children.map(node => node.toJSON()),
|
|
1036
874
|
tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
|
|
1037
875
|
};
|
|
1038
876
|
}
|
|
@@ -1042,43 +880,48 @@ class HTMLCloseTagNode extends Node {
|
|
|
1042
880
|
output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
|
|
1043
881
|
output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
|
|
1044
882
|
output += `├── tag_name: ${this.tag_name ? this.tag_name.treeInspect() : "∅"}\n`;
|
|
883
|
+
output += `├── children: ${this.inspectArray(this.children, "│ ")}`;
|
|
1045
884
|
output += `└── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
|
|
1046
|
-
// output += "\n";
|
|
1047
885
|
return output;
|
|
1048
886
|
}
|
|
1049
887
|
}
|
|
1050
|
-
class
|
|
1051
|
-
|
|
888
|
+
class HTMLElementNode extends Node {
|
|
889
|
+
open_tag;
|
|
1052
890
|
tag_name;
|
|
1053
|
-
|
|
1054
|
-
|
|
891
|
+
body;
|
|
892
|
+
close_tag;
|
|
1055
893
|
is_void;
|
|
894
|
+
static get type() {
|
|
895
|
+
return "AST_HTML_ELEMENT_NODE";
|
|
896
|
+
}
|
|
1056
897
|
static from(data) {
|
|
1057
|
-
return new
|
|
898
|
+
return new HTMLElementNode({
|
|
1058
899
|
type: data.type,
|
|
1059
900
|
location: Location.from(data.location),
|
|
1060
901
|
errors: (data.errors || []).map(error => HerbError.from(error)),
|
|
1061
|
-
|
|
902
|
+
open_tag: data.open_tag ? fromSerializedNode((data.open_tag)) : null,
|
|
1062
903
|
tag_name: data.tag_name ? Token.from(data.tag_name) : null,
|
|
1063
|
-
|
|
1064
|
-
|
|
904
|
+
body: (data.body || []).map(node => fromSerializedNode(node)),
|
|
905
|
+
close_tag: data.close_tag ? fromSerializedNode((data.close_tag)) : null,
|
|
1065
906
|
is_void: data.is_void,
|
|
1066
907
|
});
|
|
1067
908
|
}
|
|
1068
909
|
constructor(props) {
|
|
1069
910
|
super(props.type, props.location, props.errors);
|
|
1070
|
-
this.
|
|
911
|
+
this.open_tag = props.open_tag;
|
|
1071
912
|
this.tag_name = props.tag_name;
|
|
1072
|
-
this.
|
|
1073
|
-
this.
|
|
913
|
+
this.body = props.body;
|
|
914
|
+
this.close_tag = props.close_tag;
|
|
1074
915
|
this.is_void = props.is_void;
|
|
1075
916
|
}
|
|
1076
917
|
accept(visitor) {
|
|
1077
|
-
visitor.
|
|
918
|
+
visitor.visitHTMLElementNode(this);
|
|
1078
919
|
}
|
|
1079
920
|
childNodes() {
|
|
1080
921
|
return [
|
|
1081
|
-
|
|
922
|
+
this.open_tag,
|
|
923
|
+
...this.body,
|
|
924
|
+
this.close_tag,
|
|
1082
925
|
];
|
|
1083
926
|
}
|
|
1084
927
|
compactChildNodes() {
|
|
@@ -1087,111 +930,44 @@ class HTMLSelfCloseTagNode extends Node {
|
|
|
1087
930
|
recursiveErrors() {
|
|
1088
931
|
return [
|
|
1089
932
|
...this.errors,
|
|
1090
|
-
|
|
933
|
+
this.open_tag ? this.open_tag.recursiveErrors() : [],
|
|
934
|
+
...this.body.map(node => node.recursiveErrors()),
|
|
935
|
+
this.close_tag ? this.close_tag.recursiveErrors() : [],
|
|
1091
936
|
].flat();
|
|
1092
937
|
}
|
|
1093
938
|
toJSON() {
|
|
1094
939
|
return {
|
|
1095
940
|
...super.toJSON(),
|
|
1096
|
-
type: "
|
|
1097
|
-
|
|
941
|
+
type: "AST_HTML_ELEMENT_NODE",
|
|
942
|
+
open_tag: this.open_tag ? this.open_tag.toJSON() : null,
|
|
1098
943
|
tag_name: this.tag_name ? this.tag_name.toJSON() : null,
|
|
1099
|
-
|
|
1100
|
-
|
|
944
|
+
body: this.body.map(node => node.toJSON()),
|
|
945
|
+
close_tag: this.close_tag ? this.close_tag.toJSON() : null,
|
|
1101
946
|
is_void: this.is_void,
|
|
1102
947
|
};
|
|
1103
948
|
}
|
|
1104
949
|
treeInspect() {
|
|
1105
950
|
let output = "";
|
|
1106
|
-
output += `@
|
|
951
|
+
output += `@ HTMLElementNode ${this.location.treeInspectWithLabel()}\n`;
|
|
1107
952
|
output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
|
|
1108
|
-
output += `├──
|
|
953
|
+
output += `├── open_tag: ${this.inspectNode(this.open_tag, "│ ")}`;
|
|
1109
954
|
output += `├── tag_name: ${this.tag_name ? this.tag_name.treeInspect() : "∅"}\n`;
|
|
1110
|
-
output += `├──
|
|
1111
|
-
output += `├──
|
|
955
|
+
output += `├── body: ${this.inspectArray(this.body, "│ ")}`;
|
|
956
|
+
output += `├── close_tag: ${this.inspectNode(this.close_tag, "│ ")}`;
|
|
1112
957
|
output += `└── is_void: ${typeof this.is_void === 'boolean' ? String(this.is_void) : "∅"}\n`;
|
|
1113
|
-
// output += "\n";
|
|
1114
958
|
return output;
|
|
1115
959
|
}
|
|
1116
960
|
}
|
|
1117
|
-
class
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
961
|
+
class HTMLAttributeValueNode extends Node {
|
|
962
|
+
open_quote;
|
|
963
|
+
children;
|
|
964
|
+
close_quote;
|
|
965
|
+
quoted;
|
|
966
|
+
static get type() {
|
|
967
|
+
return "AST_HTML_ATTRIBUTE_VALUE_NODE";
|
|
968
|
+
}
|
|
1123
969
|
static from(data) {
|
|
1124
|
-
return new
|
|
1125
|
-
type: data.type,
|
|
1126
|
-
location: Location.from(data.location),
|
|
1127
|
-
errors: (data.errors || []).map(error => HerbError.from(error)),
|
|
1128
|
-
open_tag: data.open_tag ? fromSerializedNode(data.open_tag) : null,
|
|
1129
|
-
tag_name: data.tag_name ? Token.from(data.tag_name) : null,
|
|
1130
|
-
body: (data.body || []).map(node => fromSerializedNode(node)),
|
|
1131
|
-
close_tag: data.close_tag ? fromSerializedNode(data.close_tag) : null,
|
|
1132
|
-
is_void: data.is_void,
|
|
1133
|
-
});
|
|
1134
|
-
}
|
|
1135
|
-
constructor(props) {
|
|
1136
|
-
super(props.type, props.location, props.errors);
|
|
1137
|
-
this.open_tag = props.open_tag;
|
|
1138
|
-
this.tag_name = props.tag_name;
|
|
1139
|
-
this.body = props.body;
|
|
1140
|
-
this.close_tag = props.close_tag;
|
|
1141
|
-
this.is_void = props.is_void;
|
|
1142
|
-
}
|
|
1143
|
-
accept(visitor) {
|
|
1144
|
-
visitor.visitHTMLElementNode(this);
|
|
1145
|
-
}
|
|
1146
|
-
childNodes() {
|
|
1147
|
-
return [
|
|
1148
|
-
this.open_tag,
|
|
1149
|
-
...this.body,
|
|
1150
|
-
this.close_tag,
|
|
1151
|
-
];
|
|
1152
|
-
}
|
|
1153
|
-
compactChildNodes() {
|
|
1154
|
-
return this.childNodes().filter(node => node !== null && node !== undefined);
|
|
1155
|
-
}
|
|
1156
|
-
recursiveErrors() {
|
|
1157
|
-
return [
|
|
1158
|
-
...this.errors,
|
|
1159
|
-
this.open_tag ? this.open_tag.recursiveErrors() : [],
|
|
1160
|
-
...this.body.map(node => node.recursiveErrors()),
|
|
1161
|
-
this.close_tag ? this.close_tag.recursiveErrors() : [],
|
|
1162
|
-
].flat();
|
|
1163
|
-
}
|
|
1164
|
-
toJSON() {
|
|
1165
|
-
return {
|
|
1166
|
-
...super.toJSON(),
|
|
1167
|
-
type: "AST_HTML_ELEMENT_NODE",
|
|
1168
|
-
open_tag: this.open_tag ? this.open_tag.toJSON() : null,
|
|
1169
|
-
tag_name: this.tag_name ? this.tag_name.toJSON() : null,
|
|
1170
|
-
body: this.body.map(node => node.toJSON()),
|
|
1171
|
-
close_tag: this.close_tag ? this.close_tag.toJSON() : null,
|
|
1172
|
-
is_void: this.is_void,
|
|
1173
|
-
};
|
|
1174
|
-
}
|
|
1175
|
-
treeInspect() {
|
|
1176
|
-
let output = "";
|
|
1177
|
-
output += `@ HTMLElementNode ${this.location.treeInspectWithLabel()}\n`;
|
|
1178
|
-
output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
|
|
1179
|
-
output += `├── open_tag: ${this.inspectNode(this.open_tag, "│ ")}`;
|
|
1180
|
-
output += `├── tag_name: ${this.tag_name ? this.tag_name.treeInspect() : "∅"}\n`;
|
|
1181
|
-
output += `├── body: ${this.inspectArray(this.body, "│ ")}`;
|
|
1182
|
-
output += `├── close_tag: ${this.inspectNode(this.close_tag, "│ ")}`;
|
|
1183
|
-
output += `└── is_void: ${typeof this.is_void === 'boolean' ? String(this.is_void) : "∅"}\n`;
|
|
1184
|
-
// output += "\n";
|
|
1185
|
-
return output;
|
|
1186
|
-
}
|
|
1187
|
-
}
|
|
1188
|
-
class HTMLAttributeValueNode extends Node {
|
|
1189
|
-
open_quote;
|
|
1190
|
-
children;
|
|
1191
|
-
close_quote;
|
|
1192
|
-
quoted;
|
|
1193
|
-
static from(data) {
|
|
1194
|
-
return new HTMLAttributeValueNode({
|
|
970
|
+
return new HTMLAttributeValueNode({
|
|
1195
971
|
type: data.type,
|
|
1196
972
|
location: Location.from(data.location),
|
|
1197
973
|
errors: (data.errors || []).map(error => HerbError.from(error)),
|
|
@@ -1243,29 +1019,33 @@ class HTMLAttributeValueNode extends Node {
|
|
|
1243
1019
|
output += `├── children: ${this.inspectArray(this.children, "│ ")}`;
|
|
1244
1020
|
output += `├── close_quote: ${this.close_quote ? this.close_quote.treeInspect() : "∅"}\n`;
|
|
1245
1021
|
output += `└── quoted: ${typeof this.quoted === 'boolean' ? String(this.quoted) : "∅"}\n`;
|
|
1246
|
-
// output += "\n";
|
|
1247
1022
|
return output;
|
|
1248
1023
|
}
|
|
1249
1024
|
}
|
|
1250
1025
|
class HTMLAttributeNameNode extends Node {
|
|
1251
|
-
|
|
1026
|
+
children;
|
|
1027
|
+
static get type() {
|
|
1028
|
+
return "AST_HTML_ATTRIBUTE_NAME_NODE";
|
|
1029
|
+
}
|
|
1252
1030
|
static from(data) {
|
|
1253
1031
|
return new HTMLAttributeNameNode({
|
|
1254
1032
|
type: data.type,
|
|
1255
1033
|
location: Location.from(data.location),
|
|
1256
1034
|
errors: (data.errors || []).map(error => HerbError.from(error)),
|
|
1257
|
-
|
|
1035
|
+
children: (data.children || []).map(node => fromSerializedNode(node)),
|
|
1258
1036
|
});
|
|
1259
1037
|
}
|
|
1260
1038
|
constructor(props) {
|
|
1261
1039
|
super(props.type, props.location, props.errors);
|
|
1262
|
-
this.
|
|
1040
|
+
this.children = props.children;
|
|
1263
1041
|
}
|
|
1264
1042
|
accept(visitor) {
|
|
1265
1043
|
visitor.visitHTMLAttributeNameNode(this);
|
|
1266
1044
|
}
|
|
1267
1045
|
childNodes() {
|
|
1268
|
-
return [
|
|
1046
|
+
return [
|
|
1047
|
+
...this.children,
|
|
1048
|
+
];
|
|
1269
1049
|
}
|
|
1270
1050
|
compactChildNodes() {
|
|
1271
1051
|
return this.childNodes().filter(node => node !== null && node !== undefined);
|
|
@@ -1273,21 +1053,21 @@ class HTMLAttributeNameNode extends Node {
|
|
|
1273
1053
|
recursiveErrors() {
|
|
1274
1054
|
return [
|
|
1275
1055
|
...this.errors,
|
|
1056
|
+
...this.children.map(node => node.recursiveErrors()),
|
|
1276
1057
|
].flat();
|
|
1277
1058
|
}
|
|
1278
1059
|
toJSON() {
|
|
1279
1060
|
return {
|
|
1280
1061
|
...super.toJSON(),
|
|
1281
1062
|
type: "AST_HTML_ATTRIBUTE_NAME_NODE",
|
|
1282
|
-
|
|
1063
|
+
children: this.children.map(node => node.toJSON()),
|
|
1283
1064
|
};
|
|
1284
1065
|
}
|
|
1285
1066
|
treeInspect() {
|
|
1286
1067
|
let output = "";
|
|
1287
1068
|
output += `@ HTMLAttributeNameNode ${this.location.treeInspectWithLabel()}\n`;
|
|
1288
1069
|
output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
|
|
1289
|
-
output += `└──
|
|
1290
|
-
// output += "\n";
|
|
1070
|
+
output += `└── children: ${this.inspectArray(this.children, " ")}`;
|
|
1291
1071
|
return output;
|
|
1292
1072
|
}
|
|
1293
1073
|
}
|
|
@@ -1295,14 +1075,17 @@ class HTMLAttributeNode extends Node {
|
|
|
1295
1075
|
name;
|
|
1296
1076
|
equals;
|
|
1297
1077
|
value;
|
|
1078
|
+
static get type() {
|
|
1079
|
+
return "AST_HTML_ATTRIBUTE_NODE";
|
|
1080
|
+
}
|
|
1298
1081
|
static from(data) {
|
|
1299
1082
|
return new HTMLAttributeNode({
|
|
1300
1083
|
type: data.type,
|
|
1301
1084
|
location: Location.from(data.location),
|
|
1302
1085
|
errors: (data.errors || []).map(error => HerbError.from(error)),
|
|
1303
|
-
name: data.name ? fromSerializedNode(data.name) : null,
|
|
1086
|
+
name: data.name ? fromSerializedNode((data.name)) : null,
|
|
1304
1087
|
equals: data.equals ? Token.from(data.equals) : null,
|
|
1305
|
-
value: data.value ? fromSerializedNode(data.value) : null,
|
|
1088
|
+
value: data.value ? fromSerializedNode((data.value)) : null,
|
|
1306
1089
|
});
|
|
1307
1090
|
}
|
|
1308
1091
|
constructor(props) {
|
|
@@ -1346,12 +1129,14 @@ class HTMLAttributeNode extends Node {
|
|
|
1346
1129
|
output += `├── name: ${this.inspectNode(this.name, "│ ")}`;
|
|
1347
1130
|
output += `├── equals: ${this.equals ? this.equals.treeInspect() : "∅"}\n`;
|
|
1348
1131
|
output += `└── value: ${this.inspectNode(this.value, " ")}`;
|
|
1349
|
-
// output += "\n";
|
|
1350
1132
|
return output;
|
|
1351
1133
|
}
|
|
1352
1134
|
}
|
|
1353
1135
|
class HTMLTextNode extends Node {
|
|
1354
1136
|
content;
|
|
1137
|
+
static get type() {
|
|
1138
|
+
return "AST_HTML_TEXT_NODE";
|
|
1139
|
+
}
|
|
1355
1140
|
static from(data) {
|
|
1356
1141
|
return new HTMLTextNode({
|
|
1357
1142
|
type: data.type,
|
|
@@ -1390,7 +1175,6 @@ class HTMLTextNode extends Node {
|
|
|
1390
1175
|
output += `@ HTMLTextNode ${this.location.treeInspectWithLabel()}\n`;
|
|
1391
1176
|
output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
|
|
1392
1177
|
output += `└── content: ${this.content ? JSON.stringify(this.content) : "∅"}\n`;
|
|
1393
|
-
// output += "\n";
|
|
1394
1178
|
return output;
|
|
1395
1179
|
}
|
|
1396
1180
|
}
|
|
@@ -1398,6 +1182,9 @@ class HTMLCommentNode extends Node {
|
|
|
1398
1182
|
comment_start;
|
|
1399
1183
|
children;
|
|
1400
1184
|
comment_end;
|
|
1185
|
+
static get type() {
|
|
1186
|
+
return "AST_HTML_COMMENT_NODE";
|
|
1187
|
+
}
|
|
1401
1188
|
static from(data) {
|
|
1402
1189
|
return new HTMLCommentNode({
|
|
1403
1190
|
type: data.type,
|
|
@@ -1447,7 +1234,6 @@ class HTMLCommentNode extends Node {
|
|
|
1447
1234
|
output += `├── comment_start: ${this.comment_start ? this.comment_start.treeInspect() : "∅"}\n`;
|
|
1448
1235
|
output += `├── children: ${this.inspectArray(this.children, "│ ")}`;
|
|
1449
1236
|
output += `└── comment_end: ${this.comment_end ? this.comment_end.treeInspect() : "∅"}\n`;
|
|
1450
|
-
// output += "\n";
|
|
1451
1237
|
return output;
|
|
1452
1238
|
}
|
|
1453
1239
|
}
|
|
@@ -1455,6 +1241,9 @@ class HTMLDoctypeNode extends Node {
|
|
|
1455
1241
|
tag_opening;
|
|
1456
1242
|
children;
|
|
1457
1243
|
tag_closing;
|
|
1244
|
+
static get type() {
|
|
1245
|
+
return "AST_HTML_DOCTYPE_NODE";
|
|
1246
|
+
}
|
|
1458
1247
|
static from(data) {
|
|
1459
1248
|
return new HTMLDoctypeNode({
|
|
1460
1249
|
type: data.type,
|
|
@@ -1504,12 +1293,132 @@ class HTMLDoctypeNode extends Node {
|
|
|
1504
1293
|
output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
|
|
1505
1294
|
output += `├── children: ${this.inspectArray(this.children, "│ ")}`;
|
|
1506
1295
|
output += `└── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
|
|
1507
|
-
|
|
1296
|
+
return output;
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
class XMLDeclarationNode extends Node {
|
|
1300
|
+
tag_opening;
|
|
1301
|
+
children;
|
|
1302
|
+
tag_closing;
|
|
1303
|
+
static get type() {
|
|
1304
|
+
return "AST_XML_DECLARATION_NODE";
|
|
1305
|
+
}
|
|
1306
|
+
static from(data) {
|
|
1307
|
+
return new XMLDeclarationNode({
|
|
1308
|
+
type: data.type,
|
|
1309
|
+
location: Location.from(data.location),
|
|
1310
|
+
errors: (data.errors || []).map(error => HerbError.from(error)),
|
|
1311
|
+
tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
|
|
1312
|
+
children: (data.children || []).map(node => fromSerializedNode(node)),
|
|
1313
|
+
tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
|
|
1314
|
+
});
|
|
1315
|
+
}
|
|
1316
|
+
constructor(props) {
|
|
1317
|
+
super(props.type, props.location, props.errors);
|
|
1318
|
+
this.tag_opening = props.tag_opening;
|
|
1319
|
+
this.children = props.children;
|
|
1320
|
+
this.tag_closing = props.tag_closing;
|
|
1321
|
+
}
|
|
1322
|
+
accept(visitor) {
|
|
1323
|
+
visitor.visitXMLDeclarationNode(this);
|
|
1324
|
+
}
|
|
1325
|
+
childNodes() {
|
|
1326
|
+
return [
|
|
1327
|
+
...this.children,
|
|
1328
|
+
];
|
|
1329
|
+
}
|
|
1330
|
+
compactChildNodes() {
|
|
1331
|
+
return this.childNodes().filter(node => node !== null && node !== undefined);
|
|
1332
|
+
}
|
|
1333
|
+
recursiveErrors() {
|
|
1334
|
+
return [
|
|
1335
|
+
...this.errors,
|
|
1336
|
+
...this.children.map(node => node.recursiveErrors()),
|
|
1337
|
+
].flat();
|
|
1338
|
+
}
|
|
1339
|
+
toJSON() {
|
|
1340
|
+
return {
|
|
1341
|
+
...super.toJSON(),
|
|
1342
|
+
type: "AST_XML_DECLARATION_NODE",
|
|
1343
|
+
tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
|
|
1344
|
+
children: this.children.map(node => node.toJSON()),
|
|
1345
|
+
tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
|
|
1346
|
+
};
|
|
1347
|
+
}
|
|
1348
|
+
treeInspect() {
|
|
1349
|
+
let output = "";
|
|
1350
|
+
output += `@ XMLDeclarationNode ${this.location.treeInspectWithLabel()}\n`;
|
|
1351
|
+
output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
|
|
1352
|
+
output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
|
|
1353
|
+
output += `├── children: ${this.inspectArray(this.children, "│ ")}`;
|
|
1354
|
+
output += `└── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
|
|
1355
|
+
return output;
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
class CDATANode extends Node {
|
|
1359
|
+
tag_opening;
|
|
1360
|
+
children;
|
|
1361
|
+
tag_closing;
|
|
1362
|
+
static get type() {
|
|
1363
|
+
return "AST_CDATA_NODE";
|
|
1364
|
+
}
|
|
1365
|
+
static from(data) {
|
|
1366
|
+
return new CDATANode({
|
|
1367
|
+
type: data.type,
|
|
1368
|
+
location: Location.from(data.location),
|
|
1369
|
+
errors: (data.errors || []).map(error => HerbError.from(error)),
|
|
1370
|
+
tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
|
|
1371
|
+
children: (data.children || []).map(node => fromSerializedNode(node)),
|
|
1372
|
+
tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
|
|
1373
|
+
});
|
|
1374
|
+
}
|
|
1375
|
+
constructor(props) {
|
|
1376
|
+
super(props.type, props.location, props.errors);
|
|
1377
|
+
this.tag_opening = props.tag_opening;
|
|
1378
|
+
this.children = props.children;
|
|
1379
|
+
this.tag_closing = props.tag_closing;
|
|
1380
|
+
}
|
|
1381
|
+
accept(visitor) {
|
|
1382
|
+
visitor.visitCDATANode(this);
|
|
1383
|
+
}
|
|
1384
|
+
childNodes() {
|
|
1385
|
+
return [
|
|
1386
|
+
...this.children,
|
|
1387
|
+
];
|
|
1388
|
+
}
|
|
1389
|
+
compactChildNodes() {
|
|
1390
|
+
return this.childNodes().filter(node => node !== null && node !== undefined);
|
|
1391
|
+
}
|
|
1392
|
+
recursiveErrors() {
|
|
1393
|
+
return [
|
|
1394
|
+
...this.errors,
|
|
1395
|
+
...this.children.map(node => node.recursiveErrors()),
|
|
1396
|
+
].flat();
|
|
1397
|
+
}
|
|
1398
|
+
toJSON() {
|
|
1399
|
+
return {
|
|
1400
|
+
...super.toJSON(),
|
|
1401
|
+
type: "AST_CDATA_NODE",
|
|
1402
|
+
tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
|
|
1403
|
+
children: this.children.map(node => node.toJSON()),
|
|
1404
|
+
tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
|
|
1405
|
+
};
|
|
1406
|
+
}
|
|
1407
|
+
treeInspect() {
|
|
1408
|
+
let output = "";
|
|
1409
|
+
output += `@ CDATANode ${this.location.treeInspectWithLabel()}\n`;
|
|
1410
|
+
output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
|
|
1411
|
+
output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
|
|
1412
|
+
output += `├── children: ${this.inspectArray(this.children, "│ ")}`;
|
|
1413
|
+
output += `└── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
|
|
1508
1414
|
return output;
|
|
1509
1415
|
}
|
|
1510
1416
|
}
|
|
1511
1417
|
class WhitespaceNode extends Node {
|
|
1512
1418
|
value;
|
|
1419
|
+
static get type() {
|
|
1420
|
+
return "AST_WHITESPACE_NODE";
|
|
1421
|
+
}
|
|
1513
1422
|
static from(data) {
|
|
1514
1423
|
return new WhitespaceNode({
|
|
1515
1424
|
type: data.type,
|
|
@@ -1548,7 +1457,6 @@ class WhitespaceNode extends Node {
|
|
|
1548
1457
|
output += `@ WhitespaceNode ${this.location.treeInspectWithLabel()}\n`;
|
|
1549
1458
|
output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
|
|
1550
1459
|
output += `└── value: ${this.value ? this.value.treeInspect() : "∅"}\n`;
|
|
1551
|
-
// output += "\n";
|
|
1552
1460
|
return output;
|
|
1553
1461
|
}
|
|
1554
1462
|
}
|
|
@@ -1559,6 +1467,9 @@ class ERBContentNode extends Node {
|
|
|
1559
1467
|
// no-op for analyzed_ruby
|
|
1560
1468
|
parsed;
|
|
1561
1469
|
valid;
|
|
1470
|
+
static get type() {
|
|
1471
|
+
return "AST_ERB_CONTENT_NODE";
|
|
1472
|
+
}
|
|
1562
1473
|
static from(data) {
|
|
1563
1474
|
return new ERBContentNode({
|
|
1564
1475
|
type: data.type,
|
|
@@ -1617,7 +1528,6 @@ class ERBContentNode extends Node {
|
|
|
1617
1528
|
// no-op for analyzed_ruby
|
|
1618
1529
|
output += `├── parsed: ${typeof this.parsed === 'boolean' ? String(this.parsed) : "∅"}\n`;
|
|
1619
1530
|
output += `└── valid: ${typeof this.valid === 'boolean' ? String(this.valid) : "∅"}\n`;
|
|
1620
|
-
// output += "\n";
|
|
1621
1531
|
return output;
|
|
1622
1532
|
}
|
|
1623
1533
|
}
|
|
@@ -1625,6 +1535,9 @@ class ERBEndNode extends Node {
|
|
|
1625
1535
|
tag_opening;
|
|
1626
1536
|
content;
|
|
1627
1537
|
tag_closing;
|
|
1538
|
+
static get type() {
|
|
1539
|
+
return "AST_ERB_END_NODE";
|
|
1540
|
+
}
|
|
1628
1541
|
static from(data) {
|
|
1629
1542
|
return new ERBEndNode({
|
|
1630
1543
|
type: data.type,
|
|
@@ -1671,7 +1584,6 @@ class ERBEndNode extends Node {
|
|
|
1671
1584
|
output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
|
|
1672
1585
|
output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
|
|
1673
1586
|
output += `└── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
|
|
1674
|
-
// output += "\n";
|
|
1675
1587
|
return output;
|
|
1676
1588
|
}
|
|
1677
1589
|
}
|
|
@@ -1680,6 +1592,9 @@ class ERBElseNode extends Node {
|
|
|
1680
1592
|
content;
|
|
1681
1593
|
tag_closing;
|
|
1682
1594
|
statements;
|
|
1595
|
+
static get type() {
|
|
1596
|
+
return "AST_ERB_ELSE_NODE";
|
|
1597
|
+
}
|
|
1683
1598
|
static from(data) {
|
|
1684
1599
|
return new ERBElseNode({
|
|
1685
1600
|
type: data.type,
|
|
@@ -1733,7 +1648,6 @@ class ERBElseNode extends Node {
|
|
|
1733
1648
|
output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
|
|
1734
1649
|
output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
|
|
1735
1650
|
output += `└── statements: ${this.inspectArray(this.statements, " ")}`;
|
|
1736
|
-
// output += "\n";
|
|
1737
1651
|
return output;
|
|
1738
1652
|
}
|
|
1739
1653
|
}
|
|
@@ -1744,6 +1658,9 @@ class ERBIfNode extends Node {
|
|
|
1744
1658
|
statements;
|
|
1745
1659
|
subsequent;
|
|
1746
1660
|
end_node;
|
|
1661
|
+
static get type() {
|
|
1662
|
+
return "AST_ERB_IF_NODE";
|
|
1663
|
+
}
|
|
1747
1664
|
static from(data) {
|
|
1748
1665
|
return new ERBIfNode({
|
|
1749
1666
|
type: data.type,
|
|
@@ -1753,8 +1670,8 @@ class ERBIfNode extends Node {
|
|
|
1753
1670
|
content: data.content ? Token.from(data.content) : null,
|
|
1754
1671
|
tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
|
|
1755
1672
|
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,
|
|
1673
|
+
subsequent: data.subsequent ? fromSerializedNode((data.subsequent)) : null,
|
|
1674
|
+
end_node: data.end_node ? fromSerializedNode((data.end_node)) : null,
|
|
1758
1675
|
});
|
|
1759
1676
|
}
|
|
1760
1677
|
constructor(props) {
|
|
@@ -1809,7 +1726,6 @@ class ERBIfNode extends Node {
|
|
|
1809
1726
|
output += `├── statements: ${this.inspectArray(this.statements, "│ ")}`;
|
|
1810
1727
|
output += `├── subsequent: ${this.inspectNode(this.subsequent, "│ ")}`;
|
|
1811
1728
|
output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
|
|
1812
|
-
// output += "\n";
|
|
1813
1729
|
return output;
|
|
1814
1730
|
}
|
|
1815
1731
|
}
|
|
@@ -1819,6 +1735,9 @@ class ERBBlockNode extends Node {
|
|
|
1819
1735
|
tag_closing;
|
|
1820
1736
|
body;
|
|
1821
1737
|
end_node;
|
|
1738
|
+
static get type() {
|
|
1739
|
+
return "AST_ERB_BLOCK_NODE";
|
|
1740
|
+
}
|
|
1822
1741
|
static from(data) {
|
|
1823
1742
|
return new ERBBlockNode({
|
|
1824
1743
|
type: data.type,
|
|
@@ -1828,7 +1747,7 @@ class ERBBlockNode extends Node {
|
|
|
1828
1747
|
content: data.content ? Token.from(data.content) : null,
|
|
1829
1748
|
tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
|
|
1830
1749
|
body: (data.body || []).map(node => fromSerializedNode(node)),
|
|
1831
|
-
end_node: data.end_node ? fromSerializedNode(data.end_node) : null,
|
|
1750
|
+
end_node: data.end_node ? fromSerializedNode((data.end_node)) : null,
|
|
1832
1751
|
});
|
|
1833
1752
|
}
|
|
1834
1753
|
constructor(props) {
|
|
@@ -1878,7 +1797,6 @@ class ERBBlockNode extends Node {
|
|
|
1878
1797
|
output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
|
|
1879
1798
|
output += `├── body: ${this.inspectArray(this.body, "│ ")}`;
|
|
1880
1799
|
output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
|
|
1881
|
-
// output += "\n";
|
|
1882
1800
|
return output;
|
|
1883
1801
|
}
|
|
1884
1802
|
}
|
|
@@ -1887,6 +1805,9 @@ class ERBWhenNode extends Node {
|
|
|
1887
1805
|
content;
|
|
1888
1806
|
tag_closing;
|
|
1889
1807
|
statements;
|
|
1808
|
+
static get type() {
|
|
1809
|
+
return "AST_ERB_WHEN_NODE";
|
|
1810
|
+
}
|
|
1890
1811
|
static from(data) {
|
|
1891
1812
|
return new ERBWhenNode({
|
|
1892
1813
|
type: data.type,
|
|
@@ -1940,7 +1861,6 @@ class ERBWhenNode extends Node {
|
|
|
1940
1861
|
output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
|
|
1941
1862
|
output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
|
|
1942
1863
|
output += `└── statements: ${this.inspectArray(this.statements, " ")}`;
|
|
1943
|
-
// output += "\n";
|
|
1944
1864
|
return output;
|
|
1945
1865
|
}
|
|
1946
1866
|
}
|
|
@@ -1952,6 +1872,9 @@ class ERBCaseNode extends Node {
|
|
|
1952
1872
|
conditions;
|
|
1953
1873
|
else_clause;
|
|
1954
1874
|
end_node;
|
|
1875
|
+
static get type() {
|
|
1876
|
+
return "AST_ERB_CASE_NODE";
|
|
1877
|
+
}
|
|
1955
1878
|
static from(data) {
|
|
1956
1879
|
return new ERBCaseNode({
|
|
1957
1880
|
type: data.type,
|
|
@@ -1962,8 +1885,8 @@ class ERBCaseNode extends Node {
|
|
|
1962
1885
|
tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
|
|
1963
1886
|
children: (data.children || []).map(node => fromSerializedNode(node)),
|
|
1964
1887
|
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,
|
|
1888
|
+
else_clause: data.else_clause ? fromSerializedNode((data.else_clause)) : null,
|
|
1889
|
+
end_node: data.end_node ? fromSerializedNode((data.end_node)) : null,
|
|
1967
1890
|
});
|
|
1968
1891
|
}
|
|
1969
1892
|
constructor(props) {
|
|
@@ -2023,7 +1946,6 @@ class ERBCaseNode extends Node {
|
|
|
2023
1946
|
output += `├── conditions: ${this.inspectArray(this.conditions, "│ ")}`;
|
|
2024
1947
|
output += `├── else_clause: ${this.inspectNode(this.else_clause, "│ ")}`;
|
|
2025
1948
|
output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
|
|
2026
|
-
// output += "\n";
|
|
2027
1949
|
return output;
|
|
2028
1950
|
}
|
|
2029
1951
|
}
|
|
@@ -2035,6 +1957,9 @@ class ERBCaseMatchNode extends Node {
|
|
|
2035
1957
|
conditions;
|
|
2036
1958
|
else_clause;
|
|
2037
1959
|
end_node;
|
|
1960
|
+
static get type() {
|
|
1961
|
+
return "AST_ERB_CASE_MATCH_NODE";
|
|
1962
|
+
}
|
|
2038
1963
|
static from(data) {
|
|
2039
1964
|
return new ERBCaseMatchNode({
|
|
2040
1965
|
type: data.type,
|
|
@@ -2045,8 +1970,8 @@ class ERBCaseMatchNode extends Node {
|
|
|
2045
1970
|
tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
|
|
2046
1971
|
children: (data.children || []).map(node => fromSerializedNode(node)),
|
|
2047
1972
|
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,
|
|
1973
|
+
else_clause: data.else_clause ? fromSerializedNode((data.else_clause)) : null,
|
|
1974
|
+
end_node: data.end_node ? fromSerializedNode((data.end_node)) : null,
|
|
2050
1975
|
});
|
|
2051
1976
|
}
|
|
2052
1977
|
constructor(props) {
|
|
@@ -2106,7 +2031,6 @@ class ERBCaseMatchNode extends Node {
|
|
|
2106
2031
|
output += `├── conditions: ${this.inspectArray(this.conditions, "│ ")}`;
|
|
2107
2032
|
output += `├── else_clause: ${this.inspectNode(this.else_clause, "│ ")}`;
|
|
2108
2033
|
output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
|
|
2109
|
-
// output += "\n";
|
|
2110
2034
|
return output;
|
|
2111
2035
|
}
|
|
2112
2036
|
}
|
|
@@ -2116,6 +2040,9 @@ class ERBWhileNode extends Node {
|
|
|
2116
2040
|
tag_closing;
|
|
2117
2041
|
statements;
|
|
2118
2042
|
end_node;
|
|
2043
|
+
static get type() {
|
|
2044
|
+
return "AST_ERB_WHILE_NODE";
|
|
2045
|
+
}
|
|
2119
2046
|
static from(data) {
|
|
2120
2047
|
return new ERBWhileNode({
|
|
2121
2048
|
type: data.type,
|
|
@@ -2125,7 +2052,7 @@ class ERBWhileNode extends Node {
|
|
|
2125
2052
|
content: data.content ? Token.from(data.content) : null,
|
|
2126
2053
|
tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
|
|
2127
2054
|
statements: (data.statements || []).map(node => fromSerializedNode(node)),
|
|
2128
|
-
end_node: data.end_node ? fromSerializedNode(data.end_node) : null,
|
|
2055
|
+
end_node: data.end_node ? fromSerializedNode((data.end_node)) : null,
|
|
2129
2056
|
});
|
|
2130
2057
|
}
|
|
2131
2058
|
constructor(props) {
|
|
@@ -2175,7 +2102,6 @@ class ERBWhileNode extends Node {
|
|
|
2175
2102
|
output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
|
|
2176
2103
|
output += `├── statements: ${this.inspectArray(this.statements, "│ ")}`;
|
|
2177
2104
|
output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
|
|
2178
|
-
// output += "\n";
|
|
2179
2105
|
return output;
|
|
2180
2106
|
}
|
|
2181
2107
|
}
|
|
@@ -2185,6 +2111,9 @@ class ERBUntilNode extends Node {
|
|
|
2185
2111
|
tag_closing;
|
|
2186
2112
|
statements;
|
|
2187
2113
|
end_node;
|
|
2114
|
+
static get type() {
|
|
2115
|
+
return "AST_ERB_UNTIL_NODE";
|
|
2116
|
+
}
|
|
2188
2117
|
static from(data) {
|
|
2189
2118
|
return new ERBUntilNode({
|
|
2190
2119
|
type: data.type,
|
|
@@ -2194,7 +2123,7 @@ class ERBUntilNode extends Node {
|
|
|
2194
2123
|
content: data.content ? Token.from(data.content) : null,
|
|
2195
2124
|
tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
|
|
2196
2125
|
statements: (data.statements || []).map(node => fromSerializedNode(node)),
|
|
2197
|
-
end_node: data.end_node ? fromSerializedNode(data.end_node) : null,
|
|
2126
|
+
end_node: data.end_node ? fromSerializedNode((data.end_node)) : null,
|
|
2198
2127
|
});
|
|
2199
2128
|
}
|
|
2200
2129
|
constructor(props) {
|
|
@@ -2244,7 +2173,6 @@ class ERBUntilNode extends Node {
|
|
|
2244
2173
|
output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
|
|
2245
2174
|
output += `├── statements: ${this.inspectArray(this.statements, "│ ")}`;
|
|
2246
2175
|
output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
|
|
2247
|
-
// output += "\n";
|
|
2248
2176
|
return output;
|
|
2249
2177
|
}
|
|
2250
2178
|
}
|
|
@@ -2254,6 +2182,9 @@ class ERBForNode extends Node {
|
|
|
2254
2182
|
tag_closing;
|
|
2255
2183
|
statements;
|
|
2256
2184
|
end_node;
|
|
2185
|
+
static get type() {
|
|
2186
|
+
return "AST_ERB_FOR_NODE";
|
|
2187
|
+
}
|
|
2257
2188
|
static from(data) {
|
|
2258
2189
|
return new ERBForNode({
|
|
2259
2190
|
type: data.type,
|
|
@@ -2263,7 +2194,7 @@ class ERBForNode extends Node {
|
|
|
2263
2194
|
content: data.content ? Token.from(data.content) : null,
|
|
2264
2195
|
tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
|
|
2265
2196
|
statements: (data.statements || []).map(node => fromSerializedNode(node)),
|
|
2266
|
-
end_node: data.end_node ? fromSerializedNode(data.end_node) : null,
|
|
2197
|
+
end_node: data.end_node ? fromSerializedNode((data.end_node)) : null,
|
|
2267
2198
|
});
|
|
2268
2199
|
}
|
|
2269
2200
|
constructor(props) {
|
|
@@ -2313,7 +2244,6 @@ class ERBForNode extends Node {
|
|
|
2313
2244
|
output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
|
|
2314
2245
|
output += `├── statements: ${this.inspectArray(this.statements, "│ ")}`;
|
|
2315
2246
|
output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
|
|
2316
|
-
// output += "\n";
|
|
2317
2247
|
return output;
|
|
2318
2248
|
}
|
|
2319
2249
|
}
|
|
@@ -2323,6 +2253,9 @@ class ERBRescueNode extends Node {
|
|
|
2323
2253
|
tag_closing;
|
|
2324
2254
|
statements;
|
|
2325
2255
|
subsequent;
|
|
2256
|
+
static get type() {
|
|
2257
|
+
return "AST_ERB_RESCUE_NODE";
|
|
2258
|
+
}
|
|
2326
2259
|
static from(data) {
|
|
2327
2260
|
return new ERBRescueNode({
|
|
2328
2261
|
type: data.type,
|
|
@@ -2332,7 +2265,7 @@ class ERBRescueNode extends Node {
|
|
|
2332
2265
|
content: data.content ? Token.from(data.content) : null,
|
|
2333
2266
|
tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
|
|
2334
2267
|
statements: (data.statements || []).map(node => fromSerializedNode(node)),
|
|
2335
|
-
subsequent: data.subsequent ? fromSerializedNode(data.subsequent) : null,
|
|
2268
|
+
subsequent: data.subsequent ? fromSerializedNode((data.subsequent)) : null,
|
|
2336
2269
|
});
|
|
2337
2270
|
}
|
|
2338
2271
|
constructor(props) {
|
|
@@ -2382,7 +2315,6 @@ class ERBRescueNode extends Node {
|
|
|
2382
2315
|
output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
|
|
2383
2316
|
output += `├── statements: ${this.inspectArray(this.statements, "│ ")}`;
|
|
2384
2317
|
output += `└── subsequent: ${this.inspectNode(this.subsequent, " ")}`;
|
|
2385
|
-
// output += "\n";
|
|
2386
2318
|
return output;
|
|
2387
2319
|
}
|
|
2388
2320
|
}
|
|
@@ -2391,6 +2323,9 @@ class ERBEnsureNode extends Node {
|
|
|
2391
2323
|
content;
|
|
2392
2324
|
tag_closing;
|
|
2393
2325
|
statements;
|
|
2326
|
+
static get type() {
|
|
2327
|
+
return "AST_ERB_ENSURE_NODE";
|
|
2328
|
+
}
|
|
2394
2329
|
static from(data) {
|
|
2395
2330
|
return new ERBEnsureNode({
|
|
2396
2331
|
type: data.type,
|
|
@@ -2444,7 +2379,6 @@ class ERBEnsureNode extends Node {
|
|
|
2444
2379
|
output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
|
|
2445
2380
|
output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
|
|
2446
2381
|
output += `└── statements: ${this.inspectArray(this.statements, " ")}`;
|
|
2447
|
-
// output += "\n";
|
|
2448
2382
|
return output;
|
|
2449
2383
|
}
|
|
2450
2384
|
}
|
|
@@ -2457,6 +2391,9 @@ class ERBBeginNode extends Node {
|
|
|
2457
2391
|
else_clause;
|
|
2458
2392
|
ensure_clause;
|
|
2459
2393
|
end_node;
|
|
2394
|
+
static get type() {
|
|
2395
|
+
return "AST_ERB_BEGIN_NODE";
|
|
2396
|
+
}
|
|
2460
2397
|
static from(data) {
|
|
2461
2398
|
return new ERBBeginNode({
|
|
2462
2399
|
type: data.type,
|
|
@@ -2466,10 +2403,10 @@ class ERBBeginNode extends Node {
|
|
|
2466
2403
|
content: data.content ? Token.from(data.content) : null,
|
|
2467
2404
|
tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
|
|
2468
2405
|
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,
|
|
2406
|
+
rescue_clause: data.rescue_clause ? fromSerializedNode((data.rescue_clause)) : null,
|
|
2407
|
+
else_clause: data.else_clause ? fromSerializedNode((data.else_clause)) : null,
|
|
2408
|
+
ensure_clause: data.ensure_clause ? fromSerializedNode((data.ensure_clause)) : null,
|
|
2409
|
+
end_node: data.end_node ? fromSerializedNode((data.end_node)) : null,
|
|
2473
2410
|
});
|
|
2474
2411
|
}
|
|
2475
2412
|
constructor(props) {
|
|
@@ -2534,7 +2471,6 @@ class ERBBeginNode extends Node {
|
|
|
2534
2471
|
output += `├── else_clause: ${this.inspectNode(this.else_clause, "│ ")}`;
|
|
2535
2472
|
output += `├── ensure_clause: ${this.inspectNode(this.ensure_clause, "│ ")}`;
|
|
2536
2473
|
output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
|
|
2537
|
-
// output += "\n";
|
|
2538
2474
|
return output;
|
|
2539
2475
|
}
|
|
2540
2476
|
}
|
|
@@ -2545,6 +2481,9 @@ class ERBUnlessNode extends Node {
|
|
|
2545
2481
|
statements;
|
|
2546
2482
|
else_clause;
|
|
2547
2483
|
end_node;
|
|
2484
|
+
static get type() {
|
|
2485
|
+
return "AST_ERB_UNLESS_NODE";
|
|
2486
|
+
}
|
|
2548
2487
|
static from(data) {
|
|
2549
2488
|
return new ERBUnlessNode({
|
|
2550
2489
|
type: data.type,
|
|
@@ -2554,8 +2493,8 @@ class ERBUnlessNode extends Node {
|
|
|
2554
2493
|
content: data.content ? Token.from(data.content) : null,
|
|
2555
2494
|
tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
|
|
2556
2495
|
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,
|
|
2496
|
+
else_clause: data.else_clause ? fromSerializedNode((data.else_clause)) : null,
|
|
2497
|
+
end_node: data.end_node ? fromSerializedNode((data.end_node)) : null,
|
|
2559
2498
|
});
|
|
2560
2499
|
}
|
|
2561
2500
|
constructor(props) {
|
|
@@ -2610,7 +2549,6 @@ class ERBUnlessNode extends Node {
|
|
|
2610
2549
|
output += `├── statements: ${this.inspectArray(this.statements, "│ ")}`;
|
|
2611
2550
|
output += `├── else_clause: ${this.inspectNode(this.else_clause, "│ ")}`;
|
|
2612
2551
|
output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
|
|
2613
|
-
// output += "\n";
|
|
2614
2552
|
return output;
|
|
2615
2553
|
}
|
|
2616
2554
|
}
|
|
@@ -2618,6 +2556,9 @@ class ERBYieldNode extends Node {
|
|
|
2618
2556
|
tag_opening;
|
|
2619
2557
|
content;
|
|
2620
2558
|
tag_closing;
|
|
2559
|
+
static get type() {
|
|
2560
|
+
return "AST_ERB_YIELD_NODE";
|
|
2561
|
+
}
|
|
2621
2562
|
static from(data) {
|
|
2622
2563
|
return new ERBYieldNode({
|
|
2623
2564
|
type: data.type,
|
|
@@ -2664,7 +2605,6 @@ class ERBYieldNode extends Node {
|
|
|
2664
2605
|
output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
|
|
2665
2606
|
output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
|
|
2666
2607
|
output += `└── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
|
|
2667
|
-
// output += "\n";
|
|
2668
2608
|
return output;
|
|
2669
2609
|
}
|
|
2670
2610
|
}
|
|
@@ -2673,6 +2613,9 @@ class ERBInNode extends Node {
|
|
|
2673
2613
|
content;
|
|
2674
2614
|
tag_closing;
|
|
2675
2615
|
statements;
|
|
2616
|
+
static get type() {
|
|
2617
|
+
return "AST_ERB_IN_NODE";
|
|
2618
|
+
}
|
|
2676
2619
|
static from(data) {
|
|
2677
2620
|
return new ERBInNode({
|
|
2678
2621
|
type: data.type,
|
|
@@ -2726,7 +2669,6 @@ class ERBInNode extends Node {
|
|
|
2726
2669
|
output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
|
|
2727
2670
|
output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
|
|
2728
2671
|
output += `└── statements: ${this.inspectArray(this.statements, " ")}`;
|
|
2729
|
-
// output += "\n";
|
|
2730
2672
|
return output;
|
|
2731
2673
|
}
|
|
2732
2674
|
}
|
|
@@ -2736,7 +2678,6 @@ function fromSerializedNode(node) {
|
|
|
2736
2678
|
case "AST_LITERAL_NODE": return LiteralNode.from(node);
|
|
2737
2679
|
case "AST_HTML_OPEN_TAG_NODE": return HTMLOpenTagNode.from(node);
|
|
2738
2680
|
case "AST_HTML_CLOSE_TAG_NODE": return HTMLCloseTagNode.from(node);
|
|
2739
|
-
case "AST_HTML_SELF_CLOSE_TAG_NODE": return HTMLSelfCloseTagNode.from(node);
|
|
2740
2681
|
case "AST_HTML_ELEMENT_NODE": return HTMLElementNode.from(node);
|
|
2741
2682
|
case "AST_HTML_ATTRIBUTE_VALUE_NODE": return HTMLAttributeValueNode.from(node);
|
|
2742
2683
|
case "AST_HTML_ATTRIBUTE_NAME_NODE": return HTMLAttributeNameNode.from(node);
|
|
@@ -2744,6 +2685,8 @@ function fromSerializedNode(node) {
|
|
|
2744
2685
|
case "AST_HTML_TEXT_NODE": return HTMLTextNode.from(node);
|
|
2745
2686
|
case "AST_HTML_COMMENT_NODE": return HTMLCommentNode.from(node);
|
|
2746
2687
|
case "AST_HTML_DOCTYPE_NODE": return HTMLDoctypeNode.from(node);
|
|
2688
|
+
case "AST_XML_DECLARATION_NODE": return XMLDeclarationNode.from(node);
|
|
2689
|
+
case "AST_CDATA_NODE": return CDATANode.from(node);
|
|
2747
2690
|
case "AST_WHITESPACE_NODE": return WhitespaceNode.from(node);
|
|
2748
2691
|
case "AST_ERB_CONTENT_NODE": return ERBContentNode.from(node);
|
|
2749
2692
|
case "AST_ERB_END_NODE": return ERBEndNode.from(node);
|
|
@@ -2785,8 +2728,42 @@ const ERBNodeClasses = [
|
|
|
2785
2728
|
ERBYieldNode,
|
|
2786
2729
|
ERBInNode,
|
|
2787
2730
|
];
|
|
2788
|
-
|
|
2789
|
-
|
|
2731
|
+
|
|
2732
|
+
class Result {
|
|
2733
|
+
source;
|
|
2734
|
+
warnings;
|
|
2735
|
+
errors;
|
|
2736
|
+
constructor(source, warnings = [], errors = []) {
|
|
2737
|
+
this.source = source;
|
|
2738
|
+
this.warnings = warnings || [];
|
|
2739
|
+
this.errors = errors || [];
|
|
2740
|
+
}
|
|
2741
|
+
/**
|
|
2742
|
+
* Determines if the parsing was successful.
|
|
2743
|
+
* @returns `true` if there are no errors, otherwise `false`.
|
|
2744
|
+
*/
|
|
2745
|
+
get successful() {
|
|
2746
|
+
return this.errors.length === 0;
|
|
2747
|
+
}
|
|
2748
|
+
/**
|
|
2749
|
+
* Determines if the parsing failed.
|
|
2750
|
+
* @returns `true` if there are errors, otherwise `false`.
|
|
2751
|
+
*/
|
|
2752
|
+
get failed() {
|
|
2753
|
+
return this.errors.length > 0;
|
|
2754
|
+
}
|
|
2755
|
+
}
|
|
2756
|
+
|
|
2757
|
+
class HerbWarning {
|
|
2758
|
+
message;
|
|
2759
|
+
location;
|
|
2760
|
+
static from(warning) {
|
|
2761
|
+
return new HerbWarning(warning.message, Location.from(warning.location));
|
|
2762
|
+
}
|
|
2763
|
+
constructor(message, location) {
|
|
2764
|
+
this.message = message;
|
|
2765
|
+
this.location = location;
|
|
2766
|
+
}
|
|
2790
2767
|
}
|
|
2791
2768
|
|
|
2792
2769
|
/**
|
|
@@ -2856,23 +2833,1017 @@ class ParseResult extends Result {
|
|
|
2856
2833
|
}
|
|
2857
2834
|
}
|
|
2858
2835
|
|
|
2836
|
+
// NOTE: This file is generated by the templates/template.rb script and should not
|
|
2837
|
+
// be modified manually. See /Users/marcoroth/Development/herb-release-0.6.1/templates/javascript/packages/core/src/node-type-guards.ts.erb
|
|
2859
2838
|
/**
|
|
2860
|
-
*
|
|
2839
|
+
* Type guard functions for AST nodes.
|
|
2840
|
+
* These functions provide type checking by combining both instanceof
|
|
2841
|
+
* checks and type string comparisons for maximum reliability across different
|
|
2842
|
+
* runtime scenarios (e.g., serialized/deserialized nodes).
|
|
2861
2843
|
*/
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2844
|
+
/**
|
|
2845
|
+
* Checks if a node is a DocumentNode
|
|
2846
|
+
*/
|
|
2847
|
+
function isDocumentNode(node) {
|
|
2848
|
+
return node instanceof DocumentNode || node.type === "AST_DOCUMENT_NODE" || node.constructor.type === "AST_DOCUMENT_NODE";
|
|
2849
|
+
}
|
|
2850
|
+
/**
|
|
2851
|
+
* Checks if a node is a LiteralNode
|
|
2852
|
+
*/
|
|
2853
|
+
function isLiteralNode(node) {
|
|
2854
|
+
return node instanceof LiteralNode || node.type === "AST_LITERAL_NODE" || node.constructor.type === "AST_LITERAL_NODE";
|
|
2855
|
+
}
|
|
2856
|
+
/**
|
|
2857
|
+
* Checks if a node is a HTMLOpenTagNode
|
|
2858
|
+
*/
|
|
2859
|
+
function isHTMLOpenTagNode(node) {
|
|
2860
|
+
return node instanceof HTMLOpenTagNode || node.type === "AST_HTML_OPEN_TAG_NODE" || node.constructor.type === "AST_HTML_OPEN_TAG_NODE";
|
|
2861
|
+
}
|
|
2862
|
+
/**
|
|
2863
|
+
* Checks if a node is a HTMLCloseTagNode
|
|
2864
|
+
*/
|
|
2865
|
+
function isHTMLCloseTagNode(node) {
|
|
2866
|
+
return node instanceof HTMLCloseTagNode || node.type === "AST_HTML_CLOSE_TAG_NODE" || node.constructor.type === "AST_HTML_CLOSE_TAG_NODE";
|
|
2867
|
+
}
|
|
2868
|
+
/**
|
|
2869
|
+
* Checks if a node is a HTMLElementNode
|
|
2870
|
+
*/
|
|
2871
|
+
function isHTMLElementNode(node) {
|
|
2872
|
+
return node instanceof HTMLElementNode || node.type === "AST_HTML_ELEMENT_NODE" || node.constructor.type === "AST_HTML_ELEMENT_NODE";
|
|
2873
|
+
}
|
|
2874
|
+
/**
|
|
2875
|
+
* Checks if a node is a HTMLAttributeValueNode
|
|
2876
|
+
*/
|
|
2877
|
+
function isHTMLAttributeValueNode(node) {
|
|
2878
|
+
return node instanceof HTMLAttributeValueNode || node.type === "AST_HTML_ATTRIBUTE_VALUE_NODE" || node.constructor.type === "AST_HTML_ATTRIBUTE_VALUE_NODE";
|
|
2879
|
+
}
|
|
2880
|
+
/**
|
|
2881
|
+
* Checks if a node is a HTMLAttributeNameNode
|
|
2882
|
+
*/
|
|
2883
|
+
function isHTMLAttributeNameNode(node) {
|
|
2884
|
+
return node instanceof HTMLAttributeNameNode || node.type === "AST_HTML_ATTRIBUTE_NAME_NODE" || node.constructor.type === "AST_HTML_ATTRIBUTE_NAME_NODE";
|
|
2885
|
+
}
|
|
2886
|
+
/**
|
|
2887
|
+
* Checks if a node is a HTMLAttributeNode
|
|
2888
|
+
*/
|
|
2889
|
+
function isHTMLAttributeNode(node) {
|
|
2890
|
+
return node instanceof HTMLAttributeNode || node.type === "AST_HTML_ATTRIBUTE_NODE" || node.constructor.type === "AST_HTML_ATTRIBUTE_NODE";
|
|
2891
|
+
}
|
|
2892
|
+
/**
|
|
2893
|
+
* Checks if a node is a HTMLTextNode
|
|
2894
|
+
*/
|
|
2895
|
+
function isHTMLTextNode(node) {
|
|
2896
|
+
return node instanceof HTMLTextNode || node.type === "AST_HTML_TEXT_NODE" || node.constructor.type === "AST_HTML_TEXT_NODE";
|
|
2897
|
+
}
|
|
2898
|
+
/**
|
|
2899
|
+
* Checks if a node is a HTMLCommentNode
|
|
2900
|
+
*/
|
|
2901
|
+
function isHTMLCommentNode(node) {
|
|
2902
|
+
return node instanceof HTMLCommentNode || node.type === "AST_HTML_COMMENT_NODE" || node.constructor.type === "AST_HTML_COMMENT_NODE";
|
|
2903
|
+
}
|
|
2904
|
+
/**
|
|
2905
|
+
* Checks if a node is a HTMLDoctypeNode
|
|
2906
|
+
*/
|
|
2907
|
+
function isHTMLDoctypeNode(node) {
|
|
2908
|
+
return node instanceof HTMLDoctypeNode || node.type === "AST_HTML_DOCTYPE_NODE" || node.constructor.type === "AST_HTML_DOCTYPE_NODE";
|
|
2909
|
+
}
|
|
2910
|
+
/**
|
|
2911
|
+
* Checks if a node is a XMLDeclarationNode
|
|
2912
|
+
*/
|
|
2913
|
+
function isXMLDeclarationNode(node) {
|
|
2914
|
+
return node instanceof XMLDeclarationNode || node.type === "AST_XML_DECLARATION_NODE" || node.constructor.type === "AST_XML_DECLARATION_NODE";
|
|
2915
|
+
}
|
|
2916
|
+
/**
|
|
2917
|
+
* Checks if a node is a CDATANode
|
|
2918
|
+
*/
|
|
2919
|
+
function isCDATANode(node) {
|
|
2920
|
+
return node instanceof CDATANode || node.type === "AST_CDATA_NODE" || node.constructor.type === "AST_CDATA_NODE";
|
|
2921
|
+
}
|
|
2922
|
+
/**
|
|
2923
|
+
* Checks if a node is a WhitespaceNode
|
|
2924
|
+
*/
|
|
2925
|
+
function isWhitespaceNode(node) {
|
|
2926
|
+
return node instanceof WhitespaceNode || node.type === "AST_WHITESPACE_NODE" || node.constructor.type === "AST_WHITESPACE_NODE";
|
|
2927
|
+
}
|
|
2928
|
+
/**
|
|
2929
|
+
* Checks if a node is a ERBContentNode
|
|
2930
|
+
*/
|
|
2931
|
+
function isERBContentNode(node) {
|
|
2932
|
+
return node instanceof ERBContentNode || node.type === "AST_ERB_CONTENT_NODE" || node.constructor.type === "AST_ERB_CONTENT_NODE";
|
|
2933
|
+
}
|
|
2934
|
+
/**
|
|
2935
|
+
* Checks if a node is a ERBEndNode
|
|
2936
|
+
*/
|
|
2937
|
+
function isERBEndNode(node) {
|
|
2938
|
+
return node instanceof ERBEndNode || node.type === "AST_ERB_END_NODE" || node.constructor.type === "AST_ERB_END_NODE";
|
|
2939
|
+
}
|
|
2940
|
+
/**
|
|
2941
|
+
* Checks if a node is a ERBElseNode
|
|
2942
|
+
*/
|
|
2943
|
+
function isERBElseNode(node) {
|
|
2944
|
+
return node instanceof ERBElseNode || node.type === "AST_ERB_ELSE_NODE" || node.constructor.type === "AST_ERB_ELSE_NODE";
|
|
2945
|
+
}
|
|
2946
|
+
/**
|
|
2947
|
+
* Checks if a node is a ERBIfNode
|
|
2948
|
+
*/
|
|
2949
|
+
function isERBIfNode(node) {
|
|
2950
|
+
return node instanceof ERBIfNode || node.type === "AST_ERB_IF_NODE" || node.constructor.type === "AST_ERB_IF_NODE";
|
|
2951
|
+
}
|
|
2952
|
+
/**
|
|
2953
|
+
* Checks if a node is a ERBBlockNode
|
|
2954
|
+
*/
|
|
2955
|
+
function isERBBlockNode(node) {
|
|
2956
|
+
return node instanceof ERBBlockNode || node.type === "AST_ERB_BLOCK_NODE" || node.constructor.type === "AST_ERB_BLOCK_NODE";
|
|
2957
|
+
}
|
|
2958
|
+
/**
|
|
2959
|
+
* Checks if a node is a ERBWhenNode
|
|
2960
|
+
*/
|
|
2961
|
+
function isERBWhenNode(node) {
|
|
2962
|
+
return node instanceof ERBWhenNode || node.type === "AST_ERB_WHEN_NODE" || node.constructor.type === "AST_ERB_WHEN_NODE";
|
|
2963
|
+
}
|
|
2964
|
+
/**
|
|
2965
|
+
* Checks if a node is a ERBCaseNode
|
|
2966
|
+
*/
|
|
2967
|
+
function isERBCaseNode(node) {
|
|
2968
|
+
return node instanceof ERBCaseNode || node.type === "AST_ERB_CASE_NODE" || node.constructor.type === "AST_ERB_CASE_NODE";
|
|
2969
|
+
}
|
|
2970
|
+
/**
|
|
2971
|
+
* Checks if a node is a ERBCaseMatchNode
|
|
2972
|
+
*/
|
|
2973
|
+
function isERBCaseMatchNode(node) {
|
|
2974
|
+
return node instanceof ERBCaseMatchNode || node.type === "AST_ERB_CASE_MATCH_NODE" || node.constructor.type === "AST_ERB_CASE_MATCH_NODE";
|
|
2975
|
+
}
|
|
2976
|
+
/**
|
|
2977
|
+
* Checks if a node is a ERBWhileNode
|
|
2978
|
+
*/
|
|
2979
|
+
function isERBWhileNode(node) {
|
|
2980
|
+
return node instanceof ERBWhileNode || node.type === "AST_ERB_WHILE_NODE" || node.constructor.type === "AST_ERB_WHILE_NODE";
|
|
2981
|
+
}
|
|
2982
|
+
/**
|
|
2983
|
+
* Checks if a node is a ERBUntilNode
|
|
2984
|
+
*/
|
|
2985
|
+
function isERBUntilNode(node) {
|
|
2986
|
+
return node instanceof ERBUntilNode || node.type === "AST_ERB_UNTIL_NODE" || node.constructor.type === "AST_ERB_UNTIL_NODE";
|
|
2987
|
+
}
|
|
2988
|
+
/**
|
|
2989
|
+
* Checks if a node is a ERBForNode
|
|
2990
|
+
*/
|
|
2991
|
+
function isERBForNode(node) {
|
|
2992
|
+
return node instanceof ERBForNode || node.type === "AST_ERB_FOR_NODE" || node.constructor.type === "AST_ERB_FOR_NODE";
|
|
2993
|
+
}
|
|
2994
|
+
/**
|
|
2995
|
+
* Checks if a node is a ERBRescueNode
|
|
2996
|
+
*/
|
|
2997
|
+
function isERBRescueNode(node) {
|
|
2998
|
+
return node instanceof ERBRescueNode || node.type === "AST_ERB_RESCUE_NODE" || node.constructor.type === "AST_ERB_RESCUE_NODE";
|
|
2999
|
+
}
|
|
3000
|
+
/**
|
|
3001
|
+
* Checks if a node is a ERBEnsureNode
|
|
3002
|
+
*/
|
|
3003
|
+
function isERBEnsureNode(node) {
|
|
3004
|
+
return node instanceof ERBEnsureNode || node.type === "AST_ERB_ENSURE_NODE" || node.constructor.type === "AST_ERB_ENSURE_NODE";
|
|
3005
|
+
}
|
|
3006
|
+
/**
|
|
3007
|
+
* Checks if a node is a ERBBeginNode
|
|
3008
|
+
*/
|
|
3009
|
+
function isERBBeginNode(node) {
|
|
3010
|
+
return node instanceof ERBBeginNode || node.type === "AST_ERB_BEGIN_NODE" || node.constructor.type === "AST_ERB_BEGIN_NODE";
|
|
3011
|
+
}
|
|
3012
|
+
/**
|
|
3013
|
+
* Checks if a node is a ERBUnlessNode
|
|
3014
|
+
*/
|
|
3015
|
+
function isERBUnlessNode(node) {
|
|
3016
|
+
return node instanceof ERBUnlessNode || node.type === "AST_ERB_UNLESS_NODE" || node.constructor.type === "AST_ERB_UNLESS_NODE";
|
|
3017
|
+
}
|
|
3018
|
+
/**
|
|
3019
|
+
* Checks if a node is a ERBYieldNode
|
|
3020
|
+
*/
|
|
3021
|
+
function isERBYieldNode(node) {
|
|
3022
|
+
return node instanceof ERBYieldNode || node.type === "AST_ERB_YIELD_NODE" || node.constructor.type === "AST_ERB_YIELD_NODE";
|
|
3023
|
+
}
|
|
3024
|
+
/**
|
|
3025
|
+
* Checks if a node is a ERBInNode
|
|
3026
|
+
*/
|
|
3027
|
+
function isERBInNode(node) {
|
|
3028
|
+
return node instanceof ERBInNode || node.type === "AST_ERB_IN_NODE" || node.constructor.type === "AST_ERB_IN_NODE";
|
|
3029
|
+
}
|
|
3030
|
+
/**
|
|
3031
|
+
* Convenience type guards for common node categories
|
|
3032
|
+
*/
|
|
3033
|
+
/**
|
|
3034
|
+
* Checks if a node is any HTML node type
|
|
3035
|
+
*/
|
|
3036
|
+
function isHTMLNode(node) {
|
|
3037
|
+
return isHTMLOpenTagNode(node) ||
|
|
3038
|
+
isHTMLCloseTagNode(node) ||
|
|
3039
|
+
isHTMLElementNode(node) ||
|
|
3040
|
+
isHTMLAttributeValueNode(node) ||
|
|
3041
|
+
isHTMLAttributeNameNode(node) ||
|
|
3042
|
+
isHTMLAttributeNode(node) ||
|
|
3043
|
+
isHTMLTextNode(node) ||
|
|
3044
|
+
isHTMLCommentNode(node) ||
|
|
3045
|
+
isHTMLDoctypeNode(node);
|
|
3046
|
+
}
|
|
3047
|
+
/**
|
|
3048
|
+
* Checks if a node is any ERB node type
|
|
3049
|
+
*/
|
|
3050
|
+
function isERBNode(node) {
|
|
3051
|
+
return isERBContentNode(node) ||
|
|
3052
|
+
isERBEndNode(node) ||
|
|
3053
|
+
isERBElseNode(node) ||
|
|
3054
|
+
isERBIfNode(node) ||
|
|
3055
|
+
isERBBlockNode(node) ||
|
|
3056
|
+
isERBWhenNode(node) ||
|
|
3057
|
+
isERBCaseNode(node) ||
|
|
3058
|
+
isERBCaseMatchNode(node) ||
|
|
3059
|
+
isERBWhileNode(node) ||
|
|
3060
|
+
isERBUntilNode(node) ||
|
|
3061
|
+
isERBForNode(node) ||
|
|
3062
|
+
isERBRescueNode(node) ||
|
|
3063
|
+
isERBEnsureNode(node) ||
|
|
3064
|
+
isERBBeginNode(node) ||
|
|
3065
|
+
isERBUnlessNode(node) ||
|
|
3066
|
+
isERBYieldNode(node) ||
|
|
3067
|
+
isERBInNode(node);
|
|
3068
|
+
}
|
|
3069
|
+
/**
|
|
3070
|
+
* Map of node classes to their corresponding type guard functions
|
|
3071
|
+
*
|
|
3072
|
+
* @example
|
|
3073
|
+
* const guard = NODE_TYPE_GUARDS[HTMLTextNode]
|
|
3074
|
+
*
|
|
3075
|
+
* if (guard(node)) {
|
|
3076
|
+
* // node is HTMLTextNode
|
|
3077
|
+
* }
|
|
3078
|
+
*/
|
|
3079
|
+
const NODE_TYPE_GUARDS = new Map([
|
|
3080
|
+
[DocumentNode, isDocumentNode],
|
|
3081
|
+
[LiteralNode, isLiteralNode],
|
|
3082
|
+
[HTMLOpenTagNode, isHTMLOpenTagNode],
|
|
3083
|
+
[HTMLCloseTagNode, isHTMLCloseTagNode],
|
|
3084
|
+
[HTMLElementNode, isHTMLElementNode],
|
|
3085
|
+
[HTMLAttributeValueNode, isHTMLAttributeValueNode],
|
|
3086
|
+
[HTMLAttributeNameNode, isHTMLAttributeNameNode],
|
|
3087
|
+
[HTMLAttributeNode, isHTMLAttributeNode],
|
|
3088
|
+
[HTMLTextNode, isHTMLTextNode],
|
|
3089
|
+
[HTMLCommentNode, isHTMLCommentNode],
|
|
3090
|
+
[HTMLDoctypeNode, isHTMLDoctypeNode],
|
|
3091
|
+
[XMLDeclarationNode, isXMLDeclarationNode],
|
|
3092
|
+
[CDATANode, isCDATANode],
|
|
3093
|
+
[WhitespaceNode, isWhitespaceNode],
|
|
3094
|
+
[ERBContentNode, isERBContentNode],
|
|
3095
|
+
[ERBEndNode, isERBEndNode],
|
|
3096
|
+
[ERBElseNode, isERBElseNode],
|
|
3097
|
+
[ERBIfNode, isERBIfNode],
|
|
3098
|
+
[ERBBlockNode, isERBBlockNode],
|
|
3099
|
+
[ERBWhenNode, isERBWhenNode],
|
|
3100
|
+
[ERBCaseNode, isERBCaseNode],
|
|
3101
|
+
[ERBCaseMatchNode, isERBCaseMatchNode],
|
|
3102
|
+
[ERBWhileNode, isERBWhileNode],
|
|
3103
|
+
[ERBUntilNode, isERBUntilNode],
|
|
3104
|
+
[ERBForNode, isERBForNode],
|
|
3105
|
+
[ERBRescueNode, isERBRescueNode],
|
|
3106
|
+
[ERBEnsureNode, isERBEnsureNode],
|
|
3107
|
+
[ERBBeginNode, isERBBeginNode],
|
|
3108
|
+
[ERBUnlessNode, isERBUnlessNode],
|
|
3109
|
+
[ERBYieldNode, isERBYieldNode],
|
|
3110
|
+
[ERBInNode, isERBInNode],
|
|
3111
|
+
]);
|
|
3112
|
+
/**
|
|
3113
|
+
* Map of AST node type strings to their corresponding type guard functions
|
|
3114
|
+
*
|
|
3115
|
+
* @example
|
|
3116
|
+
* const guard = AST_TYPE_GUARDS["AST_HTML_TEXT_NODE"]
|
|
3117
|
+
*
|
|
3118
|
+
* if (guard(node)) {
|
|
3119
|
+
* // node is HTMLTextNode
|
|
3120
|
+
* }
|
|
3121
|
+
*/
|
|
3122
|
+
const AST_TYPE_GUARDS = new Map([
|
|
3123
|
+
["AST_DOCUMENT_NODE", isDocumentNode],
|
|
3124
|
+
["AST_LITERAL_NODE", isLiteralNode],
|
|
3125
|
+
["AST_HTML_OPEN_TAG_NODE", isHTMLOpenTagNode],
|
|
3126
|
+
["AST_HTML_CLOSE_TAG_NODE", isHTMLCloseTagNode],
|
|
3127
|
+
["AST_HTML_ELEMENT_NODE", isHTMLElementNode],
|
|
3128
|
+
["AST_HTML_ATTRIBUTE_VALUE_NODE", isHTMLAttributeValueNode],
|
|
3129
|
+
["AST_HTML_ATTRIBUTE_NAME_NODE", isHTMLAttributeNameNode],
|
|
3130
|
+
["AST_HTML_ATTRIBUTE_NODE", isHTMLAttributeNode],
|
|
3131
|
+
["AST_HTML_TEXT_NODE", isHTMLTextNode],
|
|
3132
|
+
["AST_HTML_COMMENT_NODE", isHTMLCommentNode],
|
|
3133
|
+
["AST_HTML_DOCTYPE_NODE", isHTMLDoctypeNode],
|
|
3134
|
+
["AST_XML_DECLARATION_NODE", isXMLDeclarationNode],
|
|
3135
|
+
["AST_CDATA_NODE", isCDATANode],
|
|
3136
|
+
["AST_WHITESPACE_NODE", isWhitespaceNode],
|
|
3137
|
+
["AST_ERB_CONTENT_NODE", isERBContentNode],
|
|
3138
|
+
["AST_ERB_END_NODE", isERBEndNode],
|
|
3139
|
+
["AST_ERB_ELSE_NODE", isERBElseNode],
|
|
3140
|
+
["AST_ERB_IF_NODE", isERBIfNode],
|
|
3141
|
+
["AST_ERB_BLOCK_NODE", isERBBlockNode],
|
|
3142
|
+
["AST_ERB_WHEN_NODE", isERBWhenNode],
|
|
3143
|
+
["AST_ERB_CASE_NODE", isERBCaseNode],
|
|
3144
|
+
["AST_ERB_CASE_MATCH_NODE", isERBCaseMatchNode],
|
|
3145
|
+
["AST_ERB_WHILE_NODE", isERBWhileNode],
|
|
3146
|
+
["AST_ERB_UNTIL_NODE", isERBUntilNode],
|
|
3147
|
+
["AST_ERB_FOR_NODE", isERBForNode],
|
|
3148
|
+
["AST_ERB_RESCUE_NODE", isERBRescueNode],
|
|
3149
|
+
["AST_ERB_ENSURE_NODE", isERBEnsureNode],
|
|
3150
|
+
["AST_ERB_BEGIN_NODE", isERBBeginNode],
|
|
3151
|
+
["AST_ERB_UNLESS_NODE", isERBUnlessNode],
|
|
3152
|
+
["AST_ERB_YIELD_NODE", isERBYieldNode],
|
|
3153
|
+
["AST_ERB_IN_NODE", isERBInNode],
|
|
3154
|
+
]);
|
|
3155
|
+
/**
|
|
3156
|
+
* Checks if a node matches any of the provided type identifiers with proper type narrowing
|
|
3157
|
+
* Supports AST type strings, node classes, or type guard functions
|
|
3158
|
+
*
|
|
3159
|
+
* @example
|
|
3160
|
+
* if (isAnyOf(node, "AST_HTML_TEXT_NODE", "AST_LITERAL_NODE")) {
|
|
3161
|
+
* // node is narrowed to HTMLTextNode | LiteralNode
|
|
3162
|
+
* }
|
|
3163
|
+
*
|
|
3164
|
+
* @example
|
|
3165
|
+
* if (isAnyOf(node, HTMLTextNode, LiteralNode)) {
|
|
3166
|
+
* // node is narrowed to HTMLTextNode | LiteralNode
|
|
3167
|
+
* }
|
|
3168
|
+
*/
|
|
3169
|
+
function isAnyOf(node, ...types) {
|
|
3170
|
+
return types.some(type => {
|
|
3171
|
+
if (typeof type === 'string') {
|
|
3172
|
+
return isNode(node, type);
|
|
3173
|
+
}
|
|
3174
|
+
else if (typeof type === 'function' && type.prototype && type.prototype.constructor === type && NODE_TYPE_GUARDS.has(type)) {
|
|
3175
|
+
return isNode(node, type);
|
|
3176
|
+
}
|
|
3177
|
+
else if (typeof type === 'function') {
|
|
3178
|
+
return type(node);
|
|
3179
|
+
}
|
|
3180
|
+
else {
|
|
3181
|
+
return false;
|
|
3182
|
+
}
|
|
3183
|
+
});
|
|
3184
|
+
}
|
|
3185
|
+
/**
|
|
3186
|
+
* Checks if a node does NOT match any of the provided type identifiers
|
|
3187
|
+
* Supports AST type strings, node classes, or type guard functions
|
|
3188
|
+
* This is the logical inverse of isAnyOf
|
|
3189
|
+
*
|
|
3190
|
+
* @example
|
|
3191
|
+
* if (isNoneOf(node, "AST_HTML_TEXT_NODE", "AST_LITERAL_NODE")) {
|
|
3192
|
+
* // node is neither HTMLTextNode nor LiteralNode
|
|
3193
|
+
* }
|
|
3194
|
+
*
|
|
3195
|
+
* @example
|
|
3196
|
+
* if (isNoneOf(node, HTMLTextNode, LiteralNode)) {
|
|
3197
|
+
* // node is neither HTMLTextNode nor LiteralNode
|
|
3198
|
+
* }
|
|
3199
|
+
*
|
|
3200
|
+
* @example
|
|
3201
|
+
* if (isNoneOf(node, isHTMLTextNode, isLiteralNode)) {
|
|
3202
|
+
* // node is neither HTMLTextNode nor LiteralNode
|
|
3203
|
+
* }
|
|
3204
|
+
*/
|
|
3205
|
+
function isNoneOf(node, ...types) {
|
|
3206
|
+
return !isAnyOf(node, ...types);
|
|
3207
|
+
}
|
|
3208
|
+
function areAllOfType(nodes, ...types) {
|
|
3209
|
+
return nodes.every(node => isAnyOf(node, ...types));
|
|
3210
|
+
}
|
|
3211
|
+
function filterNodes(nodes, ...types) {
|
|
3212
|
+
if (!nodes)
|
|
3213
|
+
return [];
|
|
3214
|
+
return nodes.filter(node => isAnyOf(node, ...types));
|
|
3215
|
+
}
|
|
3216
|
+
function isNode(node, type) {
|
|
3217
|
+
if (!node)
|
|
3218
|
+
return false;
|
|
3219
|
+
if (typeof type === 'string') {
|
|
3220
|
+
const guard = AST_TYPE_GUARDS.get(type);
|
|
3221
|
+
return guard ? guard(node) : false;
|
|
3222
|
+
}
|
|
3223
|
+
else if (typeof type === 'function') {
|
|
3224
|
+
const guard = NODE_TYPE_GUARDS.get(type);
|
|
3225
|
+
return guard ? guard(node) : false;
|
|
3226
|
+
}
|
|
3227
|
+
else {
|
|
3228
|
+
return false;
|
|
3229
|
+
}
|
|
3230
|
+
}
|
|
3231
|
+
function isToken(object) {
|
|
3232
|
+
return (object instanceof Token) || (object?.constructor?.name === "Token" && "value" in object) || object.type?.startsWith('TOKEN_');
|
|
3233
|
+
}
|
|
3234
|
+
function isParseResult(object) {
|
|
3235
|
+
return (object instanceof ParseResult) || (object?.constructor?.name === "ParseResult" && "value" in object);
|
|
3236
|
+
}
|
|
3237
|
+
/**
|
|
3238
|
+
* Checks if a node has children (contains other nodes)
|
|
3239
|
+
*/
|
|
3240
|
+
function hasChildren(node) {
|
|
3241
|
+
return isDocumentNode(node) ||
|
|
3242
|
+
isHTMLOpenTagNode(node) ||
|
|
3243
|
+
isHTMLCloseTagNode(node) ||
|
|
3244
|
+
isHTMLElementNode(node) ||
|
|
3245
|
+
isHTMLAttributeValueNode(node) ||
|
|
3246
|
+
isHTMLAttributeNameNode(node) ||
|
|
3247
|
+
isHTMLCommentNode(node) ||
|
|
3248
|
+
isHTMLDoctypeNode(node) ||
|
|
3249
|
+
isERBElseNode(node) ||
|
|
3250
|
+
isERBIfNode(node) ||
|
|
3251
|
+
isERBBlockNode(node) ||
|
|
3252
|
+
isERBWhenNode(node) ||
|
|
3253
|
+
isERBCaseNode(node) ||
|
|
3254
|
+
isERBCaseMatchNode(node) ||
|
|
3255
|
+
isERBWhileNode(node) ||
|
|
3256
|
+
isERBUntilNode(node) ||
|
|
3257
|
+
isERBForNode(node) ||
|
|
3258
|
+
isERBRescueNode(node) ||
|
|
3259
|
+
isERBEnsureNode(node) ||
|
|
3260
|
+
isERBBeginNode(node) ||
|
|
3261
|
+
isERBUnlessNode(node) ||
|
|
3262
|
+
isERBInNode(node);
|
|
3263
|
+
}
|
|
3264
|
+
/**
|
|
3265
|
+
* Filter functions for extracting specific node types from arrays
|
|
3266
|
+
*/
|
|
3267
|
+
/**
|
|
3268
|
+
* Filters an array of nodes to only include DocumentNode nodes
|
|
3269
|
+
*/
|
|
3270
|
+
function filterDocumentNodes(nodes) {
|
|
3271
|
+
return nodes.filter(isDocumentNode);
|
|
3272
|
+
}
|
|
3273
|
+
/**
|
|
3274
|
+
* Filters an array of nodes to only include LiteralNode nodes
|
|
3275
|
+
*/
|
|
3276
|
+
function filterLiteralNodes(nodes) {
|
|
3277
|
+
return nodes.filter(isLiteralNode);
|
|
3278
|
+
}
|
|
3279
|
+
/**
|
|
3280
|
+
* Filters an array of nodes to only include HTMLOpenTagNode nodes
|
|
3281
|
+
*/
|
|
3282
|
+
function filterHTMLOpenTagNodes(nodes) {
|
|
3283
|
+
return nodes.filter(isHTMLOpenTagNode);
|
|
3284
|
+
}
|
|
3285
|
+
/**
|
|
3286
|
+
* Filters an array of nodes to only include HTMLCloseTagNode nodes
|
|
3287
|
+
*/
|
|
3288
|
+
function filterHTMLCloseTagNodes(nodes) {
|
|
3289
|
+
return nodes.filter(isHTMLCloseTagNode);
|
|
3290
|
+
}
|
|
3291
|
+
/**
|
|
3292
|
+
* Filters an array of nodes to only include HTMLElementNode nodes
|
|
3293
|
+
*/
|
|
3294
|
+
function filterHTMLElementNodes(nodes) {
|
|
3295
|
+
return nodes.filter(isHTMLElementNode);
|
|
3296
|
+
}
|
|
3297
|
+
/**
|
|
3298
|
+
* Filters an array of nodes to only include HTMLAttributeValueNode nodes
|
|
3299
|
+
*/
|
|
3300
|
+
function filterHTMLAttributeValueNodes(nodes) {
|
|
3301
|
+
return nodes.filter(isHTMLAttributeValueNode);
|
|
3302
|
+
}
|
|
3303
|
+
/**
|
|
3304
|
+
* Filters an array of nodes to only include HTMLAttributeNameNode nodes
|
|
3305
|
+
*/
|
|
3306
|
+
function filterHTMLAttributeNameNodes(nodes) {
|
|
3307
|
+
return nodes.filter(isHTMLAttributeNameNode);
|
|
3308
|
+
}
|
|
3309
|
+
/**
|
|
3310
|
+
* Filters an array of nodes to only include HTMLAttributeNode nodes
|
|
3311
|
+
*/
|
|
3312
|
+
function filterHTMLAttributeNodes(nodes) {
|
|
3313
|
+
return nodes.filter(isHTMLAttributeNode);
|
|
3314
|
+
}
|
|
3315
|
+
/**
|
|
3316
|
+
* Filters an array of nodes to only include HTMLTextNode nodes
|
|
3317
|
+
*/
|
|
3318
|
+
function filterHTMLTextNodes(nodes) {
|
|
3319
|
+
return nodes.filter(isHTMLTextNode);
|
|
3320
|
+
}
|
|
3321
|
+
/**
|
|
3322
|
+
* Filters an array of nodes to only include HTMLCommentNode nodes
|
|
3323
|
+
*/
|
|
3324
|
+
function filterHTMLCommentNodes(nodes) {
|
|
3325
|
+
return nodes.filter(isHTMLCommentNode);
|
|
3326
|
+
}
|
|
3327
|
+
/**
|
|
3328
|
+
* Filters an array of nodes to only include HTMLDoctypeNode nodes
|
|
3329
|
+
*/
|
|
3330
|
+
function filterHTMLDoctypeNodes(nodes) {
|
|
3331
|
+
return nodes.filter(isHTMLDoctypeNode);
|
|
3332
|
+
}
|
|
3333
|
+
/**
|
|
3334
|
+
* Filters an array of nodes to only include XMLDeclarationNode nodes
|
|
3335
|
+
*/
|
|
3336
|
+
function filterXMLDeclarationNodes(nodes) {
|
|
3337
|
+
return nodes.filter(isXMLDeclarationNode);
|
|
3338
|
+
}
|
|
3339
|
+
/**
|
|
3340
|
+
* Filters an array of nodes to only include CDATANode nodes
|
|
3341
|
+
*/
|
|
3342
|
+
function filterCDATANodes(nodes) {
|
|
3343
|
+
return nodes.filter(isCDATANode);
|
|
3344
|
+
}
|
|
3345
|
+
/**
|
|
3346
|
+
* Filters an array of nodes to only include WhitespaceNode nodes
|
|
3347
|
+
*/
|
|
3348
|
+
function filterWhitespaceNodes(nodes) {
|
|
3349
|
+
return nodes.filter(isWhitespaceNode);
|
|
3350
|
+
}
|
|
3351
|
+
/**
|
|
3352
|
+
* Filters an array of nodes to only include ERBContentNode nodes
|
|
3353
|
+
*/
|
|
3354
|
+
function filterERBContentNodes(nodes) {
|
|
3355
|
+
return nodes.filter(isERBContentNode);
|
|
3356
|
+
}
|
|
3357
|
+
/**
|
|
3358
|
+
* Filters an array of nodes to only include ERBEndNode nodes
|
|
3359
|
+
*/
|
|
3360
|
+
function filterERBEndNodes(nodes) {
|
|
3361
|
+
return nodes.filter(isERBEndNode);
|
|
3362
|
+
}
|
|
3363
|
+
/**
|
|
3364
|
+
* Filters an array of nodes to only include ERBElseNode nodes
|
|
3365
|
+
*/
|
|
3366
|
+
function filterERBElseNodes(nodes) {
|
|
3367
|
+
return nodes.filter(isERBElseNode);
|
|
3368
|
+
}
|
|
3369
|
+
/**
|
|
3370
|
+
* Filters an array of nodes to only include ERBIfNode nodes
|
|
3371
|
+
*/
|
|
3372
|
+
function filterERBIfNodes(nodes) {
|
|
3373
|
+
return nodes.filter(isERBIfNode);
|
|
3374
|
+
}
|
|
3375
|
+
/**
|
|
3376
|
+
* Filters an array of nodes to only include ERBBlockNode nodes
|
|
3377
|
+
*/
|
|
3378
|
+
function filterERBBlockNodes(nodes) {
|
|
3379
|
+
return nodes.filter(isERBBlockNode);
|
|
3380
|
+
}
|
|
3381
|
+
/**
|
|
3382
|
+
* Filters an array of nodes to only include ERBWhenNode nodes
|
|
3383
|
+
*/
|
|
3384
|
+
function filterERBWhenNodes(nodes) {
|
|
3385
|
+
return nodes.filter(isERBWhenNode);
|
|
3386
|
+
}
|
|
3387
|
+
/**
|
|
3388
|
+
* Filters an array of nodes to only include ERBCaseNode nodes
|
|
3389
|
+
*/
|
|
3390
|
+
function filterERBCaseNodes(nodes) {
|
|
3391
|
+
return nodes.filter(isERBCaseNode);
|
|
3392
|
+
}
|
|
3393
|
+
/**
|
|
3394
|
+
* Filters an array of nodes to only include ERBCaseMatchNode nodes
|
|
3395
|
+
*/
|
|
3396
|
+
function filterERBCaseMatchNodes(nodes) {
|
|
3397
|
+
return nodes.filter(isERBCaseMatchNode);
|
|
3398
|
+
}
|
|
3399
|
+
/**
|
|
3400
|
+
* Filters an array of nodes to only include ERBWhileNode nodes
|
|
3401
|
+
*/
|
|
3402
|
+
function filterERBWhileNodes(nodes) {
|
|
3403
|
+
return nodes.filter(isERBWhileNode);
|
|
3404
|
+
}
|
|
3405
|
+
/**
|
|
3406
|
+
* Filters an array of nodes to only include ERBUntilNode nodes
|
|
3407
|
+
*/
|
|
3408
|
+
function filterERBUntilNodes(nodes) {
|
|
3409
|
+
return nodes.filter(isERBUntilNode);
|
|
3410
|
+
}
|
|
3411
|
+
/**
|
|
3412
|
+
* Filters an array of nodes to only include ERBForNode nodes
|
|
3413
|
+
*/
|
|
3414
|
+
function filterERBForNodes(nodes) {
|
|
3415
|
+
return nodes.filter(isERBForNode);
|
|
3416
|
+
}
|
|
3417
|
+
/**
|
|
3418
|
+
* Filters an array of nodes to only include ERBRescueNode nodes
|
|
3419
|
+
*/
|
|
3420
|
+
function filterERBRescueNodes(nodes) {
|
|
3421
|
+
return nodes.filter(isERBRescueNode);
|
|
3422
|
+
}
|
|
3423
|
+
/**
|
|
3424
|
+
* Filters an array of nodes to only include ERBEnsureNode nodes
|
|
3425
|
+
*/
|
|
3426
|
+
function filterERBEnsureNodes(nodes) {
|
|
3427
|
+
return nodes.filter(isERBEnsureNode);
|
|
3428
|
+
}
|
|
3429
|
+
/**
|
|
3430
|
+
* Filters an array of nodes to only include ERBBeginNode nodes
|
|
3431
|
+
*/
|
|
3432
|
+
function filterERBBeginNodes(nodes) {
|
|
3433
|
+
return nodes.filter(isERBBeginNode);
|
|
3434
|
+
}
|
|
3435
|
+
/**
|
|
3436
|
+
* Filters an array of nodes to only include ERBUnlessNode nodes
|
|
3437
|
+
*/
|
|
3438
|
+
function filterERBUnlessNodes(nodes) {
|
|
3439
|
+
return nodes.filter(isERBUnlessNode);
|
|
3440
|
+
}
|
|
3441
|
+
/**
|
|
3442
|
+
* Filters an array of nodes to only include ERBYieldNode nodes
|
|
3443
|
+
*/
|
|
3444
|
+
function filterERBYieldNodes(nodes) {
|
|
3445
|
+
return nodes.filter(isERBYieldNode);
|
|
3446
|
+
}
|
|
3447
|
+
/**
|
|
3448
|
+
* Filters an array of nodes to only include ERBInNode nodes
|
|
3449
|
+
*/
|
|
3450
|
+
function filterERBInNodes(nodes) {
|
|
3451
|
+
return nodes.filter(isERBInNode);
|
|
3452
|
+
}
|
|
3453
|
+
|
|
3454
|
+
/**
|
|
3455
|
+
* Checks if a node is an ERB output node (generates content: <%= %> or <%== %>)
|
|
3456
|
+
*/
|
|
3457
|
+
function isERBOutputNode(node) {
|
|
3458
|
+
return isNode(node, ERBContentNode) && ["<%=", "<%=="].includes(node.tag_opening?.value);
|
|
3459
|
+
}
|
|
3460
|
+
/**
|
|
3461
|
+
* Checks if a node is a non-output ERB node (control flow: <% %>)
|
|
3462
|
+
*/
|
|
3463
|
+
function isERBControlFlowNode(node) {
|
|
3464
|
+
return isAnyOf(node, ERBIfNode, ERBUnlessNode, ERBBlockNode, ERBCaseNode, ERBCaseMatchNode, ERBWhileNode, ERBForNode, ERBBeginNode);
|
|
3465
|
+
}
|
|
3466
|
+
/**
|
|
3467
|
+
* Checks if an array of nodes contains any ERB content nodes
|
|
3468
|
+
*/
|
|
3469
|
+
function hasERBContent(nodes) {
|
|
3470
|
+
return nodes.some(isERBContentNode);
|
|
3471
|
+
}
|
|
3472
|
+
/**
|
|
3473
|
+
* Checks if an array of nodes contains any ERB output nodes (dynamic content)
|
|
3474
|
+
*/
|
|
3475
|
+
function hasERBOutput(nodes) {
|
|
3476
|
+
return nodes.some(isERBOutputNode);
|
|
3477
|
+
}
|
|
3478
|
+
/**
|
|
3479
|
+
* Extracts a static string from an array of literal nodes
|
|
3480
|
+
* Returns null if any node is not a literal node
|
|
3481
|
+
*/
|
|
3482
|
+
function getStaticStringFromNodes(nodes) {
|
|
3483
|
+
if (!areAllOfType(nodes, LiteralNode)) {
|
|
3484
|
+
return null;
|
|
3485
|
+
}
|
|
3486
|
+
return nodes.map(node => node.content).join("");
|
|
3487
|
+
}
|
|
3488
|
+
/**
|
|
3489
|
+
* Extracts static content from nodes, including mixed literal/ERB content
|
|
3490
|
+
* Returns the concatenated literal content, or null if no literal nodes exist
|
|
3491
|
+
*/
|
|
3492
|
+
function getStaticContentFromNodes(nodes) {
|
|
3493
|
+
const literalNodes = filterLiteralNodes(nodes);
|
|
3494
|
+
if (literalNodes.length === 0) {
|
|
3495
|
+
return null;
|
|
3496
|
+
}
|
|
3497
|
+
return literalNodes.map(node => node.content).join("");
|
|
3498
|
+
}
|
|
3499
|
+
/**
|
|
3500
|
+
* Checks if nodes contain any literal content (for static validation)
|
|
3501
|
+
*/
|
|
3502
|
+
function hasStaticContent(nodes) {
|
|
3503
|
+
return nodes.some(isLiteralNode);
|
|
3504
|
+
}
|
|
3505
|
+
/**
|
|
3506
|
+
* Checks if nodes are effectively static (only literals and non-output ERB)
|
|
3507
|
+
* Non-output ERB like <% if %> doesn't affect static validation
|
|
3508
|
+
*/
|
|
3509
|
+
function isEffectivelyStatic(nodes) {
|
|
3510
|
+
return !hasERBOutput(nodes);
|
|
3511
|
+
}
|
|
3512
|
+
/**
|
|
3513
|
+
* Gets static-validatable content from nodes (ignores control ERB, includes literals)
|
|
3514
|
+
* Returns concatenated literal content for validation, or null if contains output ERB
|
|
3515
|
+
*/
|
|
3516
|
+
function getValidatableStaticContent(nodes) {
|
|
3517
|
+
if (hasERBOutput(nodes)) {
|
|
3518
|
+
return null;
|
|
3519
|
+
}
|
|
3520
|
+
return filterLiteralNodes(nodes).map(node => node.content).join("");
|
|
3521
|
+
}
|
|
3522
|
+
/**
|
|
3523
|
+
* Extracts a combined string from nodes, including ERB content
|
|
3524
|
+
* For ERB nodes, includes the full tag syntax (e.g., "<%= foo %>")
|
|
3525
|
+
* This is useful for debugging or displaying the full attribute name
|
|
3526
|
+
*/
|
|
3527
|
+
function getCombinedStringFromNodes(nodes) {
|
|
3528
|
+
return nodes.map(node => {
|
|
3529
|
+
if (isLiteralNode(node)) {
|
|
3530
|
+
return node.content;
|
|
3531
|
+
}
|
|
3532
|
+
else if (isERBContentNode(node)) {
|
|
3533
|
+
const opening = node.tag_opening?.value || "";
|
|
3534
|
+
const content = node.content?.value || "";
|
|
3535
|
+
const closing = node.tag_closing?.value || "";
|
|
3536
|
+
return `${opening}${content}${closing}`;
|
|
3537
|
+
}
|
|
3538
|
+
else {
|
|
3539
|
+
// For other node types, return a placeholder or empty string
|
|
3540
|
+
return `[${node.type}]`;
|
|
3541
|
+
}
|
|
3542
|
+
}).join("");
|
|
3543
|
+
}
|
|
3544
|
+
/**
|
|
3545
|
+
* Checks if an HTML attribute name node has a static (literal-only) name
|
|
3546
|
+
*/
|
|
3547
|
+
function hasStaticAttributeName(attributeNameNode) {
|
|
3548
|
+
if (!attributeNameNode.children) {
|
|
3549
|
+
return false;
|
|
3550
|
+
}
|
|
3551
|
+
return areAllOfType(attributeNameNode.children, LiteralNode);
|
|
3552
|
+
}
|
|
3553
|
+
/**
|
|
3554
|
+
* Checks if an HTML attribute name node has dynamic content (contains ERB)
|
|
3555
|
+
*/
|
|
3556
|
+
function hasDynamicAttributeName(attributeNameNode) {
|
|
3557
|
+
if (!attributeNameNode.children) {
|
|
3558
|
+
return false;
|
|
3559
|
+
}
|
|
3560
|
+
return hasERBContent(attributeNameNode.children);
|
|
3561
|
+
}
|
|
3562
|
+
/**
|
|
3563
|
+
* Gets the static string value of an HTML attribute name node
|
|
3564
|
+
* Returns null if the attribute name contains dynamic content (ERB)
|
|
3565
|
+
*/
|
|
3566
|
+
function getStaticAttributeName(attributeNameNode) {
|
|
3567
|
+
if (!attributeNameNode.children) {
|
|
3568
|
+
return null;
|
|
3569
|
+
}
|
|
3570
|
+
return getStaticStringFromNodes(attributeNameNode.children);
|
|
3571
|
+
}
|
|
3572
|
+
/**
|
|
3573
|
+
* Gets the combined string representation of an HTML attribute name node
|
|
3574
|
+
* This includes both static and dynamic content, useful for debugging
|
|
3575
|
+
*/
|
|
3576
|
+
function getCombinedAttributeName(attributeNameNode) {
|
|
3577
|
+
if (!attributeNameNode.children) {
|
|
3578
|
+
return "";
|
|
3579
|
+
}
|
|
3580
|
+
return getCombinedStringFromNodes(attributeNameNode.children);
|
|
3581
|
+
}
|
|
3582
|
+
/**
|
|
3583
|
+
* Gets the tag name of an HTML element node
|
|
3584
|
+
*/
|
|
3585
|
+
function getTagName(node) {
|
|
3586
|
+
return node.tag_name?.value ?? "";
|
|
3587
|
+
}
|
|
3588
|
+
/**
|
|
3589
|
+
* Check if a node is a comment (HTML comment or ERB comment)
|
|
3590
|
+
*/
|
|
3591
|
+
function isCommentNode(node) {
|
|
3592
|
+
return isNode(node, HTMLCommentNode) || (isERBNode(node) && !isERBControlFlowNode(node));
|
|
3593
|
+
}
|
|
3594
|
+
/**
|
|
3595
|
+
* Compares two positions to determine if the first comes before the second
|
|
3596
|
+
* Returns true if pos1 comes before pos2 in source order
|
|
3597
|
+
* @param inclusive - If true, returns true when positions are equal
|
|
3598
|
+
*/
|
|
3599
|
+
function isPositionBefore(position1, position2, inclusive = false) {
|
|
3600
|
+
if (position1.line < position2.line)
|
|
3601
|
+
return true;
|
|
3602
|
+
if (position1.line > position2.line)
|
|
3603
|
+
return false;
|
|
3604
|
+
return inclusive ? position1.column <= position2.column : position1.column < position2.column;
|
|
3605
|
+
}
|
|
3606
|
+
/**
|
|
3607
|
+
* Compares two positions to determine if they are equal
|
|
3608
|
+
* Returns true if pos1 and pos2 are at the same location
|
|
3609
|
+
*/
|
|
3610
|
+
function isPositionEqual(position1, position2) {
|
|
3611
|
+
return position1.line === position2.line && position1.column === position2.column;
|
|
3612
|
+
}
|
|
3613
|
+
/**
|
|
3614
|
+
* Compares two positions to determine if the first comes after the second
|
|
3615
|
+
* Returns true if pos1 comes after pos2 in source order
|
|
3616
|
+
* @param inclusive - If true, returns true when positions are equal
|
|
3617
|
+
*/
|
|
3618
|
+
function isPositionAfter(position1, position2, inclusive = false) {
|
|
3619
|
+
if (position1.line > position2.line)
|
|
3620
|
+
return true;
|
|
3621
|
+
if (position1.line < position2.line)
|
|
3622
|
+
return false;
|
|
3623
|
+
return inclusive ? position1.column >= position2.column : position1.column > position2.column;
|
|
3624
|
+
}
|
|
3625
|
+
/**
|
|
3626
|
+
* Gets nodes that appear before the specified location in source order
|
|
3627
|
+
* Uses line and column positions to determine ordering
|
|
3628
|
+
*/
|
|
3629
|
+
function getNodesBeforeLocation(nodes, location) {
|
|
3630
|
+
return nodes.filter(node => node.location && isPositionBefore(node.location.end, location.start));
|
|
3631
|
+
}
|
|
3632
|
+
/**
|
|
3633
|
+
* Gets nodes that appear after the specified location in source order
|
|
3634
|
+
* Uses line and column positions to determine ordering
|
|
3635
|
+
*/
|
|
3636
|
+
function getNodesAfterLocation(nodes, location) {
|
|
3637
|
+
return nodes.filter(node => node.location && isPositionAfter(node.location.start, location.end));
|
|
3638
|
+
}
|
|
3639
|
+
/**
|
|
3640
|
+
* Splits nodes into before and after the specified location
|
|
3641
|
+
* Returns an object with `before` and `after` arrays
|
|
3642
|
+
*/
|
|
3643
|
+
function splitNodesAroundLocation(nodes, location) {
|
|
3644
|
+
return {
|
|
3645
|
+
before: getNodesBeforeLocation(nodes, location),
|
|
3646
|
+
after: getNodesAfterLocation(nodes, location)
|
|
3647
|
+
};
|
|
3648
|
+
}
|
|
3649
|
+
/**
|
|
3650
|
+
* Splits nodes at a specific position
|
|
3651
|
+
* Returns nodes that end before the position and nodes that start after the position
|
|
3652
|
+
* More precise than splitNodesAroundLocation as it uses a single position point
|
|
3653
|
+
* Uses the same defaults as the individual functions: before=exclusive, after=inclusive
|
|
3654
|
+
*/
|
|
3655
|
+
function splitNodesAroundPosition(nodes, position) {
|
|
3656
|
+
return {
|
|
3657
|
+
before: getNodesBeforePosition(nodes, position), // uses default: inclusive = false
|
|
3658
|
+
after: getNodesAfterPosition(nodes, position) // uses default: inclusive = true
|
|
3659
|
+
};
|
|
3660
|
+
}
|
|
3661
|
+
/**
|
|
3662
|
+
* Gets nodes that end before the specified position
|
|
3663
|
+
* @param inclusive - If true, includes nodes that end exactly at the position (default: false, matching half-open interval semantics)
|
|
3664
|
+
*/
|
|
3665
|
+
function getNodesBeforePosition(nodes, position, inclusive = false) {
|
|
3666
|
+
return nodes.filter(node => node.location && isPositionBefore(node.location.end, position, inclusive));
|
|
3667
|
+
}
|
|
3668
|
+
/**
|
|
3669
|
+
* Gets nodes that start after the specified position
|
|
3670
|
+
* @param inclusive - If true, includes nodes that start exactly at the position (default: true, matching typical boundary behavior)
|
|
3671
|
+
*/
|
|
3672
|
+
function getNodesAfterPosition(nodes, position, inclusive = true) {
|
|
3673
|
+
return nodes.filter(node => node.location && isPositionAfter(node.location.start, position, inclusive));
|
|
3674
|
+
}
|
|
3675
|
+
|
|
3676
|
+
const expectedFunctions = [
|
|
3677
|
+
"parse",
|
|
3678
|
+
"lex",
|
|
3679
|
+
"parseFile",
|
|
3680
|
+
"lexFile",
|
|
3681
|
+
"extractRuby",
|
|
3682
|
+
"extractHTML",
|
|
3683
|
+
"version",
|
|
3684
|
+
];
|
|
3685
|
+
// NOTE: This function should never be called and is only for type checking
|
|
3686
|
+
// so we can make sure `expectedFunctions` matches the functions defined
|
|
3687
|
+
// in `LibHerbBackendFunctions` and the other way around.
|
|
3688
|
+
//
|
|
3689
|
+
function _TYPECHECK() {
|
|
3690
|
+
const checkFunctionsExist = true;
|
|
3691
|
+
const checkInterfaceComplete = true;
|
|
3692
|
+
return { checkFunctionsExist, checkInterfaceComplete };
|
|
3693
|
+
}
|
|
3694
|
+
function isLibHerbBackend(object, libherbpath = "unknown") {
|
|
3695
|
+
for (const expectedFunction of expectedFunctions) {
|
|
3696
|
+
if (object[expectedFunction] === undefined) {
|
|
3697
|
+
throw new Error(`Libherb at "${libherbpath}" doesn't expose function "${expectedFunction}".`);
|
|
3698
|
+
}
|
|
3699
|
+
if (typeof object[expectedFunction] !== "function") {
|
|
3700
|
+
throw new Error(`Libherb at "${libherbpath}" has "${expectedFunction}" but it's not a function.`);
|
|
3701
|
+
}
|
|
3702
|
+
}
|
|
3703
|
+
return true;
|
|
3704
|
+
}
|
|
3705
|
+
function ensureLibHerbBackend(object, libherbpath = "unknown") {
|
|
3706
|
+
isLibHerbBackend(object, libherbpath);
|
|
3707
|
+
return object;
|
|
3708
|
+
}
|
|
3709
|
+
|
|
3710
|
+
/**
|
|
3711
|
+
* Converts a Diagnostic to Monaco/VSCode-compatible MonacoDiagnostic format
|
|
3712
|
+
*/
|
|
3713
|
+
function toMonacoDiagnostic(diagnostic) {
|
|
3714
|
+
const { message, location } = diagnostic;
|
|
3715
|
+
const severity = diagnostic.severity === "hint" ? "info" : diagnostic.severity;
|
|
3716
|
+
return {
|
|
3717
|
+
line: location.start.line,
|
|
3718
|
+
column: location.start.column,
|
|
3719
|
+
endLine: location.end.line,
|
|
3720
|
+
endColumn: location.end.column,
|
|
3721
|
+
message,
|
|
3722
|
+
severity
|
|
3723
|
+
};
|
|
3724
|
+
}
|
|
3725
|
+
|
|
3726
|
+
var name = "@herb-tools/core";
|
|
3727
|
+
var version = "0.6.1";
|
|
3728
|
+
var packageJSON = {
|
|
3729
|
+
name: name,
|
|
3730
|
+
version: version};
|
|
3731
|
+
|
|
3732
|
+
class TokenList {
|
|
3733
|
+
list;
|
|
3734
|
+
static from(list) {
|
|
3735
|
+
return new TokenList(list.map((token) => Token.from(token)));
|
|
3736
|
+
}
|
|
3737
|
+
constructor(list) {
|
|
3738
|
+
this.list = list;
|
|
3739
|
+
}
|
|
3740
|
+
get length() {
|
|
3741
|
+
return this.list.length;
|
|
3742
|
+
}
|
|
3743
|
+
get tokens() {
|
|
3744
|
+
return this.list;
|
|
3745
|
+
}
|
|
3746
|
+
[Symbol.iterator]() {
|
|
3747
|
+
return this.list[Symbol.iterator]();
|
|
3748
|
+
}
|
|
3749
|
+
at(index) {
|
|
3750
|
+
return this.list.at(index);
|
|
3751
|
+
}
|
|
3752
|
+
forEach(callback) {
|
|
3753
|
+
this.list.forEach(callback);
|
|
3754
|
+
}
|
|
3755
|
+
map(callback) {
|
|
3756
|
+
return this.list.map(callback);
|
|
3757
|
+
}
|
|
3758
|
+
filter(predicate) {
|
|
3759
|
+
return this.list.filter(predicate);
|
|
3760
|
+
}
|
|
3761
|
+
__getobj__() {
|
|
3762
|
+
return this.list;
|
|
3763
|
+
}
|
|
3764
|
+
inspect() {
|
|
3765
|
+
return this.list.map((token) => token.inspect()).join("\n") + "\n";
|
|
3766
|
+
}
|
|
3767
|
+
toString() {
|
|
3768
|
+
return this.inspect();
|
|
3769
|
+
}
|
|
3770
|
+
}
|
|
3771
|
+
|
|
3772
|
+
/**
|
|
3773
|
+
* Represents the result of a lexical analysis, extending the base `Result` class.
|
|
3774
|
+
* It contains the token list, source code, warnings, and errors.
|
|
3775
|
+
*/
|
|
3776
|
+
class LexResult extends Result {
|
|
3777
|
+
/** The list of tokens generated from the source code. */
|
|
3778
|
+
value;
|
|
3779
|
+
/**
|
|
3780
|
+
* Creates a `LexResult` instance from a serialized result.
|
|
3781
|
+
* @param result - The serialized lexical result containing tokens, source, warnings, and errors.
|
|
3782
|
+
* @returns A new `LexResult` instance.
|
|
3783
|
+
*/
|
|
3784
|
+
static from(result) {
|
|
3785
|
+
return new LexResult(TokenList.from(result.tokens || []), result.source, result.warnings.map((warning) => HerbWarning.from(warning)), result.errors.map((error) => HerbError.from(error)));
|
|
3786
|
+
}
|
|
3787
|
+
/**
|
|
3788
|
+
* Constructs a new `LexResult`.
|
|
3789
|
+
* @param value - The list of tokens.
|
|
3790
|
+
* @param source - The source code that was lexed.
|
|
3791
|
+
* @param warnings - An array of warnings encountered during lexing.
|
|
3792
|
+
* @param errors - An array of errors encountered during lexing.
|
|
3793
|
+
*/
|
|
3794
|
+
constructor(value, source, warnings = [], errors = []) {
|
|
3795
|
+
super(source, warnings, errors);
|
|
3796
|
+
this.value = value;
|
|
3797
|
+
}
|
|
3798
|
+
/**
|
|
3799
|
+
* Determines if the lexing was successful.
|
|
3800
|
+
* @returns `true` if there are no errors, otherwise `false`.
|
|
3801
|
+
*/
|
|
3802
|
+
get successful() {
|
|
3803
|
+
return this.errors.length === 0;
|
|
3804
|
+
}
|
|
3805
|
+
/**
|
|
3806
|
+
* Determines if the lexing failed.
|
|
3807
|
+
* @returns `true` if there are errors, otherwise `false`.
|
|
3808
|
+
*/
|
|
3809
|
+
get failed() {
|
|
3810
|
+
return this.errors.length > 0;
|
|
3811
|
+
}
|
|
3812
|
+
/**
|
|
3813
|
+
* Converts the `LexResult` to a JSON representation.
|
|
3814
|
+
* @returns An object containing the token list, source, warnings, and errors.
|
|
3815
|
+
*/
|
|
3816
|
+
toJSON() {
|
|
3817
|
+
return {
|
|
3818
|
+
value: this.value,
|
|
3819
|
+
source: this.source,
|
|
3820
|
+
warnings: this.warnings,
|
|
3821
|
+
errors: this.errors,
|
|
3822
|
+
};
|
|
3823
|
+
}
|
|
3824
|
+
}
|
|
3825
|
+
|
|
3826
|
+
const DEFAULT_PARSER_OPTIONS = {
|
|
3827
|
+
track_whitespace: false,
|
|
3828
|
+
};
|
|
3829
|
+
|
|
3830
|
+
/**
|
|
3831
|
+
* The main Herb parser interface, providing methods to lex and parse input.
|
|
3832
|
+
*/
|
|
3833
|
+
class HerbBackend {
|
|
3834
|
+
/** The backend instance handling lexing and parsing. */
|
|
3835
|
+
backend = undefined;
|
|
3836
|
+
backendPromise;
|
|
3837
|
+
/**
|
|
3838
|
+
* Creates a new Herb instance.
|
|
3839
|
+
* @param backendPromise - A promise resolving to a `LibHerbBackend` implementation for lexing and parsing.
|
|
3840
|
+
* @throws Error if no valid backend is provided.
|
|
3841
|
+
*/
|
|
3842
|
+
constructor(backendPromise) {
|
|
3843
|
+
if (!backendPromise) {
|
|
3844
|
+
throw new Error("No LibHerb backend provided");
|
|
3845
|
+
}
|
|
3846
|
+
this.backendPromise = backendPromise;
|
|
2876
3847
|
}
|
|
2877
3848
|
/**
|
|
2878
3849
|
* Loads the backend by resolving the backend promise.
|
|
@@ -2906,12 +3877,14 @@ class HerbBackend {
|
|
|
2906
3877
|
/**
|
|
2907
3878
|
* Parses the given source string into a `ParseResult`.
|
|
2908
3879
|
* @param source - The source code to parse.
|
|
3880
|
+
* @param options - Optional parsing options.
|
|
2909
3881
|
* @returns A `ParseResult` instance.
|
|
2910
3882
|
* @throws Error if the backend is not loaded.
|
|
2911
3883
|
*/
|
|
2912
|
-
parse(source) {
|
|
3884
|
+
parse(source, options) {
|
|
2913
3885
|
this.ensureBackend();
|
|
2914
|
-
|
|
3886
|
+
const mergedOptions = { ...DEFAULT_PARSER_OPTIONS, ...options };
|
|
3887
|
+
return ParseResult.from(this.backend.parse(ensureString(source), mergedOptions));
|
|
2915
3888
|
}
|
|
2916
3889
|
/**
|
|
2917
3890
|
* Parses a file.
|
|
@@ -2974,7 +3947,7 @@ class HerbBackend {
|
|
|
2974
3947
|
}
|
|
2975
3948
|
|
|
2976
3949
|
// NOTE: This file is generated by the templates/template.rb script and should not
|
|
2977
|
-
// be modified manually. See /Users/marcoroth/Development/herb-release-0.
|
|
3950
|
+
// be modified manually. See /Users/marcoroth/Development/herb-release-0.6.1/templates/javascript/packages/core/src/visitor.ts.erb
|
|
2978
3951
|
class Visitor {
|
|
2979
3952
|
visit(node) {
|
|
2980
3953
|
if (!node)
|
|
@@ -2999,9 +3972,6 @@ class Visitor {
|
|
|
2999
3972
|
visitHTMLCloseTagNode(node) {
|
|
3000
3973
|
this.visitChildNodes(node);
|
|
3001
3974
|
}
|
|
3002
|
-
visitHTMLSelfCloseTagNode(node) {
|
|
3003
|
-
this.visitChildNodes(node);
|
|
3004
|
-
}
|
|
3005
3975
|
visitHTMLElementNode(node) {
|
|
3006
3976
|
this.visitChildNodes(node);
|
|
3007
3977
|
}
|
|
@@ -3023,6 +3993,12 @@ class Visitor {
|
|
|
3023
3993
|
visitHTMLDoctypeNode(node) {
|
|
3024
3994
|
this.visitChildNodes(node);
|
|
3025
3995
|
}
|
|
3996
|
+
visitXMLDeclarationNode(node) {
|
|
3997
|
+
this.visitChildNodes(node);
|
|
3998
|
+
}
|
|
3999
|
+
visitCDATANode(node) {
|
|
4000
|
+
this.visitChildNodes(node);
|
|
4001
|
+
}
|
|
3026
4002
|
visitWhitespaceNode(node) {
|
|
3027
4003
|
this.visitChildNodes(node);
|
|
3028
4004
|
}
|
|
@@ -3079,5 +4055,5 @@ class Visitor {
|
|
|
3079
4055
|
}
|
|
3080
4056
|
}
|
|
3081
4057
|
|
|
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,
|
|
4058
|
+
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, getNodesAfterLocation, getNodesAfterPosition, getNodesBeforeLocation, getNodesBeforePosition, 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, isPositionAfter, isPositionEqual, isToken, isWhitespaceNode, isXMLDeclarationNode, splitNodesAroundLocation, splitNodesAroundPosition, toMonacoDiagnostic };
|
|
3083
4059
|
//# sourceMappingURL=herb-core.esm.js.map
|