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



166
167
168
169
170
171
172
173
174
175
# File 'lib/syntax_tree/erb/format.rb', line 166

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

  formatter.format(statement)
  formatter.flush
  rows = formatter.output.join.split("\n")

  output_rows(rows)
end

#output_rows(rows) ⇒ Object



177
178
179
180
181
182
183
# File 'lib/syntax_tree/erb/format.rb', line 177

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.



220
221
222
223
224
225
226
# File 'lib/syntax_tree/erb/format.rb', line 220

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

#visit_block(node) ⇒ Object



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

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.



248
249
250
251
252
# File 'lib/syntax_tree/erb/format.rb', line 248

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.



211
212
213
214
215
216
217
# File 'lib/syntax_tree/erb/format.rb', line 211

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.



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

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
# File 'lib/syntax_tree/erb/format.rb', line 22

def visit_document(node)
  child_nodes = node.child_nodes.sort_by(&:location)

  handle_child_nodes(child_nodes)

  q.breakable(force: true)
end

#visit_erb(node) ⇒ Object

Visit an ErbNode node.



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

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



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

def visit_erb_block(node)
  visit_block(node)
end

#visit_erb_case(node) ⇒ Object



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

def visit_erb_case(node)
  visit_block(node)
end

#visit_erb_case_when(node) ⇒ Object



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

def visit_erb_case_when(node)
  visit_block(node)
end

#visit_erb_close(node) ⇒ Object



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

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

#visit_erb_comment(node) ⇒ Object



241
242
243
244
245
# File 'lib/syntax_tree/erb/format.rb', line 241

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



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/syntax_tree/erb/format.rb', line 143

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



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

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



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

def visit_erb_else(node)
  visit_block(node)
end

#visit_erb_elsif(node) ⇒ Object



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

def visit_erb_elsif(node)
  visit_block(node)
end

#visit_erb_end(node) ⇒ Object

Visit an ErbEnd node.



135
136
137
138
139
140
141
# File 'lib/syntax_tree/erb/format.rb', line 135

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



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

def visit_erb_if(node)
  visit_block(node)
end

#visit_html(node) ⇒ Object



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

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



237
238
239
# File 'lib/syntax_tree/erb/format.rb', line 237

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

#visit_html_groupable(node, group) ⇒ Object



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

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.



229
230
231
232
233
234
235
# File 'lib/syntax_tree/erb/format.rb', line 229

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



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

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.



186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/syntax_tree/erb/format.rb', line 186

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

    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