@herb-tools/core 0.8.9 → 0.9.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.
- package/dist/herb-core.browser.js +22025 -129
- package/dist/herb-core.browser.js.map +1 -1
- package/dist/herb-core.cjs +22100 -130
- package/dist/herb-core.cjs.map +1 -1
- package/dist/herb-core.esm.js +22025 -129
- package/dist/herb-core.esm.js.map +1 -1
- package/dist/herb-core.umd.js +22100 -130
- package/dist/herb-core.umd.js.map +1 -1
- package/dist/types/ast-utils.d.ts +185 -3
- package/dist/types/backend.d.ts +6 -6
- package/dist/types/errors.d.ts +267 -25
- package/dist/types/extract-ruby-options.d.ts +6 -0
- package/dist/types/herb-backend.d.ts +15 -7
- package/dist/types/index.d.ts +2 -0
- package/dist/types/node-type-guards.d.ts +95 -32
- package/dist/types/nodes.d.ts +354 -49
- package/dist/types/parse-result.d.ts +7 -1
- package/dist/types/parser-options.d.ts +30 -2
- package/dist/types/prism/index.d.ts +28 -0
- package/dist/types/prism/inspect.d.ts +3 -0
- package/dist/types/util.d.ts +0 -1
- package/dist/types/visitor.d.ts +15 -1
- package/package.json +4 -1
- package/src/ast-utils.ts +564 -7
- package/src/backend.ts +7 -7
- package/src/errors.ts +830 -76
- package/src/extract-ruby-options.ts +11 -0
- package/src/herb-backend.ts +30 -15
- package/src/index.ts +2 -0
- package/src/node-type-guards.ts +240 -33
- package/src/nodes.ts +1081 -192
- package/src/parse-result.ts +11 -0
- package/src/parser-options.ts +56 -2
- package/src/prism/index.ts +44 -0
- package/src/prism/inspect.ts +118 -0
- package/src/util.ts +0 -12
- package/src/visitor.ts +51 -1
package/src/parse-result.ts
CHANGED
|
@@ -3,10 +3,12 @@ import { Result } from "./result.js"
|
|
|
3
3
|
import { DocumentNode } from "./nodes.js"
|
|
4
4
|
import { HerbError } from "./errors.js"
|
|
5
5
|
import { HerbWarning } from "./warning.js"
|
|
6
|
+
import { ParserOptions } from "./parser-options.js"
|
|
6
7
|
|
|
7
8
|
import type { SerializedHerbError } from "./errors.js"
|
|
8
9
|
import type { SerializedHerbWarning } from "./warning.js"
|
|
9
10
|
import type { SerializedDocumentNode } from "./nodes.js"
|
|
11
|
+
import type { SerializedParserOptions } from "./parser-options.js"
|
|
10
12
|
|
|
11
13
|
import type { Visitor } from "./visitor.js"
|
|
12
14
|
|
|
@@ -15,6 +17,7 @@ export type SerializedParseResult = {
|
|
|
15
17
|
source: string
|
|
16
18
|
warnings: SerializedHerbWarning[]
|
|
17
19
|
errors: SerializedHerbError[]
|
|
20
|
+
options: SerializedParserOptions
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
/**
|
|
@@ -25,6 +28,9 @@ export class ParseResult extends Result {
|
|
|
25
28
|
/** The document node generated from the source code. */
|
|
26
29
|
readonly value: DocumentNode
|
|
27
30
|
|
|
31
|
+
/** The parser options used during parsing. */
|
|
32
|
+
readonly options: ParserOptions
|
|
33
|
+
|
|
28
34
|
/**
|
|
29
35
|
* Creates a `ParseResult` instance from a serialized result.
|
|
30
36
|
* @param result - The serialized parse result containing the value and source.
|
|
@@ -36,6 +42,7 @@ export class ParseResult extends Result {
|
|
|
36
42
|
result.source,
|
|
37
43
|
result.warnings.map((warning) => HerbWarning.from(warning)),
|
|
38
44
|
result.errors.map((error) => HerbError.from(error)),
|
|
45
|
+
ParserOptions.from(result.options),
|
|
39
46
|
)
|
|
40
47
|
}
|
|
41
48
|
|
|
@@ -45,15 +52,19 @@ export class ParseResult extends Result {
|
|
|
45
52
|
* @param source - The source code that was parsed.
|
|
46
53
|
* @param warnings - An array of warnings encountered during parsing.
|
|
47
54
|
* @param errors - An array of errors encountered during parsing.
|
|
55
|
+
* @param options - The parser options used during parsing.
|
|
48
56
|
*/
|
|
49
57
|
constructor(
|
|
50
58
|
value: DocumentNode,
|
|
51
59
|
source: string,
|
|
52
60
|
warnings: HerbWarning[] = [],
|
|
53
61
|
errors: HerbError[] = [],
|
|
62
|
+
options: ParserOptions = new ParserOptions(),
|
|
54
63
|
) {
|
|
55
64
|
super(source, warnings, errors)
|
|
56
65
|
this.value = value
|
|
66
|
+
this.options = options
|
|
67
|
+
this.value.setSource(source)
|
|
57
68
|
}
|
|
58
69
|
|
|
59
70
|
/**
|
package/src/parser-options.ts
CHANGED
|
@@ -1,7 +1,61 @@
|
|
|
1
|
-
export interface
|
|
1
|
+
export interface ParseOptions {
|
|
2
2
|
track_whitespace?: boolean
|
|
3
|
+
analyze?: boolean
|
|
4
|
+
strict?: boolean
|
|
5
|
+
action_view_helpers?: boolean
|
|
6
|
+
prism_nodes?: boolean
|
|
7
|
+
prism_nodes_deep?: boolean
|
|
8
|
+
prism_program?: boolean
|
|
3
9
|
}
|
|
4
10
|
|
|
5
|
-
export
|
|
11
|
+
export type SerializedParserOptions = Required<ParseOptions>
|
|
12
|
+
|
|
13
|
+
export const DEFAULT_PARSER_OPTIONS: SerializedParserOptions = {
|
|
6
14
|
track_whitespace: false,
|
|
15
|
+
analyze: true,
|
|
16
|
+
strict: true,
|
|
17
|
+
action_view_helpers: false,
|
|
18
|
+
prism_nodes: false,
|
|
19
|
+
prism_nodes_deep: false,
|
|
20
|
+
prism_program: false,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Represents the parser options used during parsing.
|
|
25
|
+
*/
|
|
26
|
+
export class ParserOptions {
|
|
27
|
+
/** Whether strict mode was enabled during parsing. */
|
|
28
|
+
readonly strict: boolean
|
|
29
|
+
|
|
30
|
+
/** Whether whitespace tracking was enabled during parsing. */
|
|
31
|
+
readonly track_whitespace: boolean
|
|
32
|
+
|
|
33
|
+
/** Whether analysis was performed during parsing. */
|
|
34
|
+
readonly analyze: boolean
|
|
35
|
+
|
|
36
|
+
/** Whether ActionView tag helper transformation was enabled during parsing. */
|
|
37
|
+
readonly action_view_helpers: boolean
|
|
38
|
+
|
|
39
|
+
/** Whether Prism node serialization was enabled during parsing. */
|
|
40
|
+
readonly prism_nodes: boolean
|
|
41
|
+
|
|
42
|
+
/** Whether deep Prism node serialization was enabled during parsing. */
|
|
43
|
+
readonly prism_nodes_deep: boolean
|
|
44
|
+
|
|
45
|
+
/** Whether the full Prism ProgramNode was serialized on the DocumentNode. */
|
|
46
|
+
readonly prism_program: boolean
|
|
47
|
+
|
|
48
|
+
static from(options: SerializedParserOptions): ParserOptions {
|
|
49
|
+
return new ParserOptions(options)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
constructor(options: ParseOptions = {}) {
|
|
53
|
+
this.strict = options.strict ?? DEFAULT_PARSER_OPTIONS.strict
|
|
54
|
+
this.track_whitespace = options.track_whitespace ?? DEFAULT_PARSER_OPTIONS.track_whitespace
|
|
55
|
+
this.analyze = options.analyze ?? DEFAULT_PARSER_OPTIONS.analyze
|
|
56
|
+
this.action_view_helpers = options.action_view_helpers ?? DEFAULT_PARSER_OPTIONS.action_view_helpers
|
|
57
|
+
this.prism_nodes = options.prism_nodes ?? DEFAULT_PARSER_OPTIONS.prism_nodes
|
|
58
|
+
this.prism_nodes_deep = options.prism_nodes_deep ?? DEFAULT_PARSER_OPTIONS.prism_nodes_deep
|
|
59
|
+
this.prism_program = options.prism_program ?? DEFAULT_PARSER_OPTIONS.prism_program
|
|
60
|
+
}
|
|
7
61
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { deserialize } from "@ruby/prism/src/deserialize.js"
|
|
2
|
+
import type { ParseResult as PrismParseResult } from "@ruby/prism/src/deserialize.js"
|
|
3
|
+
|
|
4
|
+
export * as PrismNodes from "@ruby/prism/src/nodes.js"
|
|
5
|
+
|
|
6
|
+
export { Visitor as PrismVisitor, BasicVisitor as PrismBasicVisitor } from "@ruby/prism/src/visitor.js"
|
|
7
|
+
|
|
8
|
+
export type PrismNode = any
|
|
9
|
+
export type PrismLocation = { startOffset: number; length: number }
|
|
10
|
+
export type { PrismParseResult }
|
|
11
|
+
|
|
12
|
+
export { inspectPrismNode, inspectPrismSerialized } from "./inspect.js"
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Deserialize a Prism parse result from the raw bytes produced by pm_serialize().
|
|
16
|
+
*
|
|
17
|
+
* @param bytes - The serialized bytes (from prism_serialized field on ERB nodes)
|
|
18
|
+
* @param source - The original source string that was parsed
|
|
19
|
+
* @returns The deserialized Prism ParseResult containing the AST
|
|
20
|
+
*/
|
|
21
|
+
export function deserializePrismParseResult(bytes: Uint8Array, source: string): PrismParseResult {
|
|
22
|
+
const sourceBytes = new TextEncoder().encode(source)
|
|
23
|
+
|
|
24
|
+
return deserialize(sourceBytes, bytes)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Deserialize a Prism node from the raw bytes produced by pm_serialize().
|
|
29
|
+
* pm_serialize() serializes a single node subtree, so the ParseResult's
|
|
30
|
+
* value is the Prism node directly (not wrapped in ProgramNode).
|
|
31
|
+
*
|
|
32
|
+
* @param bytes - The serialized bytes (from prism_serialized field on ERB nodes)
|
|
33
|
+
* @param source - The original source string that was parsed
|
|
34
|
+
* @returns The Prism node, or null if deserialization fails
|
|
35
|
+
*/
|
|
36
|
+
export function deserializePrismNode(bytes: Uint8Array, source: string): PrismNode | null {
|
|
37
|
+
try {
|
|
38
|
+
const result = deserializePrismParseResult(bytes, source)
|
|
39
|
+
|
|
40
|
+
return result.value ?? null
|
|
41
|
+
} catch {
|
|
42
|
+
return null
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { deserializePrismNode } from "./index.js"
|
|
2
|
+
|
|
3
|
+
import type { PrismLocation } from "./index.js"
|
|
4
|
+
import type { PrismNode } from "./index.js"
|
|
5
|
+
|
|
6
|
+
function offsetToLineColumn(source: string, offset: number): string {
|
|
7
|
+
let line = 1
|
|
8
|
+
let column = 0
|
|
9
|
+
|
|
10
|
+
for (let i = 0; i < offset && i < source.length; i++) {
|
|
11
|
+
if (source[i] === "\n") {
|
|
12
|
+
line++
|
|
13
|
+
column = 0
|
|
14
|
+
} else {
|
|
15
|
+
column++
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return `${line}:${column}`
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function formatLocation(location: PrismLocation, source: string): string {
|
|
23
|
+
const start = offsetToLineColumn(source, location.startOffset)
|
|
24
|
+
const end = offsetToLineColumn(source, location.startOffset + location.length)
|
|
25
|
+
|
|
26
|
+
return `(${start})-(${end})`
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function isPrismNode(value: any): boolean {
|
|
30
|
+
return value && typeof value === "object" && typeof value.toJSON === "function" && value.location
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function inspectPrismNode(node: PrismNode, source: string, prefix: string = ""): string {
|
|
34
|
+
if (!node) return "∅\n"
|
|
35
|
+
|
|
36
|
+
const nodeName = typeof node.toJSON === "function" ? node.toJSON().type : node.constructor.name
|
|
37
|
+
let output = ""
|
|
38
|
+
|
|
39
|
+
output += `@ ${nodeName}`
|
|
40
|
+
|
|
41
|
+
if (node.location) {
|
|
42
|
+
output += ` (location: ${formatLocation(node.location, source)})`
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
output += "\n"
|
|
46
|
+
|
|
47
|
+
const fields = getNodeFields(node)
|
|
48
|
+
|
|
49
|
+
fields.forEach((field, index) => {
|
|
50
|
+
const isLastField = index === fields.length - 1
|
|
51
|
+
const symbol = isLastField ? "└── " : "├── "
|
|
52
|
+
const childPrefix = prefix + (isLastField ? " " : "│ ")
|
|
53
|
+
const value = node[field]
|
|
54
|
+
|
|
55
|
+
if (value === null || value === undefined) {
|
|
56
|
+
output += `${prefix}${symbol}${field}: ∅\n`
|
|
57
|
+
} else if (typeof value === "string") {
|
|
58
|
+
output += `${prefix}${symbol}${field}: ${JSON.stringify(value)}\n`
|
|
59
|
+
} else if (typeof value === "number" || typeof value === "boolean") {
|
|
60
|
+
output += `${prefix}${symbol}${field}: ${value}\n`
|
|
61
|
+
} else if (Array.isArray(value)) {
|
|
62
|
+
output += `${prefix}${symbol}${field}: `
|
|
63
|
+
|
|
64
|
+
if (value.length === 0) {
|
|
65
|
+
output += "[]\n"
|
|
66
|
+
} else {
|
|
67
|
+
output += `(${value.length} item${value.length === 1 ? "" : "s"})\n`
|
|
68
|
+
|
|
69
|
+
value.forEach((item: any, i: number) => {
|
|
70
|
+
const isLastItem = i === value.length - 1
|
|
71
|
+
const itemSymbol = isLastItem ? "└── " : "├── "
|
|
72
|
+
const itemPrefix = childPrefix + (isLastItem ? " " : "│ ")
|
|
73
|
+
|
|
74
|
+
if (isPrismNode(item)) {
|
|
75
|
+
output += `${childPrefix}${itemSymbol}${inspectPrismNode(item, source, itemPrefix).trimStart()}`
|
|
76
|
+
} else {
|
|
77
|
+
output += `${childPrefix}${itemSymbol}${item}\n`
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
} else if (isPrismNode(value)) {
|
|
82
|
+
output += `${prefix}${symbol}${field}:\n`
|
|
83
|
+
output += `${childPrefix}└── ${inspectPrismNode(value, source, childPrefix + " ").trimStart()}`
|
|
84
|
+
} else if (typeof value === "object" && value.startOffset !== undefined) {
|
|
85
|
+
output += `${prefix}${symbol}${field}: (location: ${formatLocation(value, source)})\n`
|
|
86
|
+
} else if (typeof value === "object" && "value" in value && "encoding" in value) {
|
|
87
|
+
output += `${prefix}${symbol}${field}: ${JSON.stringify(value.value)}\n`
|
|
88
|
+
} else {
|
|
89
|
+
output += `${prefix}${symbol}${field}: ${String(value)}\n`
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
return output
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function getNodeFields(node: PrismNode): string[] {
|
|
97
|
+
const skip = new Set(["nodeID", "location", "flags"])
|
|
98
|
+
const fields: string[] = []
|
|
99
|
+
|
|
100
|
+
for (const key of Object.keys(node)) {
|
|
101
|
+
if (!skip.has(key)) {
|
|
102
|
+
fields.push(key)
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return fields
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function inspectPrismSerialized(bytes: Uint8Array, source: string, prefix: string = ""): string {
|
|
110
|
+
try {
|
|
111
|
+
const node = deserializePrismNode(bytes, source)
|
|
112
|
+
if (!node) return "∅"
|
|
113
|
+
|
|
114
|
+
return "\n" + prefix + "└── " + inspectPrismNode(node, source, prefix + " ").trimStart().trimEnd()
|
|
115
|
+
} catch {
|
|
116
|
+
return `(${bytes.length} bytes, deserialize error)`
|
|
117
|
+
}
|
|
118
|
+
}
|
package/src/util.ts
CHANGED
|
@@ -5,15 +5,3 @@ export function ensureString(object: any): string {
|
|
|
5
5
|
|
|
6
6
|
throw new TypeError("Argument must be a string")
|
|
7
7
|
}
|
|
8
|
-
|
|
9
|
-
export function convertToUTF8(string: string) {
|
|
10
|
-
const bytes = []
|
|
11
|
-
|
|
12
|
-
for (let i = 0; i < string.length; i++) {
|
|
13
|
-
bytes.push(string.charCodeAt(i))
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const decoder = new TextDecoder("utf-8")
|
|
17
|
-
|
|
18
|
-
return decoder.decode(new Uint8Array(bytes))
|
|
19
|
-
}
|
package/src/visitor.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
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-0.
|
|
2
|
+
// be modified manually. See /Users/marcoroth/Development/herb-release-0.9.0/templates/javascript/packages/core/src/visitor.ts.erb
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
Node,
|
|
@@ -7,11 +7,18 @@ import {
|
|
|
7
7
|
DocumentNode,
|
|
8
8
|
LiteralNode,
|
|
9
9
|
HTMLOpenTagNode,
|
|
10
|
+
HTMLConditionalOpenTagNode,
|
|
10
11
|
HTMLCloseTagNode,
|
|
12
|
+
HTMLOmittedCloseTagNode,
|
|
13
|
+
HTMLVirtualCloseTagNode,
|
|
11
14
|
HTMLElementNode,
|
|
15
|
+
HTMLConditionalElementNode,
|
|
12
16
|
HTMLAttributeValueNode,
|
|
13
17
|
HTMLAttributeNameNode,
|
|
14
18
|
HTMLAttributeNode,
|
|
19
|
+
RubyLiteralNode,
|
|
20
|
+
RubyHTMLAttributesSplatNode,
|
|
21
|
+
ERBOpenTagNode,
|
|
15
22
|
HTMLTextNode,
|
|
16
23
|
HTMLCommentNode,
|
|
17
24
|
HTMLDoctypeNode,
|
|
@@ -48,11 +55,18 @@ export interface IVisitor {
|
|
|
48
55
|
visitDocumentNode(node: DocumentNode): void
|
|
49
56
|
visitLiteralNode(node: LiteralNode): void
|
|
50
57
|
visitHTMLOpenTagNode(node: HTMLOpenTagNode): void
|
|
58
|
+
visitHTMLConditionalOpenTagNode(node: HTMLConditionalOpenTagNode): void
|
|
51
59
|
visitHTMLCloseTagNode(node: HTMLCloseTagNode): void
|
|
60
|
+
visitHTMLOmittedCloseTagNode(node: HTMLOmittedCloseTagNode): void
|
|
61
|
+
visitHTMLVirtualCloseTagNode(node: HTMLVirtualCloseTagNode): void
|
|
52
62
|
visitHTMLElementNode(node: HTMLElementNode): void
|
|
63
|
+
visitHTMLConditionalElementNode(node: HTMLConditionalElementNode): void
|
|
53
64
|
visitHTMLAttributeValueNode(node: HTMLAttributeValueNode): void
|
|
54
65
|
visitHTMLAttributeNameNode(node: HTMLAttributeNameNode): void
|
|
55
66
|
visitHTMLAttributeNode(node: HTMLAttributeNode): void
|
|
67
|
+
visitRubyLiteralNode(node: RubyLiteralNode): void
|
|
68
|
+
visitRubyHTMLAttributesSplatNode(node: RubyHTMLAttributesSplatNode): void
|
|
69
|
+
visitERBOpenTagNode(node: ERBOpenTagNode): void
|
|
56
70
|
visitHTMLTextNode(node: HTMLTextNode): void
|
|
57
71
|
visitHTMLCommentNode(node: HTMLCommentNode): void
|
|
58
72
|
visitHTMLDoctypeNode(node: HTMLDoctypeNode): void
|
|
@@ -118,16 +132,36 @@ export class Visitor implements IVisitor {
|
|
|
118
132
|
this.visitChildNodes(node)
|
|
119
133
|
}
|
|
120
134
|
|
|
135
|
+
visitHTMLConditionalOpenTagNode(node: HTMLConditionalOpenTagNode): void {
|
|
136
|
+
this.visitNode(node)
|
|
137
|
+
this.visitChildNodes(node)
|
|
138
|
+
}
|
|
139
|
+
|
|
121
140
|
visitHTMLCloseTagNode(node: HTMLCloseTagNode): void {
|
|
122
141
|
this.visitNode(node)
|
|
123
142
|
this.visitChildNodes(node)
|
|
124
143
|
}
|
|
125
144
|
|
|
145
|
+
visitHTMLOmittedCloseTagNode(node: HTMLOmittedCloseTagNode): void {
|
|
146
|
+
this.visitNode(node)
|
|
147
|
+
this.visitChildNodes(node)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
visitHTMLVirtualCloseTagNode(node: HTMLVirtualCloseTagNode): void {
|
|
151
|
+
this.visitNode(node)
|
|
152
|
+
this.visitChildNodes(node)
|
|
153
|
+
}
|
|
154
|
+
|
|
126
155
|
visitHTMLElementNode(node: HTMLElementNode): void {
|
|
127
156
|
this.visitNode(node)
|
|
128
157
|
this.visitChildNodes(node)
|
|
129
158
|
}
|
|
130
159
|
|
|
160
|
+
visitHTMLConditionalElementNode(node: HTMLConditionalElementNode): void {
|
|
161
|
+
this.visitNode(node)
|
|
162
|
+
this.visitChildNodes(node)
|
|
163
|
+
}
|
|
164
|
+
|
|
131
165
|
visitHTMLAttributeValueNode(node: HTMLAttributeValueNode): void {
|
|
132
166
|
this.visitNode(node)
|
|
133
167
|
this.visitChildNodes(node)
|
|
@@ -143,6 +177,22 @@ export class Visitor implements IVisitor {
|
|
|
143
177
|
this.visitChildNodes(node)
|
|
144
178
|
}
|
|
145
179
|
|
|
180
|
+
visitRubyLiteralNode(node: RubyLiteralNode): void {
|
|
181
|
+
this.visitNode(node)
|
|
182
|
+
this.visitChildNodes(node)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
visitRubyHTMLAttributesSplatNode(node: RubyHTMLAttributesSplatNode): void {
|
|
186
|
+
this.visitNode(node)
|
|
187
|
+
this.visitChildNodes(node)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
visitERBOpenTagNode(node: ERBOpenTagNode): void {
|
|
191
|
+
this.visitNode(node)
|
|
192
|
+
this.visitERBNode(node)
|
|
193
|
+
this.visitChildNodes(node)
|
|
194
|
+
}
|
|
195
|
+
|
|
146
196
|
visitHTMLTextNode(node: HTMLTextNode): void {
|
|
147
197
|
this.visitNode(node)
|
|
148
198
|
this.visitChildNodes(node)
|