Class: SyntaxTree::ERB::Format

Inherits:
Visitor
  • Object
show all
Defined in:
lib/syntax_tree/erb/format.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Visitor

#visit, #visit_statements

Constructor Details

#initialize(q) ⇒ Format

Returns a new instance of Format.



8
9
10
# File 'lib/syntax_tree/erb/format.rb', line 8

def initialize(q)
  @q = q
end

Instance Attribute Details

#qObject (readonly)

Returns the value of attribute q.



6
7
8
# File 'lib/syntax_tree/erb/format.rb', line 6

def q
  @q
end

Instance Method Details

#format_statement(statement) ⇒ Object



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/syntax_tree/erb/format.rb', line 171

def format_statement(statement)
  formatter =
    SyntaxTree::Formatter.new("", [], SyntaxTree::ERB::MAX_WIDTH)

  formatter.format(statement)
  formatter.flush

  formatted =
    formatter.output.join.gsub(
      SyntaxTree::ERB::ErbYield::PLACEHOLDER,
      "yield"
    )

  output_rows(formatted.split("\n"))
end

#output_rows(rows) ⇒ Object



187
188
189
190
191
192
193
# File 'lib/syntax_tree/erb/format.rb', line 187

def output_rows(rows)
  if rows.size > 1
    q.seplist(rows, -> { q.breakable("") }) { |row| q.text(row) }
  elsif rows.size == 1
    q.text(rows.first)
  end
end

#visit_attribute(node) ⇒ Object

Visit an Attribute node.



234
235
236
237
238
239
240
# File 'lib/syntax_tree/erb/format.rb', line 234

def visit_attribute(node)
  q.group do
    visit(node.key)
    visit(node.equals)
    visit(node.value)
  end
end

#visit_block(node) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/syntax_tree/erb/format.rb', line 31

def visit_block(node)
  visit(node.opening)

  breakable = breakable_inside(node)
  if node.elements.any?
    q.indent do
      q.breakable if breakable
      handle_child_nodes(node.elements)
    end
  end

  if node.closing
    q.breakable("") if breakable
    visit(node.closing)
  end
end

#visit_char_data(node) ⇒ Object

Visit a CharData node.



262
263
264
265
266
# File 'lib/syntax_tree/erb/format.rb', line 262

def visit_char_data(node)
  return if node.value.value.strip.empty?

  q.text(node.value.value)
end

#visit_closing_tag(node) ⇒ Object

Visit an HtmlNode::ClosingTag node.



225
226
227
228
229
230
231
# File 'lib/syntax_tree/erb/format.rb', line 225

def visit_closing_tag(node)
  q.group do
    visit(node.opening)
    visit(node.name)
    visit(node.closing)
  end
end

#visit_doctype(node) ⇒ Object

Visit a Doctype node.



274
275
276
277
278
279
280
281
282
# File 'lib/syntax_tree/erb/format.rb', line 274

def visit_doctype(node)
  q.group do
    visit(node.opening)
    q.text(" ")
    visit(node.name)

    visit(node.closing)
  end
end

#visit_document(node) ⇒ Object

Visit a Document node.



22
23
24
25
26
27
28
29
# File 'lib/syntax_tree/erb/format.rb', line 22

def visit_document(node)
  child_nodes =
    node.child_nodes.sort_by { |node| node.location.start_char }

  handle_child_nodes(child_nodes)

  q.breakable(force: true)
end

#visit_erb(node) ⇒ Object

Visit an ErbNode node.



111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/syntax_tree/erb/format.rb', line 111

def visit_erb(node)
  visit(node.opening_tag)

  if node.keyword
    q.text(" ")
    visit(node.keyword)
  end

  node.content.blank? ? q.text(" ") : visit(node.content)

  visit(node.closing_tag)
end

#visit_erb_block(node) ⇒ Object



86
87
88
# File 'lib/syntax_tree/erb/format.rb', line 86

def visit_erb_block(node)
  visit_block(node)
end

#visit_erb_case(node) ⇒ Object



102
103
104
# File 'lib/syntax_tree/erb/format.rb', line 102

def visit_erb_case(node)
  visit_block(node)
end

#visit_erb_case_when(node) ⇒ Object



106
107
108
# File 'lib/syntax_tree/erb/format.rb', line 106

def visit_erb_case_when(node)
  visit_block(node)
end

#visit_erb_close(node) ⇒ Object



131
132
133
# File 'lib/syntax_tree/erb/format.rb', line 131

def visit_erb_close(node)
  visit(node.closing)
end

#visit_erb_comment(node) ⇒ Object



255
256
257
258
259
# File 'lib/syntax_tree/erb/format.rb', line 255

def visit_erb_comment(node)
  q.seplist(node.token.value.split("\n"), -> { q.breakable }) do |line|
    q.text(line.lstrip)
  end
end

#visit_erb_content(node) ⇒ Object



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/syntax_tree/erb/format.rb', line 148

