@herb-tools/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/CHANGELOG.md +3 -0
  2. package/README.md +9 -0
  3. package/dist/herb-core.browser.js +2704 -0
  4. package/dist/herb-core.browser.js.map +1 -0
  5. package/dist/herb-core.cjs +2759 -0
  6. package/dist/herb-core.cjs.map +1 -0
  7. package/dist/herb-core.esm.js +2704 -0
  8. package/dist/herb-core.esm.js.map +1 -0
  9. package/dist/herb-core.umd.js +2765 -0
  10. package/dist/herb-core.umd.js.map +1 -0
  11. package/dist/types/ast.d.ts +4 -0
  12. package/dist/types/backend.d.ts +24 -0
  13. package/dist/types/error.d.ts +16 -0
  14. package/dist/types/errors.d.ts +222 -0
  15. package/dist/types/herb-backend.d.ts +87 -0
  16. package/dist/types/index.d.ts +15 -0
  17. package/dist/types/lex-result.d.ts +50 -0
  18. package/dist/types/location.d.ts +18 -0
  19. package/dist/types/node.d.ts +27 -0
  20. package/dist/types/nodes.d.ts +682 -0
  21. package/dist/types/parse-result.d.ts +62 -0
  22. package/dist/types/position.d.ts +15 -0
  23. package/dist/types/range.d.ts +12 -0
  24. package/dist/types/result.d.ts +10 -0
  25. package/dist/types/token-list.d.ts +16 -0
  26. package/dist/types/token.d.ts +22 -0
  27. package/dist/types/util.d.ts +2 -0
  28. package/dist/types/visitor.d.ts +11 -0
  29. package/dist/types/warning.d.ts +11 -0
  30. package/package.json +49 -0
  31. package/src/ast.ts +7 -0
  32. package/src/backend.ts +85 -0
  33. package/src/error.ts +38 -0
  34. package/src/errors.ts +820 -0
  35. package/src/herb-backend.ts +152 -0
  36. package/src/index.ts +15 -0
  37. package/src/lex-result.ts +78 -0
  38. package/src/location.ts +51 -0
  39. package/src/node.ts +106 -0
  40. package/src/nodes.ts +2294 -0
  41. package/src/parse-result.ts +101 -0
  42. package/src/position.ts +38 -0
  43. package/src/range.ts +35 -0
  44. package/src/result.ts +26 -0
  45. package/src/token-list.ts +57 -0
  46. package/src/token.ts +63 -0
  47. package/src/util.ts +19 -0
  48. package/src/visitor.ts +14 -0
  49. package/src/warning.ts +20 -0