def visit_erb_content(node)
  # Reject all VoidStmt to avoid empty lines
  nodes =
    (node.value&.statements&.child_nodes || []).reject do |node|
      node.is_a?(SyntaxTree::VoidStmt)
    end

  if nodes.size == 1
    q.text(" ")
    format_statement(nodes.first)
    q.text(" ")
  elsif nodes.size > 1
    q.indent do
      q.breakable("")
      q.seplist(nodes, -> { q.breakable("") }) do |child_node|
        format_statement(child_node)
      end
    end

    q.breakable
  end
end

#visit_erb_do_close(node) ⇒ Object



124
125
126
127
128
129
# File 'lib/syntax_tree/erb/format.rb', line 124

def visit_erb_do_close(node)
  closing = node.closing.value.end_with?("-%>") ? "-%>" : "%>"
  q.text(node.closing.value.gsub(closing, "").rstrip)
  q.text(" ")
  q.text(closing)
end

#visit_erb_else(node) ⇒ Object



98
99
100
# File 'lib/syntax_tree/erb/format.rb', line 98

def visit_erb_else(node)
  visit_block(node)
end

#visit_erb_elsif(node) ⇒ Object



94
95
96
# File 'lib/syntax_tree/erb/format.rb', line 94

def visit_erb_elsif(node)
  visit_block(node)
end

#visit_erb_end(node) ⇒ Object

Visit an ErbEnd node.



140
141
142
143
144
145
146
# File 'lib/syntax_tree/erb/format.rb', line 140

def visit_erb_end(node)
  visit(node.opening_tag)
  q.text(" ")
  visit(node.keyword)
  q.text(" ")
  visit(node.closing_tag)
end

#visit_erb_if(node) ⇒ Object



90
91
92
# File 'lib/syntax_tree/erb/format.rb', line 90

def visit_erb_if(node)
  visit_block(node)
end

#visit_erb_yield(node) ⇒ Object



135
136
137
# File 'lib/syntax_tree/erb/format.rb', line 135

def visit_erb_yield(node)
  q.text("yield")
end

#visit_html(node) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/syntax_tree/erb/format.rb', line 70

def visit_html(node)
  # Make sure to group the tags together if there is no child nodes.
  if node.elements.size == 0 ||
       node.elements.any? { |node|
         node.is_a?(SyntaxTree::ERB::CharData)
       } ||
       (
         node.elements.size == 1 &&
           node.elements.first.is_a?(SyntaxTree::ERB::ErbNode)
       )
    q.group { visit_html_groupable(node, true) }
  else
    visit_html_groupable(node, false)
  end
end

#visit_html_comment(node) ⇒ Object



251
252
253
# File 'lib/syntax_tree/erb/format.rb', line 251

def visit_html_comment(node)
  visit(node.token)
end

#visit_html_groupable(node, group) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/syntax_tree/erb/format.rb', line 48

def visit_html_groupable(node, group)
  if node.elements.size == 0
    visit(node.opening)
    visit(node.closing)
  else
    visit(node.opening)

    with_break = breakable_inside(node)
    q.indent do
      if with_break
        group ? q.breakable("") : q.breakable
      end
      handle_child_nodes(node.elements)
    end

    if with_break
      group ? q.breakable("") : q.breakable
    end
    visit(node.closing)
  end
end

#visit_html_string(node) ⇒ Object

Visit a HtmlString node.



243
244
245
246
247
248
249
# File 'lib/syntax_tree/erb/format.rb', line 243

def visit_html_string(node)
  q.group do
    q.text("\"")
    q.seplist(node.contents, -> { "" }) { |child_node| visit(child_node) }
    q.text("\"")
  end
end

#visit_new_line(node) ⇒ Object



268
269
270
271
# File 'lib/syntax_tree/erb/format.rb', line 268

def visit_new_line(node)
  q.breakable(force: :skip_parent_break)
  q.breakable(force: :skip_parent_break) if node.count > 1
end

#visit_opening_tag(node) ⇒ Object

Visit an HtmlNode::OpeningTag node.



196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/syntax_tree/erb/format.rb', line 196

def visit_opening_tag(node)
  q.group do
    visit(node.opening)
    visit(node.name)

    if node.attributes.any?
      q.indent do
        q.breakable
        q.seplist(node.attributes, -> { q.breakable }) do |child_node|
          visit(child_node)
        end
      end

      # Only add breakable if we have attributes
      q.breakable(node.closing.value == "/>" ? " " : "")
    elsif node.closing.value == "/>"
      # Need a space before end-tag for self-closing
      q.text(" ")
    end

    # If element is a valid void element, but not currently self-closing
    # format to be self-closing
    q.text(" /") if node.is_void_element? and node.closing.value == ">"

    visit(node.closing)
  end
end

#visit_token(node) ⇒ Object

Visit a Token node.



13
14
15
16
17
18
19
# File 'lib/syntax_tree/erb/format.rb', line 13

def visit_token(node)
  if %i[text whitespace].include?(node.type)
    q.text(node.value)
  else
    q.text(node.value.strip)
  end
end