package/src/nodes.ts ADDED
@@ -0,0 +1,2294 @@
1
+ // NOTE: This file is generated by the templates/template.rb script and should not
2
+ // be modified manually. See /Users/marcoroth/Development/herb-release/templates/javascript/packages/core/src/nodes.ts.erb
3
+
4
+ import { Node } from "./node.js"
5
+ import { Location, SerializedLocation } from "./location.js"
6
+ import { Token, SerializedToken } from "./token.js"
7
+ import { HerbError, SerializedHerbError } from "./error.js"
8
+ import { convertToUTF8 } from "./util.js"
9
+
10
+ import type { SerializedNode, BaseNodeProps } from "./node.js"
11
+
12
+ export function fromSerializedNode(node: SerializedNode): Node {
13
+ switch (node.type) {
14
+ case "AST_DOCUMENT_NODE": return DocumentNode.from(node as SerializedDocumentNode);
15
+ case "AST_LITERAL_NODE": return LiteralNode.from(node as SerializedLiteralNode);
16
+ case "AST_HTML_OPEN_TAG_NODE": return HTMLOpenTagNode.from(node as SerializedHTMLOpenTagNode);
17
+ case "AST_HTML_CLOSE_TAG_NODE": return HTMLCloseTagNode.from(node as SerializedHTMLCloseTagNode);
18
+ case "AST_HTML_SELF_CLOSE_TAG_NODE": return HTMLSelfCloseTagNode.from(node as SerializedHTMLSelfCloseTagNode);
19
+ case "AST_HTML_ELEMENT_NODE": return HTMLElementNode.from(node as SerializedHTMLElementNode);
20
+ case "AST_HTML_ATTRIBUTE_VALUE_NODE": return HTMLAttributeValueNode.from(node as SerializedHTMLAttributeValueNode);
21
+ case "AST_HTML_ATTRIBUTE_NAME_NODE": return HTMLAttributeNameNode.from(node as SerializedHTMLAttributeNameNode);
22
+ case "AST_HTML_ATTRIBUTE_NODE": return HTMLAttributeNode.from(node as SerializedHTMLAttributeNode);
23
+ case "AST_HTML_TEXT_NODE": return HTMLTextNode.from(node as SerializedHTMLTextNode);
24
+ case "AST_HTML_COMMENT_NODE": return HTMLCommentNode.from(node as SerializedHTMLCommentNode);
25
+ case "AST_HTML_DOCTYPE_NODE": return HTMLDoctypeNode.from(node as SerializedHTMLDoctypeNode);
26
+ case "AST_WHITESPACE_NODE": return WhitespaceNode.from(node as SerializedWhitespaceNode);
27
+ case "AST_ERB_CONTENT_NODE": return ERBContentNode.from(node as SerializedERBContentNode);
28
+ case "AST_ERB_END_NODE": return ERBEndNode.from(node as SerializedERBEndNode);
29
+ case "AST_ERB_ELSE_NODE": return ERBElseNode.from(node as SerializedERBElseNode);
30
+ case "AST_ERB_IF_NODE": return ERBIfNode.from(node as SerializedERBIfNode);
31
+ case "AST_ERB_BLOCK_NODE": return ERBBlockNode.from(node as SerializedERBBlockNode);
32
+ case "AST_ERB_WHEN_NODE": return ERBWhenNode.from(node as SerializedERBWhenNode);
33
+ case "AST_ERB_CASE_NODE": return ERBCaseNode.from(node as SerializedERBCaseNode);
34
+ case "AST_ERB_WHILE_NODE": return ERBWhileNode.from(node as SerializedERBWhileNode);
35
+ case "AST_ERB_UNTIL_NODE": return ERBUntilNode.from(node as SerializedERBUntilNode);
36
+ case "AST_ERB_FOR_NODE": return ERBForNode.from(node as SerializedERBForNode);
37
+ case "AST_ERB_RESCUE_NODE": return ERBRescueNode.from(node as SerializedERBRescueNode);
38
+ case "AST_ERB_ENSURE_NODE": return ERBEnsureNode.from(node as SerializedERBEnsureNode);
39
+ case "AST_ERB_BEGIN_NODE": return ERBBeginNode.from(node as SerializedERBBeginNode);
40
+ case "AST_ERB_UNLESS_NODE": return ERBUnlessNode.from(node as SerializedERBUnlessNode);
41
+
42
+ default:
43
+ throw new Error(`Unknown node type: ${node.type}`);
44
+ }
45
+ }
46
+ export type SerializedNodeType = string
47
+
48
+ export type NodeType =
49
+ | "AST_DOCUMENT_NODE"
50
+ | "AST_LITERAL_NODE"
51
+ | "AST_HTML_OPEN_TAG_NODE"
52
+ | "AST_HTML_CLOSE_TAG_NODE"
53
+ | "AST_HTML_SELF_CLOSE_TAG_NODE"
54
+ | "AST_HTML_ELEMENT_NODE"
55
+ | "AST_HTML_ATTRIBUTE_VALUE_NODE"
56
+ | "AST_HTML_ATTRIBUTE_NAME_NODE"
57
+ | "AST_HTML_ATTRIBUTE_NODE"
58
+ | "AST_HTML_TEXT_NODE"
59
+ | "AST_HTML_COMMENT_NODE"
60
+ | "AST_HTML_DOCTYPE_NODE"
61
+ | "AST_WHITESPACE_NODE"
62
+ | "AST_ERB_CONTENT_NODE"
63
+ | "AST_ERB_END_NODE"
64
+ | "AST_ERB_ELSE_NODE"
65
+ | "AST_ERB_IF_NODE"
66
+ | "AST_ERB_BLOCK_NODE"
67
+ | "AST_ERB_WHEN_NODE"
68
+ | "AST_ERB_CASE_NODE"
69
+ | "AST_ERB_WHILE_NODE"
70
+ | "AST_ERB_UNTIL_NODE"
71
+ | "AST_ERB_FOR_NODE"
72
+ | "AST_ERB_RESCUE_NODE"
73
+ | "AST_ERB_ENSURE_NODE"
74
+ | "AST_ERB_BEGIN_NODE"
75
+ | "AST_ERB_UNLESS_NODE"
76
+
77
+ export interface SerializedDocumentNode extends SerializedNode {
78
+ type: "AST_DOCUMENT_NODE";
79
+ children: SerializedNode[];
80
+ }
81
+
82
+ export interface DocumentNodeProps extends BaseNodeProps {
83
+ children: Node[];
84
+ }
85
+
86
+ export class DocumentNode extends Node {
87
+ readonly children: Node[];
88
+
89
+ static from(data: SerializedDocumentNode): DocumentNode {
90
+ return new DocumentNode({
91
+ type: data.type,
92
+ location: Location.from(data.location),
93
+ errors: (data.errors || []).map(error => HerbError.from(error)),
94
+ children: (data.children || []).map(node => fromSerializedNode(node)),
95
+ })
96
+ }
97
+
98
+ constructor(props: DocumentNodeProps) {
99
+ super(props.type, props.location, props.errors);
100
+ this.children = props.children;
101
+ }
102
+
103
+ childNodes(): Node[] {
104
+ return [
105
+ ...this.children,
106
+ ].filter(node => node !== null && node !== undefined) as Node[];
107
+ }
108
+
109
+ recursiveErrors(): HerbError[] {
110
+ return [
111
+ ...this.errors,
112
+ ...this.children.map(node => node.recursiveErrors()),
113
+ ].flat();
114
+ }
115
+
116
+ toJSON(): SerializedDocumentNode {
117
+ return {
118
+ ...super.toJSON(),
119
+ type: "AST_DOCUMENT_NODE",
120
+ children: this.children.map(node => node.toJSON()),
121
+ };
122
+ }
123
+
124
+ treeInspect(): string {
125
+ let output = "";
126
+
127
+ output += `@ DocumentNode ${this.location.treeInspectWithLabel()}\n`;
128
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
129
+ output += `└── children: ${this.inspectArray(this.children, " ")}`;
130
+
131
+ // output += "\n";
132
+
133
+ return output
134
+ }
135
+ }
136
+
137
+ export interface SerializedLiteralNode extends SerializedNode {
138
+ type: "AST_LITERAL_NODE";
139
+ content: string;
140
+ }
141
+
142
+ export interface LiteralNodeProps extends BaseNodeProps {
143
+ content: string;
144
+ }
145
+
146
+ export class LiteralNode extends Node {
147
+ readonly content: string;
148
+
149
+ static from(data: SerializedLiteralNode): LiteralNode {
150
+ return new LiteralNode({
151
+ type: data.type,
152
+ location: Location.from(data.location),
153
+ errors: (data.errors || []).map(error => HerbError.from(error)),
154
+ content: data.content,
155
+ })
156
+ }
157
+
158
+ constructor(props: LiteralNodeProps) {
159
+ super(props.type, props.location, props.errors);
160
+ this.content = convertToUTF8(props.content);
161
+ }
162
+
163
+ childNodes(): Node[] {
164
+ return [
165
+ ].filter(node => node !== null && node !== undefined) as Node[];
166
+ }
167
+
168
+ recursiveErrors(): HerbError[] {
169
+ return [
170
+ ...this.errors,
171
+ ].flat();
172
+ }
173
+
174
+ toJSON(): SerializedLiteralNode {
175
+ return {
176
+ ...super.toJSON(),
177
+ type: "AST_LITERAL_NODE",
178
+ content: this.content,
179
+ };
180
+ }
181
+
182
+ treeInspect(): string {
183
+ let output = "";
184
+
185
+ output += `@ LiteralNode ${this.location.treeInspectWithLabel()}\n`;
186
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
187
+ output += `└── content: ${this.content ? JSON.stringify(this.content) : "∅"}\n`;
188
+
189
+ // output += "\n";
190
+
191
+ return output
192
+ }
193
+ }
194
+
195
+ export interface SerializedHTMLOpenTagNode extends SerializedNode {
196
+ type: "AST_HTML_OPEN_TAG_NODE";
197
+ tag_opening: SerializedToken | null;
198
+ tag_name: SerializedToken | null;
199
+ tag_closing: SerializedToken | null;
200
+ children: SerializedNode[];
201
+ is_void: boolean;
202
+ }
203
+
204
+ export interface HTMLOpenTagNodeProps extends BaseNodeProps {
205
+ tag_opening: Token | null;
206
+ tag_name: Token | null;
207
+ tag_closing: Token | null;
208
+ children: Node[];
209
+ is_void: boolean;
210
+ }
211
+
212
+ export class HTMLOpenTagNode extends Node {
213
+ readonly tag_opening: Token | null;
214
+ readonly tag_name: Token | null;
215
+ readonly tag_closing: Token | null;
216
+ readonly children: Node[];
217
+ readonly is_void: boolean;
218
+
219
+ static from(data: SerializedHTMLOpenTagNode): HTMLOpenTagNode {
220
+ return new HTMLOpenTagNode({
221
+ type: data.type,
222
+ location: Location.from(data.location),
223
+ errors: (data.errors || []).map(error => HerbError.from(error)),
224
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
225
+ tag_name: data.tag_name ? Token.from(data.tag_name) : null,
226
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
227
+ children: (data.children || []).map(node => fromSerializedNode(node)),
228
+ is_void: data.is_void,
229
+ })
230
+ }
231
+
232
+ constructor(props: HTMLOpenTagNodeProps) {
233
+ super(props.type, props.location, props.errors);
234
+ this.tag_opening = props.tag_opening;
235
+ this.tag_name = props.tag_name;
236
+ this.tag_closing = props.tag_closing;
237
+ this.children = props.children;
238
+ this.is_void = props.is_void;
239
+ }
240
+
241
+ childNodes(): Node[] {
242
+ return [
243
+ ...this.children,
244
+ ].filter(node => node !== null && node !== undefined) as Node[];
245
+ }
246
+
247
+ recursiveErrors(): HerbError[] {
248
+ return [
249
+ ...this.errors,
250
+ ...this.children.map(node => node.recursiveErrors()),
251
+ ].flat();
252
+ }
253
+
254
+ toJSON(): SerializedHTMLOpenTagNode {
255
+ return {
256
+ ...super.toJSON(),
257
+ type: "AST_HTML_OPEN_TAG_NODE",
258
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
259
+ tag_name: this.tag_name ? this.tag_name.toJSON() : null,
260
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
261
+ children: this.children.map(node => node.toJSON()),
262
+ is_void: this.is_void,
263
+ };
264
+ }
265
+
266
+ treeInspect(): string {
267
+ let output = "";
268
+
269
+ output += `@ HTMLOpenTagNode ${this.location.treeInspectWithLabel()}\n`;
270
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
271
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
272
+ output += `├── tag_name: ${this.tag_name ? this.tag_name.treeInspect() : "∅"}\n`;
273
+ output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
274
+ output += `├── children: ${this.inspectArray(this.children, "│ ")}`;
275
+ output += `└── is_void: ${typeof this.is_void === 'boolean' ? String(this.is_void) : "∅"}\n`;
276
+
277
+ // output += "\n";
278
+
279
+ return output
280
+ }
281
+ }
282
+
283
+ export interface SerializedHTMLCloseTagNode extends SerializedNode {
284
+ type: "AST_HTML_CLOSE_TAG_NODE";
285
+ tag_opening: SerializedToken | null;
286
+ tag_name: SerializedToken | null;
287
+ tag_closing: SerializedToken | null;
288
+ }
289
+
290
+ export interface HTMLCloseTagNodeProps extends BaseNodeProps {
291
+ tag_opening: Token | null;
292
+ tag_name: Token | null;
293
+ tag_closing: Token | null;
294
+ }
295
+
296
+ export class HTMLCloseTagNode extends Node {
297
+ readonly tag_opening: Token | null;
298
+ readonly tag_name: Token | null;
299
+ readonly tag_closing: Token | null;
300
+
301
+ static from(data: SerializedHTMLCloseTagNode): HTMLCloseTagNode {
302
+ return new HTMLCloseTagNode({
303
+ type: data.type,
304
+ location: Location.from(data.location),
305
+ errors: (data.errors || []).map(error => HerbError.from(error)),
306
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
307
+ tag_name: data.tag_name ? Token.from(data.tag_name) : null,
308
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
309
+ })
310
+ }
311
+
312
+ constructor(props: HTMLCloseTagNodeProps) {
313
+ super(props.type, props.location, props.errors);
314
+ this.tag_opening = props.tag_opening;
315
+ this.tag_name = props.tag_name;
316
+ this.tag_closing = props.tag_closing;
317
+ }
318
+
319
+ childNodes(): Node[] {
320
+ return [
321
+ ].filter(node => node !== null && node !== undefined) as Node[];
322
+ }
323
+
324
+ recursiveErrors(): HerbError[] {
325
+ return [
326
+ ...this.errors,
327
+ ].flat();
328
+ }
329
+
330
+ toJSON(): SerializedHTMLCloseTagNode {
331
+ return {
332
+ ...super.toJSON(),
333
+ type: "AST_HTML_CLOSE_TAG_NODE",
334
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
335
+ tag_name: this.tag_name ? this.tag_name.toJSON() : null,
336
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
337
+ };
338
+ }
339
+
340
+ treeInspect(): string {
341
+ let output = "";
342
+
343
+ output += `@ HTMLCloseTagNode ${this.location.treeInspectWithLabel()}\n`;
344
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
345
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
346
+ output += `├── tag_name: ${this.tag_name ? this.tag_name.treeInspect() : "∅"}\n`;
347
+ output += `└── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
348
+
349
+ // output += "\n";
350
+
351
+ return output
352
+ }
353
+ }
354
+
355
+ export interface SerializedHTMLSelfCloseTagNode extends SerializedNode {
356
+ type: "AST_HTML_SELF_CLOSE_TAG_NODE";
357
+ tag_opening: SerializedToken | null;
358
+ tag_name: SerializedToken | null;
359
+ attributes: SerializedNode[];
360
+ tag_closing: SerializedToken | null;
361
+ is_void: boolean;
362
+ }
363
+
364
+ export interface HTMLSelfCloseTagNodeProps extends BaseNodeProps {
365
+ tag_opening: Token | null;
366
+ tag_name: Token | null;
367
+ attributes: Node[];
368
+ tag_closing: Token | null;
369
+ is_void: boolean;
370
+ }
371
+
372
+ export class HTMLSelfCloseTagNode extends Node {
373
+ readonly tag_opening: Token | null;
374
+ readonly tag_name: Token | null;
375
+ readonly attributes: Node[];
376
+ readonly tag_closing: Token | null;
377
+ readonly is_void: boolean;
378
+
379
+ static from(data: SerializedHTMLSelfCloseTagNode): HTMLSelfCloseTagNode {
380
+ return new HTMLSelfCloseTagNode({
381
+ type: data.type,
382
+ location: Location.from(data.location),
383
+ errors: (data.errors || []).map(error => HerbError.from(error)),
384
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
385
+ tag_name: data.tag_name ? Token.from(data.tag_name) : null,
386
+ attributes: (data.attributes || []).map(node => fromSerializedNode(node)),
387
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
388
+ is_void: data.is_void,
389
+ })
390
+ }
391
+
392
+ constructor(props: HTMLSelfCloseTagNodeProps) {
393
+ super(props.type, props.location, props.errors);
394
+ this.tag_opening = props.tag_opening;
395
+ this.tag_name = props.tag_name;
396
+ this.attributes = props.attributes;
397
+ this.tag_closing = props.tag_closing;
398
+ this.is_void = props.is_void;
399
+ }
400
+
401
+ childNodes(): Node[] {
402
+ return [
403
+ ...this.attributes,
404
+ ].filter(node => node !== null && node !== undefined) as Node[];
405
+ }
406
+
407
+ recursiveErrors(): HerbError[] {
408
+ return [
409
+ ...this.errors,
410
+ ...this.attributes.map(node => node.recursiveErrors()),
411
+ ].flat();
412
+ }
413
+
414
+ toJSON(): SerializedHTMLSelfCloseTagNode {
415
+ return {
416
+ ...super.toJSON(),
417
+ type: "AST_HTML_SELF_CLOSE_TAG_NODE",
418
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
419
+ tag_name: this.tag_name ? this.tag_name.toJSON() : null,
420
+ attributes: this.attributes.map(node => node.toJSON()),
421
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
422
+ is_void: this.is_void,
423
+ };
424
+ }
425
+
426
+ treeInspect(): string {
427
+ let output = "";
428
+
429
+ output += `@ HTMLSelfCloseTagNode ${this.location.treeInspectWithLabel()}\n`;
430
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
431
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
432
+ output += `├── tag_name: ${this.tag_name ? this.tag_name.treeInspect() : "∅"}\n`;
433
+ output += `├── attributes: ${this.inspectArray(this.attributes, "│ ")}`;
434
+ output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
435
+ output += `└── is_void: ${typeof this.is_void === 'boolean' ? String(this.is_void) : "∅"}\n`;
436
+
437
+ // output += "\n";
438
+
439
+ return output
440
+ }
441
+ }
442
+
443
+ export interface SerializedHTMLElementNode extends SerializedNode {
444
+ type: "AST_HTML_ELEMENT_NODE";
445
+ open_tag: SerializedNode | null;
446
+ tag_name: SerializedToken | null;
447
+ body: SerializedNode[];
448
+ close_tag: SerializedNode | null;
449
+ is_void: boolean;
450
+ }
451
+
452
+ export interface HTMLElementNodeProps extends BaseNodeProps {
453
+ open_tag: Node | null;
454
+ tag_name: Token | null;
455
+ body: Node[];
456
+ close_tag: Node | null;
457
+ is_void: boolean;
458
+ }
459
+
460
+ export class HTMLElementNode extends Node {
461
+ readonly open_tag: Node | null;
462
+ readonly tag_name: Token | null;
463
+ readonly body: Node[];
464
+ readonly close_tag: Node | null;
465
+ readonly is_void: boolean;
466
+
467
+ static from(data: SerializedHTMLElementNode): HTMLElementNode {
468
+ return new HTMLElementNode({
469
+ type: data.type,
470
+ location: Location.from(data.location),
471
+ errors: (data.errors || []).map(error => HerbError.from(error)),
472
+ open_tag: data.open_tag ? fromSerializedNode((data.open_tag as any)) : null,
473
+ tag_name: data.tag_name ? Token.from(data.tag_name) : null,
474
+ body: (data.body || []).map(node => fromSerializedNode(node)),
475
+ close_tag: data.close_tag ? fromSerializedNode((data.close_tag as any)) : null,
476
+ is_void: data.is_void,
477
+ })
478
+ }
479
+
480
+ constructor(props: HTMLElementNodeProps) {
481
+ super(props.type, props.location, props.errors);
482
+ this.open_tag = props.open_tag;
483
+ this.tag_name = props.tag_name;
484
+ this.body = props.body;
485
+ this.close_tag = props.close_tag;
486
+ this.is_void = props.is_void;
487
+ }
488
+
489
+ childNodes(): Node[] {
490
+ return [
491
+ this.open_tag,
492
+ ...this.body,
493
+ this.close_tag,
494
+ ].filter(node => node !== null && node !== undefined) as Node[];
495
+ }
496
+
497
+ recursiveErrors(): HerbError[] {
498
+ return [
499
+ ...this.errors,
500
+ this.open_tag ? this.open_tag.recursiveErrors() : [],
501
+ ...this.body.map(node => node.recursiveErrors()),
502
+ this.close_tag ? this.close_tag.recursiveErrors() : [],
503
+ ].flat();
504
+ }
505
+
506
+ toJSON(): SerializedHTMLElementNode {
507
+ return {
508
+ ...super.toJSON(),
509
+ type: "AST_HTML_ELEMENT_NODE",
510
+ open_tag: this.open_tag ? this.open_tag.toJSON() : null,
511
+ tag_name: this.tag_name ? this.tag_name.toJSON() : null,
512
+ body: this.body.map(node => node.toJSON()),
513
+ close_tag: this.close_tag ? this.close_tag.toJSON() : null,
514
+ is_void: this.is_void,
515
+ };
516
+ }
517
+
518
+ treeInspect(): string {
519
+ let output = "";
520
+
521
+ output += `@ HTMLElementNode ${this.location.treeInspectWithLabel()}\n`;
522
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
523
+ output += `├── open_tag: ${this.inspectNode(this.open_tag, "│ ")}`;
524
+ output += `├── tag_name: ${this.tag_name ? this.tag_name.treeInspect() : "∅"}\n`;
525
+ output += `├── body: ${this.inspectArray(this.body, "│ ")}`;
526
+ output += `├── close_tag: ${this.inspectNode(this.close_tag, "│ ")}`;
527
+ output += `└── is_void: ${typeof this.is_void === 'boolean' ? String(this.is_void) : "∅"}\n`;
528
+
529
+ // output += "\n";
530
+
531
+ return output
532
+ }
533
+ }
534
+
535
+ export interface SerializedHTMLAttributeValueNode extends SerializedNode {
536
+ type: "AST_HTML_ATTRIBUTE_VALUE_NODE";
537
+ open_quote: SerializedToken | null;
538
+ children: SerializedNode[];
539
+ close_quote: SerializedToken | null;
540
+ quoted: boolean;
541
+ }
542
+
543
+ export interface HTMLAttributeValueNodeProps extends BaseNodeProps {
544
+ open_quote: Token | null;
545
+ children: Node[];
546
+ close_quote: Token | null;
547
+ quoted: boolean;
548
+ }
549
+
550
+ export class HTMLAttributeValueNode extends Node {
551
+ readonly open_quote: Token | null;
552
+ readonly children: Node[];
553
+ readonly close_quote: Token | null;
554
+ readonly quoted: boolean;
555
+
556
+ static from(data: SerializedHTMLAttributeValueNode): HTMLAttributeValueNode {
557
+ return new HTMLAttributeValueNode({
558
+ type: data.type,
559
+ location: Location.from(data.location),
560
+ errors: (data.errors || []).map(error => HerbError.from(error)),
561
+ open_quote: data.open_quote ? Token.from(data.open_quote) : null,
562
+ children: (data.children || []).map(node => fromSerializedNode(node)),
563
+ close_quote: data.close_quote ? Token.from(data.close_quote) : null,
564
+ quoted: data.quoted,
565
+ })
566
+ }
567
+
568
+ constructor(props: HTMLAttributeValueNodeProps) {
569
+ super(props.type, props.location, props.errors);
570
+ this.open_quote = props.open_quote;
571
+ this.children = props.children;
572
+ this.close_quote = props.close_quote;
573
+ this.quoted = props.quoted;
574
+ }
575
+
576
+ childNodes(): Node[] {
577
+ return [
578
+ ...this.children,
579
+ ].filter(node => node !== null && node !== undefined) as Node[];
580
+ }
581
+
582
+ recursiveErrors(): HerbError[] {
583
+ return [
584
+ ...this.errors,
585
+ ...this.children.map(node => node.recursiveErrors()),
586
+ ].flat();
587
+ }
588
+
589
+ toJSON(): SerializedHTMLAttributeValueNode {
590
+ return {
591
+ ...super.toJSON(),
592
+ type: "AST_HTML_ATTRIBUTE_VALUE_NODE",
593
+ open_quote: this.open_quote ? this.open_quote.toJSON() : null,
594
+ children: this.children.map(node => node.toJSON()),
595
+ close_quote: this.close_quote ? this.close_quote.toJSON() : null,
596
+ quoted: this.quoted,
597
+ };
598
+ }
599
+
600
+ treeInspect(): string {
601
+ let output = "";
602
+
603
+ output += `@ HTMLAttributeValueNode ${this.location.treeInspectWithLabel()}\n`;
604
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
605
+ output += `├── open_quote: ${this.open_quote ? this.open_quote.treeInspect() : "∅"}\n`;
606
+ output += `├── children: ${this.inspectArray(this.children, "│ ")}`;
607
+ output += `├── close_quote: ${this.close_quote ? this.close_quote.treeInspect() : "∅"}\n`;
608
+ output += `└── quoted: ${typeof this.quoted === 'boolean' ? String(this.quoted) : "∅"}\n`;
609
+
610
+ // output += "\n";
611
+
612
+ return output
613
+ }
614
+ }
615
+
616
+ export interface SerializedHTMLAttributeNameNode extends SerializedNode {
617
+ type: "AST_HTML_ATTRIBUTE_NAME_NODE";
618
+ name: SerializedToken | null;
619
+ }
620
+
621
+ export interface HTMLAttributeNameNodeProps extends BaseNodeProps {
622
+ name: Token | null;
623
+ }
624
+
625
+ export class HTMLAttributeNameNode extends Node {
626
+ readonly name: Token | null;
627
+
628
+ static from(data: SerializedHTMLAttributeNameNode): HTMLAttributeNameNode {
629
+ return new HTMLAttributeNameNode({
630
+ type: data.type,
631
+ location: Location.from(data.location),
632
+ errors: (data.errors || []).map(error => HerbError.from(error)),
633
+ name: data.name ? Token.from(data.name) : null,
634
+ })
635
+ }
636
+
637
+ constructor(props: HTMLAttributeNameNodeProps) {
638
+ super(props.type, props.location, props.errors);
639
+ this.name = props.name;
640
+ }
641
+
642
+ childNodes(): Node[] {
643
+ return [
644
+ ].filter(node => node !== null && node !== undefined) as Node[];
645
+ }
646
+
647
+ recursiveErrors(): HerbError[] {
648
+ return [
649
+ ...this.errors,
650
+ ].flat();
651
+ }
652
+
653
+ toJSON(): SerializedHTMLAttributeNameNode {
654
+ return {
655
+ ...super.toJSON(),
656
+ type: "AST_HTML_ATTRIBUTE_NAME_NODE",
657
+ name: this.name ? this.name.toJSON() : null,
658
+ };
659
+ }
660
+
661
+ treeInspect(): string {
662
+ let output = "";
663
+
664
+ output += `@ HTMLAttributeNameNode ${this.location.treeInspectWithLabel()}\n`;
665
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
666
+ output += `└── name: ${this.name ? this.name.treeInspect() : "∅"}\n`;
667
+
668
+ // output += "\n";
669
+
670
+ return output
671
+ }
672
+ }
673
+
674
+ export interface SerializedHTMLAttributeNode extends SerializedNode {
675
+ type: "AST_HTML_ATTRIBUTE_NODE";
676
+ name: SerializedNode | null;
677
+ equals: SerializedToken | null;
678
+ value: SerializedNode | null;
679
+ }
680
+
681
+ export interface HTMLAttributeNodeProps extends BaseNodeProps {
682
+ name: Node | null;
683
+ equals: Token | null;
684
+ value: Node | null;
685
+ }
686
+
687
+ export class HTMLAttributeNode extends Node {
688
+ readonly name: Node | null;
689
+ readonly equals: Token | null;
690
+ readonly value: Node | null;
691
+
692
+ static from(data: SerializedHTMLAttributeNode): HTMLAttributeNode {
693
+ return new HTMLAttributeNode({
694
+ type: data.type,
695
+ location: Location.from(data.location),
696
+ errors: (data.errors || []).map(error => HerbError.from(error)),
697
+ name: data.name ? fromSerializedNode((data.name as any)) : null,
698
+ equals: data.equals ? Token.from(data.equals) : null,
699
+ value: data.value ? fromSerializedNode((data.value as any)) : null,
700
+ })
701
+ }
702
+
703
+ constructor(props: HTMLAttributeNodeProps) {
704
+ super(props.type, props.location, props.errors);
705
+ this.name = props.name;
706
+ this.equals = props.equals;
707
+ this.value = props.value;
708
+ }
709
+
710
+ childNodes(): Node[] {
711
+ return [
712
+ this.name,
713
+ this.value,
714
+ ].filter(node => node !== null && node !== undefined) as Node[];
715
+ }
716
+
717
+ recursiveErrors(): HerbError[] {
718
+ return [
719
+ ...this.errors,
720
+ this.name ? this.name.recursiveErrors() : [],
721
+ this.value ? this.value.recursiveErrors() : [],
722
+ ].flat();
723
+ }
724
+
725
+ toJSON(): SerializedHTMLAttributeNode {
726
+ return {
727
+ ...super.toJSON(),
728
+ type: "AST_HTML_ATTRIBUTE_NODE",
729
+ name: this.name ? this.name.toJSON() : null,
730
+ equals: this.equals ? this.equals.toJSON() : null,
731
+ value: this.value ? this.value.toJSON() : null,
732
+ };
733
+ }
734
+
735
+ treeInspect(): string {
736
+ let output = "";
737
+
738
+ output += `@ HTMLAttributeNode ${this.location.treeInspectWithLabel()}\n`;
739
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
740
+ output += `├── name: ${this.inspectNode(this.name, "│ ")}`;
741
+ output += `├── equals: ${this.equals ? this.equals.treeInspect() : "∅"}\n`;
742
+ output += `└── value: ${this.inspectNode(this.value, " ")}`;
743
+
744
+ // output += "\n";
745
+
746
+ return output
747
+ }
748
+ }
749
+
750
+ export interface SerializedHTMLTextNode extends SerializedNode {
751
+ type: "AST_HTML_TEXT_NODE";
752
+ content: string;
753
+ }
754
+
755
+ export interface HTMLTextNodeProps extends BaseNodeProps {
756
+ content: string;
757
+ }
758
+
759
+ export class HTMLTextNode extends Node {
760
+ readonly content: string;
761
+
762
+ static from(data: SerializedHTMLTextNode): HTMLTextNode {
763
+ return new HTMLTextNode({
764
+ type: data.type,
765
+ location: Location.from(data.location),
766
+ errors: (data.errors || []).map(error => HerbError.from(error)),
767
+ content: data.content,
768
+ })
769
+ }
770
+
771
+ constructor(props: HTMLTextNodeProps) {
772
+ super(props.type, props.location, props.errors);
773
+ this.content = convertToUTF8(props.content);
774
+ }
775
+
776
+ childNodes(): Node[] {
777
+ return [
778
+ ].filter(node => node !== null && node !== undefined) as Node[];
779
+ }
780
+
781
+ recursiveErrors(): HerbError[] {
782
+ return [
783
+ ...this.errors,
784
+ ].flat();
785
+ }
786
+
787
+ toJSON(): SerializedHTMLTextNode {
788
+ return {
789
+ ...super.toJSON(),
790
+ type: "AST_HTML_TEXT_NODE",
791
+ content: this.content,
792
+ };
793
+ }
794
+
795
+ treeInspect(): string {
796
+ let output = "";
797
+
798
+ output += `@ HTMLTextNode ${this.location.treeInspectWithLabel()}\n`;
799
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
800
+ output += `└── content: ${this.content ? JSON.stringify(this.content) : "∅"}\n`;
801
+
802
+ // output += "\n";
803
+
804
+ return output
805
+ }
806
+ }
807
+
808
+ export interface SerializedHTMLCommentNode extends SerializedNode {
809
+ type: "AST_HTML_COMMENT_NODE";
810
+ comment_start: SerializedToken | null;
811
+ children: SerializedNode[];
812
+ comment_end: SerializedToken | null;
813
+ }
814
+
815
+ export interface HTMLCommentNodeProps extends BaseNodeProps {
816
+ comment_start: Token | null;
817
+ children: Node[];
818
+ comment_end: Token | null;
819
+ }
820
+
821
+ export class HTMLCommentNode extends Node {
822
+ readonly comment_start: Token | null;
823
+ readonly children: Node[];
824
+ readonly comment_end: Token | null;
825
+
826
+ static from(data: SerializedHTMLCommentNode): HTMLCommentNode {
827
+ return new HTMLCommentNode({
828
+ type: data.type,
829
+ location: Location.from(data.location),
830
+ errors: (data.errors || []).map(error => HerbError.from(error)),
831
+ comment_start: data.comment_start ? Token.from(data.comment_start) : null,
832
+ children: (data.children || []).map(node => fromSerializedNode(node)),
833
+ comment_end: data.comment_end ? Token.from(data.comment_end) : null,
834
+ })
835
+ }
836
+
837
+ constructor(props: HTMLCommentNodeProps) {
838
+ super(props.type, props.location, props.errors);
839
+ this.comment_start = props.comment_start;
840
+ this.children = props.children;
841
+ this.comment_end = props.comment_end;
842
+ }
843
+
844
+ childNodes(): Node[] {
845
+ return [
846
+ ...this.children,
847
+ ].filter(node => node !== null && node !== undefined) as Node[];
848
+ }
849
+
850
+ recursiveErrors(): HerbError[] {
851
+ return [
852
+ ...this.errors,
853
+ ...this.children.map(node => node.recursiveErrors()),
854
+ ].flat();
855
+ }
856
+
857
+ toJSON(): SerializedHTMLCommentNode {
858
+ return {
859
+ ...super.toJSON(),
860
+ type: "AST_HTML_COMMENT_NODE",
861
+ comment_start: this.comment_start ? this.comment_start.toJSON() : null,
862
+ children: this.children.map(node => node.toJSON()),
863
+ comment_end: this.comment_end ? this.comment_end.toJSON() : null,
864
+ };
865
+ }
866
+
867
+ treeInspect(): string {
868
+ let output = "";
869
+
870
+ output += `@ HTMLCommentNode ${this.location.treeInspectWithLabel()}\n`;
871
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
872
+ output += `├── comment_start: ${this.comment_start ? this.comment_start.treeInspect() : "∅"}\n`;
873
+ output += `├── children: ${this.inspectArray(this.children, "│ ")}`;
874
+ output += `└── comment_end: ${this.comment_end ? this.comment_end.treeInspect() : "∅"}\n`;
875
+
876
+ // output += "\n";
877
+
878
+ return output
879
+ }
880
+ }
881
+
882
+ export interface SerializedHTMLDoctypeNode extends SerializedNode {
883
+ type: "AST_HTML_DOCTYPE_NODE";
884
+ tag_opening: SerializedToken | null;
885
+ children: SerializedNode[];
886
+ tag_closing: SerializedToken | null;
887
+ }
888
+
889
+ export interface HTMLDoctypeNodeProps extends BaseNodeProps {
890
+ tag_opening: Token | null;
891
+ children: Node[];
892
+ tag_closing: Token | null;
893
+ }
894
+
895
+ export class HTMLDoctypeNode extends Node {
896
+ readonly tag_opening: Token | null;
897
+ readonly children: Node[];
898
+ readonly tag_closing: Token | null;
899
+
900
+ static from(data: SerializedHTMLDoctypeNode): HTMLDoctypeNode {
901
+ return new HTMLDoctypeNode({
902
+ type: data.type,
903
+ location: Location.from(data.location),
904
+ errors: (data.errors || []).map(error => HerbError.from(error)),
905
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
906
+ children: (data.children || []).map(node => fromSerializedNode(node)),
907
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
908
+ })
909
+ }
910
+
911
+ constructor(props: HTMLDoctypeNodeProps) {
912
+ super(props.type, props.location, props.errors);
913
+ this.tag_opening = props.tag_opening;
914
+ this.children = props.children;
915
+ this.tag_closing = props.tag_closing;
916
+ }
917
+
918
+ childNodes(): Node[] {
919
+ return [
920
+ ...this.children,
921
+ ].filter(node => node !== null && node !== undefined) as Node[];
922
+ }
923
+
924
+ recursiveErrors(): HerbError[] {
925
+ return [
926
+ ...this.errors,
927
+ ...this.children.map(node => node.recursiveErrors()),
928
+ ].flat();
929
+ }
930
+
931
+ toJSON(): SerializedHTMLDoctypeNode {
932
+ return {
933
+ ...super.toJSON(),
934
+ type: "AST_HTML_DOCTYPE_NODE",
935
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
936
+ children: this.children.map(node => node.toJSON()),
937
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
938
+ };
939
+ }
940
+
941
+ treeInspect(): string {
942
+ let output = "";
943
+
944
+ output += `@ HTMLDoctypeNode ${this.location.treeInspectWithLabel()}\n`;
945
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
946
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
947
+ output += `├── children: ${this.inspectArray(this.children, "│ ")}`;
948
+ output += `└── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
949
+
950
+ // output += "\n";
951
+
952
+ return output
953
+ }
954
+ }
955
+
956
+ export interface SerializedWhitespaceNode extends SerializedNode {
957
+ type: "AST_WHITESPACE_NODE";
958
+ value: SerializedToken | null;
959
+ }
960
+
961
+ export interface WhitespaceNodeProps extends BaseNodeProps {
962
+ value: Token | null;
963
+ }
964
+
965
+ export class WhitespaceNode extends Node {
966
+ readonly value: Token | null;
967
+
968
+ static from(data: SerializedWhitespaceNode): WhitespaceNode {
969
+ return new WhitespaceNode({
970
+ type: data.type,
971
+ location: Location.from(data.location),
972
+ errors: (data.errors || []).map(error => HerbError.from(error)),
973
+ value: data.value ? Token.from(data.value) : null,
974
+ })
975
+ }
976
+
977
+ constructor(props: WhitespaceNodeProps) {
978
+ super(props.type, props.location, props.errors);
979
+ this.value = props.value;
980
+ }
981
+
982
+ childNodes(): Node[] {
983
+ return [
984
+ ].filter(node => node !== null && node !== undefined) as Node[];
985
+ }
986
+
987
+ recursiveErrors(): HerbError[] {
988
+ return [
989
+ ...this.errors,
990
+ ].flat();
991
+ }
992
+
993
+ toJSON(): SerializedWhitespaceNode {
994
+ return {
995
+ ...super.toJSON(),
996
+ type: "AST_WHITESPACE_NODE",
997
+ value: this.value ? this.value.toJSON() : null,
998
+ };
999
+ }
1000
+
1001
+ treeInspect(): string {
1002
+ let output = "";
1003
+
1004
+ output += `@ WhitespaceNode ${this.location.treeInspectWithLabel()}\n`;
1005
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
1006
+ output += `└── value: ${this.value ? this.value.treeInspect() : "∅"}\n`;
1007
+
1008
+ // output += "\n";
1009
+
1010
+ return output
1011
+ }
1012
+ }
1013
+
1014
+ export interface SerializedERBContentNode extends SerializedNode {
1015
+ type: "AST_ERB_CONTENT_NODE";
1016
+ tag_opening: SerializedToken | null;
1017
+ content: SerializedToken | null;
1018
+ tag_closing: SerializedToken | null;
1019
+ // no-op for analyzed_ruby
1020
+ parsed: boolean;
1021
+ valid: boolean;
1022
+ }
1023
+
1024
+ export interface ERBContentNodeProps extends BaseNodeProps {
1025
+ tag_opening: Token | null;
1026
+ content: Token | null;
1027
+ tag_closing: Token | null;
1028
+ // no-op for analyzed_ruby
1029
+ parsed: boolean;
1030
+ valid: boolean;
1031
+ }
1032
+
1033
+ export class ERBContentNode extends Node {
1034
+ readonly tag_opening: Token | null;
1035
+ readonly content: Token | null;
1036
+ readonly tag_closing: Token | null;
1037
+ // no-op for analyzed_ruby
1038
+ readonly parsed: boolean;
1039
+ readonly valid: boolean;
1040
+
1041
+ static from(data: SerializedERBContentNode): ERBContentNode {
1042
+ return new ERBContentNode({
1043
+ type: data.type,
1044
+ location: Location.from(data.location),
1045
+ errors: (data.errors || []).map(error => HerbError.from(error)),
1046
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
1047
+ content: data.content ? Token.from(data.content) : null,
1048
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
1049
+ // no-op for analyzed_ruby
1050
+ parsed: data.parsed,
1051
+ valid: data.valid,
1052
+ })
1053
+ }
1054
+
1055
+ constructor(props: ERBContentNodeProps) {
1056
+ super(props.type, props.location, props.errors);
1057
+ this.tag_opening = props.tag_opening;
1058
+ this.content = props.content;
1059
+ this.tag_closing = props.tag_closing;
1060
+ // no-op for analyzed_ruby
1061
+ this.parsed = props.parsed;
1062
+ this.valid = props.valid;
1063
+ }
1064
+
1065
+ childNodes(): Node[] {
1066
+ return [
1067
+ ].filter(node => node !== null && node !== undefined) as Node[];
1068
+ }
1069
+
1070
+ recursiveErrors(): HerbError[] {
1071
+ return [
1072
+ ...this.errors,
1073
+ ].flat();
1074
+ }
1075
+
1076
+ toJSON(): SerializedERBContentNode {
1077
+ return {
1078
+ ...super.toJSON(),
1079
+ type: "AST_ERB_CONTENT_NODE",
1080
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
1081
+ content: this.content ? this.content.toJSON() : null,
1082
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
1083
+ // no-op for analyzed_ruby
1084
+ parsed: this.parsed,
1085
+ valid: this.valid,
1086
+ };
1087
+ }
1088
+
1089
+ treeInspect(): string {
1090
+ let output = "";
1091
+
1092
+ output += `@ ERBContentNode ${this.location.treeInspectWithLabel()}\n`;
1093
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
1094
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
1095
+ output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
1096
+ output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
1097
+ // no-op for analyzed_ruby
1098
+ output += `├── parsed: ${typeof this.parsed === 'boolean' ? String(this.parsed) : "∅"}\n`;
1099
+ output += `└── valid: ${typeof this.valid === 'boolean' ? String(this.valid) : "∅"}\n`;
1100
+
1101
+ // output += "\n";
1102
+
1103
+ return output
1104
+ }
1105
+ }
1106
+
1107
+ export interface SerializedERBEndNode extends SerializedNode {
1108
+ type: "AST_ERB_END_NODE";
1109
+ tag_opening: SerializedToken | null;
1110
+ content: SerializedToken | null;
1111
+ tag_closing: SerializedToken | null;
1112
+ }
1113
+
1114
+ export interface ERBEndNodeProps extends BaseNodeProps {
1115
+ tag_opening: Token | null;
1116
+ content: Token | null;
1117
+ tag_closing: Token | null;
1118
+ }
1119
+
1120
+ export class ERBEndNode extends Node {
1121
+ readonly tag_opening: Token | null;
1122
+ readonly content: Token | null;
1123
+ readonly tag_closing: Token | null;
1124
+
1125
+ static from(data: SerializedERBEndNode): ERBEndNode {
1126
+ return new ERBEndNode({
1127
+ type: data.type,
1128
+ location: Location.from(data.location),
1129
+ errors: (data.errors || []).map(error => HerbError.from(error)),
1130
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
1131
+ content: data.content ? Token.from(data.content) : null,
1132
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
1133
+ })
1134
+ }
1135
+
1136
+ constructor(props: ERBEndNodeProps) {
1137
+ super(props.type, props.location, props.errors);
1138
+ this.tag_opening = props.tag_opening;
1139
+ this.content = props.content;
1140
+ this.tag_closing = props.tag_closing;
1141
+ }
1142
+
1143
+ childNodes(): Node[] {
1144
+ return [
1145
+ ].filter(node => node !== null && node !== undefined) as Node[];
1146
+ }
1147
+
1148
+ recursiveErrors(): HerbError[] {
1149
+ return [
1150
+ ...this.errors,
1151
+ ].flat();
1152
+ }
1153
+
1154
+ toJSON(): SerializedERBEndNode {
1155
+ return {
1156
+ ...super.toJSON(),
1157
+ type: "AST_ERB_END_NODE",
1158
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
1159
+ content: this.content ? this.content.toJSON() : null,
1160
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
1161
+ };
1162
+ }
1163
+
1164
+ treeInspect(): string {
1165
+ let output = "";
1166
+
1167
+ output += `@ ERBEndNode ${this.location.treeInspectWithLabel()}\n`;
1168
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
1169
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
1170
+ output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
1171
+ output += `└── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
1172
+
1173
+ // output += "\n";
1174
+
1175
+ return output
1176
+ }
1177
+ }
1178
+
1179
+ export interface SerializedERBElseNode extends SerializedNode {
1180
+ type: "AST_ERB_ELSE_NODE";
1181
+ tag_opening: SerializedToken | null;
1182
+ content: SerializedToken | null;
1183
+ tag_closing: SerializedToken | null;
1184
+ statements: SerializedNode[];
1185
+ }
1186
+
1187
+ export interface ERBElseNodeProps extends BaseNodeProps {
1188
+ tag_opening: Token | null;
1189
+ content: Token | null;
1190
+ tag_closing: Token | null;
1191
+ statements: Node[];
1192
+ }
1193
+
1194
+ export class ERBElseNode extends Node {
1195
+ readonly tag_opening: Token | null;
1196
+ readonly content: Token | null;
1197
+ readonly tag_closing: Token | null;
1198
+ readonly statements: Node[];
1199
+
1200
+ static from(data: SerializedERBElseNode): ERBElseNode {
1201
+ return new ERBElseNode({
1202
+ type: data.type,
1203
+ location: Location.from(data.location),
1204
+ errors: (data.errors || []).map(error => HerbError.from(error)),
1205
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
1206
+ content: data.content ? Token.from(data.content) : null,
1207
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
1208
+ statements: (data.statements || []).map(node => fromSerializedNode(node)),
1209
+ })
1210
+ }
1211
+
1212
+ constructor(props: ERBElseNodeProps) {
1213
+ super(props.type, props.location, props.errors);
1214
+ this.tag_opening = props.tag_opening;
1215
+ this.content = props.content;
1216
+ this.tag_closing = props.tag_closing;
1217
+ this.statements = props.statements;
1218
+ }
1219
+
1220
+ childNodes(): Node[] {
1221
+ return [
1222
+ ...this.statements,
1223
+ ].filter(node => node !== null && node !== undefined) as Node[];
1224
+ }
1225
+
1226
+ recursiveErrors(): HerbError[] {
1227
+ return [
1228
+ ...this.errors,
1229
+ ...this.statements.map(node => node.recursiveErrors()),
1230
+ ].flat();
1231
+ }
1232
+
1233
+ toJSON(): SerializedERBElseNode {
1234
+ return {
1235
+ ...super.toJSON(),
1236
+ type: "AST_ERB_ELSE_NODE",
1237
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
1238
+ content: this.content ? this.content.toJSON() : null,
1239
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
1240
+ statements: this.statements.map(node => node.toJSON()),
1241
+ };
1242
+ }
1243
+
1244
+ treeInspect(): string {
1245
+ let output = "";
1246
+
1247
+ output += `@ ERBElseNode ${this.location.treeInspectWithLabel()}\n`;
1248
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
1249
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
1250
+ output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
1251
+ output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
1252
+ output += `└── statements: ${this.inspectArray(this.statements, " ")}`;
1253
+
1254
+ // output += "\n";
1255
+
1256
+ return output
1257
+ }
1258
+ }
1259
+
1260
+ export interface SerializedERBIfNode extends SerializedNode {
1261
+ type: "AST_ERB_IF_NODE";
1262
+ tag_opening: SerializedToken | null;
1263
+ content: SerializedToken | null;
1264
+ tag_closing: SerializedToken | null;
1265
+ statements: SerializedNode[];
1266
+ subsequent: SerializedNode | null;
1267
+ end_node: SerializedNode | null;
1268
+ }
1269
+
1270
+ export interface ERBIfNodeProps extends BaseNodeProps {
1271
+ tag_opening: Token | null;
1272
+ content: Token | null;
1273
+ tag_closing: Token | null;
1274
+ statements: Node[];
1275
+ subsequent: Node | null;
1276
+ end_node: Node | null;
1277
+ }
1278
+
1279
+ export class ERBIfNode extends Node {
1280
+ readonly tag_opening: Token | null;
1281
+ readonly content: Token | null;
1282
+ readonly tag_closing: Token | null;
1283
+ readonly statements: Node[];
1284
+ readonly subsequent: Node | null;
1285
+ readonly end_node: Node | null;
1286
+
1287
+ static from(data: SerializedERBIfNode): ERBIfNode {
1288
+ return new ERBIfNode({
1289
+ type: data.type,
1290
+ location: Location.from(data.location),
1291
+ errors: (data.errors || []).map(error => HerbError.from(error)),
1292
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
1293
+ content: data.content ? Token.from(data.content) : null,
1294
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
1295
+ statements: (data.statements || []).map(node => fromSerializedNode(node)),
1296
+ subsequent: data.subsequent ? fromSerializedNode((data.subsequent as any)) : null,
1297
+ end_node: data.end_node ? fromSerializedNode((data.end_node as any)) : null,
1298
+ })
1299
+ }
1300
+
1301
+ constructor(props: ERBIfNodeProps) {
1302
+ super(props.type, props.location, props.errors);
1303
+ this.tag_opening = props.tag_opening;
1304
+ this.content = props.content;
1305
+ this.tag_closing = props.tag_closing;
1306
+ this.statements = props.statements;
1307
+ this.subsequent = props.subsequent;
1308
+ this.end_node = props.end_node;
1309
+ }
1310
+
1311
+ childNodes(): Node[] {
1312
+ return [
1313
+ ...this.statements,
1314
+ this.subsequent,
1315
+ this.end_node,
1316
+ ].filter(node => node !== null && node !== undefined) as Node[];
1317
+ }
1318
+
1319
+ recursiveErrors(): HerbError[] {
1320
+ return [
1321
+ ...this.errors,
1322
+ ...this.statements.map(node => node.recursiveErrors()),
1323
+ this.subsequent ? this.subsequent.recursiveErrors() : [],
1324
+ this.end_node ? this.end_node.recursiveErrors() : [],
1325
+ ].flat();
1326
+ }
1327
+
1328
+ toJSON(): SerializedERBIfNode {
1329
+ return {
1330
+ ...super.toJSON(),
1331
+ type: "AST_ERB_IF_NODE",
1332
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
1333
+ content: this.content ? this.content.toJSON() : null,
1334
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
1335
+ statements: this.statements.map(node => node.toJSON()),
1336
+ subsequent: this.subsequent ? this.subsequent.toJSON() : null,
1337
+ end_node: this.end_node ? this.end_node.toJSON() : null,
1338
+ };
1339
+ }
1340
+
1341
+ treeInspect(): string {
1342
+ let output = "";
1343
+
1344
+ output += `@ ERBIfNode ${this.location.treeInspectWithLabel()}\n`;
1345
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
1346
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
1347
+ output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
1348
+ output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
1349
+ output += `├── statements: ${this.inspectArray(this.statements, "│ ")}`;
1350
+ output += `├── subsequent: ${this.inspectNode(this.subsequent, "│ ")}`;
1351
+ output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
1352
+
1353
+ // output += "\n";
1354
+
1355
+ return output
1356
+ }
1357
+ }
1358
+
1359
+ export interface SerializedERBBlockNode extends SerializedNode {
1360
+ type: "AST_ERB_BLOCK_NODE";
1361
+ tag_opening: SerializedToken | null;
1362
+ content: SerializedToken | null;
1363
+ tag_closing: SerializedToken | null;
1364
+ body: SerializedNode[];
1365
+ end_node: SerializedNode | null;
1366
+ }
1367
+
1368
+ export interface ERBBlockNodeProps extends BaseNodeProps {
1369
+ tag_opening: Token | null;
1370
+ content: Token | null;
1371
+ tag_closing: Token | null;
1372
+ body: Node[];
1373
+ end_node: Node | null;
1374
+ }
1375
+
1376
+ export class ERBBlockNode extends Node {
1377
+ readonly tag_opening: Token | null;
1378
+ readonly content: Token | null;
1379
+ readonly tag_closing: Token | null;
1380
+ readonly body: Node[];
1381
+ readonly end_node: Node | null;
1382
+
1383
+ static from(data: SerializedERBBlockNode): ERBBlockNode {
1384
+ return new ERBBlockNode({
1385
+ type: data.type,
1386
+ location: Location.from(data.location),
1387
+ errors: (data.errors || []).map(error => HerbError.from(error)),
1388
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
1389
+ content: data.content ? Token.from(data.content) : null,
1390
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
1391
+ body: (data.body || []).map(node => fromSerializedNode(node)),
1392
+ end_node: data.end_node ? fromSerializedNode((data.end_node as any)) : null,
1393
+ })
1394
+ }
1395
+
1396
+ constructor(props: ERBBlockNodeProps) {
1397
+ super(props.type, props.location, props.errors);
1398
+ this.tag_opening = props.tag_opening;
1399
+ this.content = props.content;
1400
+ this.tag_closing = props.tag_closing;
1401
+ this.body = props.body;
1402
+ this.end_node = props.end_node;
1403
+ }
1404
+
1405
+ childNodes(): Node[] {
1406
+ return [
1407
+ ...this.body,
1408
+ this.end_node,
1409
+ ].filter(node => node !== null && node !== undefined) as Node[];
1410
+ }
1411
+
1412
+ recursiveErrors(): HerbError[] {
1413
+ return [
1414
+ ...this.errors,
1415
+ ...this.body.map(node => node.recursiveErrors()),
1416
+ this.end_node ? this.end_node.recursiveErrors() : [],
1417
+ ].flat();
1418
+ }
1419
+
1420
+ toJSON(): SerializedERBBlockNode {
1421
+ return {
1422
+ ...super.toJSON(),
1423
+ type: "AST_ERB_BLOCK_NODE",
1424
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
1425
+ content: this.content ? this.content.toJSON() : null,
1426
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
1427
+ body: this.body.map(node => node.toJSON()),
1428
+ end_node: this.end_node ? this.end_node.toJSON() : null,
1429
+ };
1430
+ }
1431
+
1432
+ treeInspect(): string {
1433
+ let output = "";
1434
+
1435
+ output += `@ ERBBlockNode ${this.location.treeInspectWithLabel()}\n`;
1436
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
1437
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
1438
+ output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
1439
+ output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
1440
+ output += `├── body: ${this.inspectArray(this.body, "│ ")}`;
1441
+ output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
1442
+
1443
+ // output += "\n";
1444
+
1445
+ return output
1446
+ }
1447
+ }
1448
+
1449
+ export interface SerializedERBWhenNode extends SerializedNode {
1450
+ type: "AST_ERB_WHEN_NODE";
1451
+ tag_opening: SerializedToken | null;
1452
+ content: SerializedToken | null;
1453
+ tag_closing: SerializedToken | null;
1454
+ statements: SerializedNode[];
1455
+ }
1456
+
1457
+ export interface ERBWhenNodeProps extends BaseNodeProps {
1458
+ tag_opening: Token | null;
1459
+ content: Token | null;
1460
+ tag_closing: Token | null;
1461
+ statements: Node[];
1462
+ }
1463
+
1464
+ export class ERBWhenNode extends Node {
1465
+ readonly tag_opening: Token | null;
1466
+ readonly content: Token | null;
1467
+ readonly tag_closing: Token | null;
1468
+ readonly statements: Node[];
1469
+
1470
+ static from(data: SerializedERBWhenNode): ERBWhenNode {
1471
+ return new ERBWhenNode({
1472
+ type: data.type,
1473
+ location: Location.from(data.location),
1474
+ errors: (data.errors || []).map(error => HerbError.from(error)),
1475
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
1476
+ content: data.content ? Token.from(data.content) : null,
1477
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
1478
+ statements: (data.statements || []).map(node => fromSerializedNode(node)),
1479
+ })
1480
+ }
1481
+
1482
+ constructor(props: ERBWhenNodeProps) {
1483
+ super(props.type, props.location, props.errors);
1484
+ this.tag_opening = props.tag_opening;
1485
+ this.content = props.content;
1486
+ this.tag_closing = props.tag_closing;
1487
+ this.statements = props.statements;
1488
+ }
1489
+
1490
+ childNodes(): Node[] {
1491
+ return [
1492
+ ...this.statements,
1493
+ ].filter(node => node !== null && node !== undefined) as Node[];
1494
+ }
1495
+
1496
+ recursiveErrors(): HerbError[] {
1497
+ return [
1498
+ ...this.errors,
1499
+ ...this.statements.map(node => node.recursiveErrors()),
1500
+ ].flat();
1501
+ }
1502
+
1503
+ toJSON(): SerializedERBWhenNode {
1504
+ return {
1505
+ ...super.toJSON(),
1506
+ type: "AST_ERB_WHEN_NODE",
1507
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
1508
+ content: this.content ? this.content.toJSON() : null,
1509
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
1510
+ statements: this.statements.map(node => node.toJSON()),
1511
+ };
1512
+ }
1513
+
1514
+ treeInspect(): string {
1515
+ let output = "";
1516
+
1517
+ output += `@ ERBWhenNode ${this.location.treeInspectWithLabel()}\n`;
1518
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
1519
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
1520
+ output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
1521
+ output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
1522
+ output += `└── statements: ${this.inspectArray(this.statements, " ")}`;
1523
+
1524
+ // output += "\n";
1525
+
1526
+ return output
1527
+ }
1528
+ }
1529
+
1530
+ export interface SerializedERBCaseNode extends SerializedNode {
1531
+ type: "AST_ERB_CASE_NODE";
1532
+ tag_opening: SerializedToken | null;
1533
+ content: SerializedToken | null;
1534
+ tag_closing: SerializedToken | null;
1535
+ children: SerializedNode[];
1536
+ conditions: SerializedNode[];
1537
+ else_clause: SerializedNode | null;
1538
+ end_node: SerializedNode | null;
1539
+ }
1540
+
1541
+ export interface ERBCaseNodeProps extends BaseNodeProps {
1542
+ tag_opening: Token | null;
1543
+ content: Token | null;
1544
+ tag_closing: Token | null;
1545
+ children: Node[];
1546
+ conditions: Node[];
1547
+ else_clause: Node | null;
1548
+ end_node: Node | null;
1549
+ }
1550
+
1551
+ export class ERBCaseNode extends Node {
1552
+ readonly tag_opening: Token | null;
1553
+ readonly content: Token | null;
1554
+ readonly tag_closing: Token | null;
1555
+ readonly children: Node[];
1556
+ readonly conditions: Node[];
1557
+ readonly else_clause: Node | null;
1558
+ readonly end_node: Node | null;
1559
+
1560
+ static from(data: SerializedERBCaseNode): ERBCaseNode {
1561
+ return new ERBCaseNode({
1562
+ type: data.type,
1563
+ location: Location.from(data.location),
1564
+ errors: (data.errors || []).map(error => HerbError.from(error)),
1565
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
1566
+ content: data.content ? Token.from(data.content) : null,
1567
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
1568
+ children: (data.children || []).map(node => fromSerializedNode(node)),
1569
+ conditions: (data.conditions || []).map(node => fromSerializedNode(node)),
1570
+ else_clause: data.else_clause ? fromSerializedNode((data.else_clause as any)) : null,
1571
+ end_node: data.end_node ? fromSerializedNode((data.end_node as any)) : null,
1572
+ })
1573
+ }
1574
+
1575
+ constructor(props: ERBCaseNodeProps) {
1576
+ super(props.type, props.location, props.errors);
1577
+ this.tag_opening = props.tag_opening;
1578
+ this.content = props.content;
1579
+ this.tag_closing = props.tag_closing;
1580
+ this.children = props.children;
1581
+ this.conditions = props.conditions;
1582
+ this.else_clause = props.else_clause;
1583
+ this.end_node = props.end_node;
1584
+ }
1585
+
1586
+ childNodes(): Node[] {
1587
+ return [
1588
+ ...this.children,
1589
+ ...this.conditions,
1590
+ this.else_clause,
1591
+ this.end_node,
1592
+ ].filter(node => node !== null && node !== undefined) as Node[];
1593
+ }
1594
+
1595
+ recursiveErrors(): HerbError[] {
1596
+ return [
1597
+ ...this.errors,
1598
+ ...this.children.map(node => node.recursiveErrors()),
1599
+ ...this.conditions.map(node => node.recursiveErrors()),
1600
+ this.else_clause ? this.else_clause.recursiveErrors() : [],
1601
+ this.end_node ? this.end_node.recursiveErrors() : [],
1602
+ ].flat();
1603
+ }
1604
+
1605
+ toJSON(): SerializedERBCaseNode {
1606
+ return {
1607
+ ...super.toJSON(),
1608
+ type: "AST_ERB_CASE_NODE",
1609
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
1610
+ content: this.content ? this.content.toJSON() : null,
1611
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
1612
+ children: this.children.map(node => node.toJSON()),
1613
+ conditions: this.conditions.map(node => node.toJSON()),
1614
+ else_clause: this.else_clause ? this.else_clause.toJSON() : null,
1615
+ end_node: this.end_node ? this.end_node.toJSON() : null,
1616
+ };
1617
+ }
1618
+
1619
+ treeInspect(): string {
1620
+ let output = "";
1621
+
1622
+ output += `@ ERBCaseNode ${this.location.treeInspectWithLabel()}\n`;
1623
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
1624
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
1625
+ output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
1626
+ output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
1627
+ output += `├── children: ${this.inspectArray(this.children, "│ ")}`;
1628
+ output += `├── conditions: ${this.inspectArray(this.conditions, "│ ")}`;
1629
+ output += `├── else_clause: ${this.inspectNode(this.else_clause, "│ ")}`;
1630
+ output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
1631
+
1632
+ // output += "\n";
1633
+
1634
+ return output
1635
+ }
1636
+ }
1637
+
1638
+ export interface SerializedERBWhileNode extends SerializedNode {
1639
+ type: "AST_ERB_WHILE_NODE";
1640
+ tag_opening: SerializedToken | null;
1641
+ content: SerializedToken | null;
1642
+ tag_closing: SerializedToken | null;
1643
+ statements: SerializedNode[];
1644
+ end_node: SerializedNode | null;
1645
+ }
1646
+
1647
+ export interface ERBWhileNodeProps extends BaseNodeProps {
1648
+ tag_opening: Token | null;
1649
+ content: Token | null;
1650
+ tag_closing: Token | null;
1651
+ statements: Node[];
1652
+ end_node: Node | null;
1653
+ }
1654
+
1655
+ export class ERBWhileNode extends Node {
1656
+ readonly tag_opening: Token | null;
1657
+ readonly content: Token | null;
1658
+ readonly tag_closing: Token | null;
1659
+ readonly statements: Node[];
1660
+ readonly end_node: Node | null;
1661
+
1662
+ static from(data: SerializedERBWhileNode): ERBWhileNode {
1663
+ return new ERBWhileNode({
1664
+ type: data.type,
1665
+ location: Location.from(data.location),
1666
+ errors: (data.errors || []).map(error => HerbError.from(error)),
1667
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
1668
+ content: data.content ? Token.from(data.content) : null,
1669
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
1670
+ statements: (data.statements || []).map(node => fromSerializedNode(node)),
1671
+ end_node: data.end_node ? fromSerializedNode((data.end_node as any)) : null,
1672
+ })
1673
+ }
1674
+
1675
+ constructor(props: ERBWhileNodeProps) {
1676
+ super(props.type, props.location, props.errors);
1677
+ this.tag_opening = props.tag_opening;
1678
+ this.content = props.content;
1679
+ this.tag_closing = props.tag_closing;
1680
+ this.statements = props.statements;
1681
+ this.end_node = props.end_node;
1682
+ }
1683
+
1684
+ childNodes(): Node[] {
1685
+ return [
1686
+ ...this.statements,
1687
+ this.end_node,
1688
+ ].filter(node => node !== null && node !== undefined) as Node[];
1689
+ }
1690
+
1691
+ recursiveErrors(): HerbError[] {
1692
+ return [
1693
+ ...this.errors,
1694
+ ...this.statements.map(node => node.recursiveErrors()),
1695
+ this.end_node ? this.end_node.recursiveErrors() : [],
1696
+ ].flat();
1697
+ }
1698
+
1699
+ toJSON(): SerializedERBWhileNode {
1700
+ return {
1701
+ ...super.toJSON(),
1702
+ type: "AST_ERB_WHILE_NODE",
1703
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
1704
+ content: this.content ? this.content.toJSON() : null,
1705
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
1706
+ statements: this.statements.map(node => node.toJSON()),
1707
+ end_node: this.end_node ? this.end_node.toJSON() : null,
1708
+ };
1709
+ }
1710
+
1711
+ treeInspect(): string {
1712
+ let output = "";
1713
+
1714
+ output += `@ ERBWhileNode ${this.location.treeInspectWithLabel()}\n`;
1715
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
1716
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
1717
+ output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
1718
+ output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
1719
+ output += `├── statements: ${this.inspectArray(this.statements, "│ ")}`;
1720
+ output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
1721
+
1722
+ // output += "\n";
1723
+
1724
+ return output
1725
+ }
1726
+ }
1727
+
1728
+ export interface SerializedERBUntilNode extends SerializedNode {
1729
+ type: "AST_ERB_UNTIL_NODE";
1730
+ tag_opening: SerializedToken | null;
1731
+ content: SerializedToken | null;
1732
+ tag_closing: SerializedToken | null;
1733
+ statements: SerializedNode[];
1734
+ end_node: SerializedNode | null;
1735
+ }
1736
+
1737
+ export interface ERBUntilNodeProps extends BaseNodeProps {
1738
+ tag_opening: Token | null;
1739
+ content: Token | null;
1740
+ tag_closing: Token | null;
1741
+ statements: Node[];
1742
+ end_node: Node | null;
1743
+ }
1744
+
1745
+ export class ERBUntilNode extends Node {
1746
+ readonly tag_opening: Token | null;
1747
+ readonly content: Token | null;
1748
+ readonly tag_closing: Token | null;
1749
+ readonly statements: Node[];
1750
+ readonly end_node: Node | null;
1751
+
1752
+ static from(data: SerializedERBUntilNode): ERBUntilNode {
1753
+ return new ERBUntilNode({
1754
+ type: data.type,
1755
+ location: Location.from(data.location),
1756
+ errors: (data.errors || []).map(error => HerbError.from(error)),
1757
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
1758
+ content: data.content ? Token.from(data.content) : null,
1759
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
1760
+ statements: (data.statements || []).map(node => fromSerializedNode(node)),
1761
+ end_node: data.end_node ? fromSerializedNode((data.end_node as any)) : null,
1762
+ })
1763
+ }
1764
+
1765
+ constructor(props: ERBUntilNodeProps) {
1766
+ super(props.type, props.location, props.errors);
1767
+ this.tag_opening = props.tag_opening;
1768
+ this.content = props.content;
1769
+ this.tag_closing = props.tag_closing;
1770
+ this.statements = props.statements;
1771
+ this.end_node = props.end_node;
1772
+ }
1773
+
1774
+ childNodes(): Node[] {
1775
+ return [
1776
+ ...this.statements,
1777
+ this.end_node,
1778
+ ].filter(node => node !== null && node !== undefined) as Node[];
1779
+ }
1780
+
1781
+ recursiveErrors(): HerbError[] {
1782
+ return [
1783
+ ...this.errors,
1784
+ ...this.statements.map(node => node.recursiveErrors()),
1785
+ this.end_node ? this.end_node.recursiveErrors() : [],
1786
+ ].flat();
1787
+ }
1788
+
1789
+ toJSON(): SerializedERBUntilNode {
1790
+ return {
1791
+ ...super.toJSON(),
1792
+ type: "AST_ERB_UNTIL_NODE",
1793
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
1794
+ content: this.content ? this.content.toJSON() : null,
1795
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
1796
+ statements: this.statements.map(node => node.toJSON()),
1797
+ end_node: this.end_node ? this.end_node.toJSON() : null,
1798
+ };
1799
+ }
1800
+
1801
+ treeInspect(): string {
1802
+ let output = "";
1803
+
1804
+ output += `@ ERBUntilNode ${this.location.treeInspectWithLabel()}\n`;
1805
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
1806
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
1807
+ output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
1808
+ output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
1809
+ output += `├── statements: ${this.inspectArray(this.statements, "│ ")}`;
1810
+ output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
1811
+
1812
+ // output += "\n";
1813
+
1814
+ return output
1815
+ }
1816
+ }
1817
+
1818
+ export interface SerializedERBForNode extends SerializedNode {
1819
+ type: "AST_ERB_FOR_NODE";
1820
+ tag_opening: SerializedToken | null;
1821
+ content: SerializedToken | null;
1822
+ tag_closing: SerializedToken | null;
1823
+ statements: SerializedNode[];
1824
+ end_node: SerializedNode | null;
1825
+ }
1826
+
1827
+ export interface ERBForNodeProps extends BaseNodeProps {
1828
+ tag_opening: Token | null;
1829
+ content: Token | null;
1830
+ tag_closing: Token | null;
1831
+ statements: Node[];
1832
+ end_node: Node | null;
1833
+ }
1834
+
1835
+ export class ERBForNode extends Node {
1836
+ readonly tag_opening: Token | null;
1837
+ readonly content: Token | null;
1838
+ readonly tag_closing: Token | null;
1839
+ readonly statements: Node[];
1840
+ readonly end_node: Node | null;
1841
+
1842
+ static from(data: SerializedERBForNode): ERBForNode {
1843
+ return new ERBForNode({
1844
+ type: data.type,
1845
+ location: Location.from(data.location),
1846
+ errors: (data.errors || []).map(error => HerbError.from(error)),
1847
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
1848
+ content: data.content ? Token.from(data.content) : null,
1849
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
1850
+ statements: (data.statements || []).map(node => fromSerializedNode(node)),
1851
+ end_node: data.end_node ? fromSerializedNode((data.end_node as any)) : null,
1852
+ })
1853
+ }
1854
+
1855
+ constructor(props: ERBForNodeProps) {
1856
+ super(props.type, props.location, props.errors);
1857
+ this.tag_opening = props.tag_opening;
1858
+ this.content = props.content;
1859
+ this.tag_closing = props.tag_closing;
1860
+ this.statements = props.statements;
1861
+ this.end_node = props.end_node;
1862
+ }
1863
+
1864
+ childNodes(): Node[] {
1865
+ return [
1866
+ ...this.statements,
1867
+ this.end_node,
1868
+ ].filter(node => node !== null && node !== undefined) as Node[];
1869
+ }
1870
+
1871
+ recursiveErrors(): HerbError[] {
1872
+ return [
1873
+ ...this.errors,
1874
+ ...this.statements.map(node => node.recursiveErrors()),
1875
+ this.end_node ? this.end_node.recursiveErrors() : [],
1876
+ ].flat();
1877
+ }
1878
+
1879
+ toJSON(): SerializedERBForNode {
1880
+ return {
1881
+ ...super.toJSON(),
1882
+ type: "AST_ERB_FOR_NODE",
1883
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
1884
+ content: this.content ? this.content.toJSON() : null,
1885
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
1886
+ statements: this.statements.map(node => node.toJSON()),
1887
+ end_node: this.end_node ? this.end_node.toJSON() : null,
1888
+ };
1889
+ }
1890
+
1891
+ treeInspect(): string {
1892
+ let output = "";
1893
+
1894
+ output += `@ ERBForNode ${this.location.treeInspectWithLabel()}\n`;
1895
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
1896
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
1897
+ output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
1898
+ output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
1899
+ output += `├── statements: ${this.inspectArray(this.statements, "│ ")}`;
1900
+ output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
1901
+
1902
+ // output += "\n";
1903
+
1904
+ return output
1905
+ }
1906
+ }
1907
+
1908
+ export interface SerializedERBRescueNode extends SerializedNode {
1909
+ type: "AST_ERB_RESCUE_NODE";
1910
+ tag_opening: SerializedToken | null;
1911
+ content: SerializedToken | null;
1912
+ tag_closing: SerializedToken | null;
1913
+ statements: SerializedNode[];
1914
+ subsequent: SerializedNode | null;
1915
+ }
1916
+
1917
+ export interface ERBRescueNodeProps extends BaseNodeProps {
1918
+ tag_opening: Token | null;
1919
+ content: Token | null;
1920
+ tag_closing: Token | null;
1921
+ statements: Node[];
1922
+ subsequent: Node | null;
1923
+ }
1924
+
1925
+ export class ERBRescueNode extends Node {
1926
+ readonly tag_opening: Token | null;
1927
+ readonly content: Token | null;
1928
+ readonly tag_closing: Token | null;
1929
+ readonly statements: Node[];
1930
+ readonly subsequent: Node | null;
1931
+
1932
+ static from(data: SerializedERBRescueNode): ERBRescueNode {
1933
+ return new ERBRescueNode({
1934
+ type: data.type,
1935
+ location: Location.from(data.location),
1936
+ errors: (data.errors || []).map(error => HerbError.from(error)),
1937
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
1938
+ content: data.content ? Token.from(data.content) : null,
1939
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
1940
+ statements: (data.statements || []).map(node => fromSerializedNode(node)),
1941
+ subsequent: data.subsequent ? fromSerializedNode((data.subsequent as any)) : null,
1942
+ })
1943
+ }
1944
+
1945
+ constructor(props: ERBRescueNodeProps) {
1946
+ super(props.type, props.location, props.errors);
1947
+ this.tag_opening = props.tag_opening;
1948
+ this.content = props.content;
1949
+ this.tag_closing = props.tag_closing;
1950
+ this.statements = props.statements;
1951
+ this.subsequent = props.subsequent;
1952
+ }
1953
+
1954
+ childNodes(): Node[] {
1955
+ return [
1956
+ ...this.statements,
1957
+ this.subsequent,
1958
+ ].filter(node => node !== null && node !== undefined) as Node[];
1959
+ }
1960
+
1961
+ recursiveErrors(): HerbError[] {
1962
+ return [
1963
+ ...this.errors,
1964
+ ...this.statements.map(node => node.recursiveErrors()),
1965
+ this.subsequent ? this.subsequent.recursiveErrors() : [],
1966
+ ].flat();
1967
+ }
1968
+
1969
+ toJSON(): SerializedERBRescueNode {
1970
+ return {
1971
+ ...super.toJSON(),
1972
+ type: "AST_ERB_RESCUE_NODE",
1973
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
1974
+ content: this.content ? this.content.toJSON() : null,
1975
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
1976
+ statements: this.statements.map(node => node.toJSON()),
1977
+ subsequent: this.subsequent ? this.subsequent.toJSON() : null,
1978
+ };
1979
+ }
1980
+
1981
+ treeInspect(): string {
1982
+ let output = "";
1983
+
1984
+ output += `@ ERBRescueNode ${this.location.treeInspectWithLabel()}\n`;
1985
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
1986
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
1987
+ output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
1988
+ output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
1989
+ output += `├── statements: ${this.inspectArray(this.statements, "│ ")}`;
1990
+ output += `└── subsequent: ${this.inspectNode(this.subsequent, " ")}`;
1991
+
1992
+ // output += "\n";
1993
+
1994
+ return output
1995
+ }
1996
+ }
1997
+
1998
+ export interface SerializedERBEnsureNode extends SerializedNode {
1999
+ type: "AST_ERB_ENSURE_NODE";
2000
+ tag_opening: SerializedToken | null;
2001
+ content: SerializedToken | null;
2002
+ tag_closing: SerializedToken | null;
2003
+ statements: SerializedNode[];
2004
+ }
2005
+
2006
+ export interface ERBEnsureNodeProps extends BaseNodeProps {
2007
+ tag_opening: Token | null;
2008
+ content: Token | null;
2009
+ tag_closing: Token | null;
2010
+ statements: Node[];
2011
+ }
2012
+
2013
+ export class ERBEnsureNode extends Node {
2014
+ readonly tag_opening: Token | null;
2015
+ readonly content: Token | null;
2016
+ readonly tag_closing: Token | null;
2017
+ readonly statements: Node[];
2018
+
2019
+ static from(data: SerializedERBEnsureNode): ERBEnsureNode {
2020
+ return new ERBEnsureNode({
2021
+ type: data.type,
2022
+ location: Location.from(data.location),
2023
+ errors: (data.errors || []).map(error => HerbError.from(error)),
2024
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
2025
+ content: data.content ? Token.from(data.content) : null,
2026
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
2027
+ statements: (data.statements || []).map(node => fromSerializedNode(node)),
2028
+ })
2029
+ }
2030
+
2031
+ constructor(props: ERBEnsureNodeProps) {
2032
+ super(props.type, props.location, props.errors);
2033
+ this.tag_opening = props.tag_opening;
2034
+ this.content = props.content;
2035
+ this.tag_closing = props.tag_closing;
2036
+ this.statements = props.statements;
2037
+ }
2038
+
2039
+ childNodes(): Node[] {
2040
+ return [
2041
+ ...this.statements,
2042
+ ].filter(node => node !== null && node !== undefined) as Node[];
2043
+ }
2044
+
2045
+ recursiveErrors(): HerbError[] {
2046
+ return [
2047
+ ...this.errors,
2048
+ ...this.statements.map(node => node.recursiveErrors()),
2049
+ ].flat();
2050
+ }
2051
+
2052
+ toJSON(): SerializedERBEnsureNode {
2053
+ return {
2054
+ ...super.toJSON(),
2055
+ type: "AST_ERB_ENSURE_NODE",
2056
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
2057
+ content: this.content ? this.content.toJSON() : null,
2058
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
2059
+ statements: this.statements.map(node => node.toJSON()),
2060
+ };
2061
+ }
2062
+
2063
+ treeInspect(): string {
2064
+ let output = "";
2065
+
2066
+ output += `@ ERBEnsureNode ${this.location.treeInspectWithLabel()}\n`;
2067
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
2068
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
2069
+ output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
2070
+ output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
2071
+ output += `└── statements: ${this.inspectArray(this.statements, " ")}`;
2072
+
2073
+ // output += "\n";
2074
+
2075
+ return output
2076
+ }
2077
+ }
2078
+
2079
+ export interface SerializedERBBeginNode extends SerializedNode {
2080
+ type: "AST_ERB_BEGIN_NODE";
2081
+ tag_opening: SerializedToken | null;
2082
+ content: SerializedToken | null;
2083
+ tag_closing: SerializedToken | null;
2084
+ statements: SerializedNode[];
2085
+ rescue_clause: SerializedNode | null;
2086
+ else_clause: SerializedNode | null;
2087
+ ensure_clause: SerializedNode | null;
2088
+ end_node: SerializedNode | null;
2089
+ }
2090
+
2091
+ export interface ERBBeginNodeProps extends BaseNodeProps {
2092
+ tag_opening: Token | null;
2093
+ content: Token | null;
2094
+ tag_closing: Token | null;
2095
+ statements: Node[];
2096
+ rescue_clause: Node | null;
2097
+ else_clause: Node | null;
2098
+ ensure_clause: Node | null;
2099
+ end_node: Node | null;
2100
+ }
2101
+
2102
+ export class ERBBeginNode extends Node {
2103
+ readonly tag_opening: Token | null;
2104
+ readonly content: Token | null;
2105
+ readonly tag_closing: Token | null;
2106
+ readonly statements: Node[];
2107
+ readonly rescue_clause: Node | null;
2108
+ readonly else_clause: Node | null;
2109
+ readonly ensure_clause: Node | null;
2110
+ readonly end_node: Node | null;
2111
+
2112
+ static from(data: SerializedERBBeginNode): ERBBeginNode {
2113
+ return new ERBBeginNode({
2114
+ type: data.type,
2115
+ location: Location.from(data.location),
2116
+ errors: (data.errors || []).map(error => HerbError.from(error)),
2117
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
2118
+ content: data.content ? Token.from(data.content) : null,
2119
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
2120
+ statements: (data.statements || []).map(node => fromSerializedNode(node)),
2121
+ rescue_clause: data.rescue_clause ? fromSerializedNode((data.rescue_clause as any)) : null,
2122
+ else_clause: data.else_clause ? fromSerializedNode((data.else_clause as any)) : null,
2123
+ ensure_clause: data.ensure_clause ? fromSerializedNode((data.ensure_clause as any)) : null,
2124
+ end_node: data.end_node ? fromSerializedNode((data.end_node as any)) : null,
2125
+ })
2126
+ }
2127
+
2128
+ constructor(props: ERBBeginNodeProps) {
2129
+ super(props.type, props.location, props.errors);
2130
+ this.tag_opening = props.tag_opening;
2131
+ this.content = props.content;
2132
+ this.tag_closing = props.tag_closing;
2133
+ this.statements = props.statements;
2134
+ this.rescue_clause = props.rescue_clause;
2135
+ this.else_clause = props.else_clause;
2136
+ this.ensure_clause = props.ensure_clause;
2137
+ this.end_node = props.end_node;
2138
+ }
2139
+
2140
+ childNodes(): Node[] {
2141
+ return [
2142
+ ...this.statements,
2143
+ this.rescue_clause,
2144
+ this.else_clause,
2145
+ this.ensure_clause,
2146
+ this.end_node,
2147
+ ].filter(node => node !== null && node !== undefined) as Node[];
2148
+ }
2149
+
2150
+ recursiveErrors(): HerbError[] {
2151
+ return [
2152
+ ...this.errors,
2153
+ ...this.statements.map(node => node.recursiveErrors()),
2154
+ this.rescue_clause ? this.rescue_clause.recursiveErrors() : [],
2155
+ this.else_clause ? this.else_clause.recursiveErrors() : [],
2156
+ this.ensure_clause ? this.ensure_clause.recursiveErrors() : [],
2157
+ this.end_node ? this.end_node.recursiveErrors() : [],
2158
+ ].flat();
2159
+ }
2160
+
2161
+ toJSON(): SerializedERBBeginNode {
2162
+ return {
2163
+ ...super.toJSON(),
2164
+ type: "AST_ERB_BEGIN_NODE",
2165
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
2166
+ content: this.content ? this.content.toJSON() : null,
2167
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
2168
+ statements: this.statements.map(node => node.toJSON()),
2169
+ rescue_clause: this.rescue_clause ? this.rescue_clause.toJSON() : null,
2170
+ else_clause: this.else_clause ? this.else_clause.toJSON() : null,
2171
+ ensure_clause: this.ensure_clause ? this.ensure_clause.toJSON() : null,
2172
+ end_node: this.end_node ? this.end_node.toJSON() : null,
2173
+ };
2174
+ }
2175
+
2176
+ treeInspect(): string {
2177
+ let output = "";
2178
+
2179
+ output += `@ ERBBeginNode ${this.location.treeInspectWithLabel()}\n`;
2180
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
2181
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
2182
+ output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
2183
+ output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
2184
+ output += `├── statements: ${this.inspectArray(this.statements, "│ ")}`;
2185
+ output += `├── rescue_clause: ${this.inspectNode(this.rescue_clause, "│ ")}`;
2186
+ output += `├── else_clause: ${this.inspectNode(this.else_clause, "│ ")}`;
2187
+ output += `├── ensure_clause: ${this.inspectNode(this.ensure_clause, "│ ")}`;
2188
+ output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
2189
+
2190
+ // output += "\n";
2191
+
2192
+ return output
2193
+ }
2194
+ }
2195
+
2196
+ export interface SerializedERBUnlessNode extends SerializedNode {
2197
+ type: "AST_ERB_UNLESS_NODE";
2198
+ tag_opening: SerializedToken | null;
2199
+ content: SerializedToken | null;
2200
+ tag_closing: SerializedToken | null;
2201
+ statements: SerializedNode[];
2202
+ else_clause: SerializedNode | null;
2203
+ end_node: SerializedNode | null;
2204
+ }
2205
+
2206
+ export interface ERBUnlessNodeProps extends BaseNodeProps {
2207
+ tag_opening: Token | null;
2208
+ content: Token | null;
2209
+ tag_closing: Token | null;
2210
+ statements: Node[];
2211
+ else_clause: Node | null;
2212
+ end_node: Node | null;
2213
+ }
2214
+
2215
+ export class ERBUnlessNode extends Node {
2216
+ readonly tag_opening: Token | null;
2217
+ readonly content: Token | null;
2218
+ readonly tag_closing: Token | null;
2219
+ readonly statements: Node[];
2220
+ readonly else_clause: Node | null;
2221
+ readonly end_node: Node | null;
2222
+
2223
+ static from(data: SerializedERBUnlessNode): ERBUnlessNode {
2224
+ return new ERBUnlessNode({
2225
+ type: data.type,
2226
+ location: Location.from(data.location),
2227
+ errors: (data.errors || []).map(error => HerbError.from(error)),
2228
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
2229
+ content: data.content ? Token.from(data.content) : null,
2230
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
2231
+ statements: (data.statements || []).map(node => fromSerializedNode(node)),
2232
+ else_clause: data.else_clause ? fromSerializedNode((data.else_clause as any)) : null,
2233
+ end_node: data.end_node ? fromSerializedNode((data.end_node as any)) : null,
2234
+ })
2235
+ }
2236
+
2237
+ constructor(props: ERBUnlessNodeProps) {
2238
+ super(props.type, props.location, props.errors);
2239
+ this.tag_opening = props.tag_opening;
2240
+ this.content = props.content;
2241
+ this.tag_closing = props.tag_closing;
2242
+ this.statements = props.statements;
2243
+ this.else_clause = props.else_clause;
2244
+ this.end_node = props.end_node;
2245
+ }
2246
+
2247
+ childNodes(): Node[] {
2248
+ return [
2249
+ ...this.statements,
2250
+ this.else_clause,
2251
+ this.end_node,
2252
+ ].filter(node => node !== null && node !== undefined) as Node[];
2253
+ }
2254
+
2255
+ recursiveErrors(): HerbError[] {
2256
+ return [
2257
+ ...this.errors,
2258
+ ...this.statements.map(node => node.recursiveErrors()),
2259
+ this.else_clause ? this.else_clause.recursiveErrors() : [],
2260
+ this.end_node ? this.end_node.recursiveErrors() : [],
2261
+ ].flat();
2262
+ }
2263
+
2264
+ toJSON(): SerializedERBUnlessNode {
2265
+ return {
2266
+ ...super.toJSON(),
2267
+ type: "AST_ERB_UNLESS_NODE",
2268
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
2269
+ content: this.content ? this.content.toJSON() : null,
2270
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
2271
+ statements: this.statements.map(node => node.toJSON()),
2272
+ else_clause: this.else_clause ? this.else_clause.toJSON() : null,
2273
+ end_node: this.end_node ? this.end_node.toJSON() : null,
2274
+ };
2275
+ }
2276
+
2277
+ treeInspect(): string {
2278
+ let output = "";
2279
+
2280
+ output += `@ ERBUnlessNode ${this.location.treeInspectWithLabel()}\n`;
2281
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
2282
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
2283
+ output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
2284
+ output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
2285
+ output += `├── statements: ${this.inspectArray(this.statements, "│ ")}`;
2286
+ output += `├── else_clause: ${this.inspectNode(this.else_clause, "│ ")}`;
2287
+ output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
2288
+
2289
+ // output += "\n";
2290
+
2291
+ return output
2292
+ }
2293
+ }
2294
+