Skip to content

Commit 5a6900f

Browse files
authored
Merge pull request #19 from ruby-syntax-tree/fix-plain
Fix plain div with content
2 parents 50588c6 + 0f56618 commit 5a6900f

File tree

2 files changed

+67
-47
lines changed

2 files changed

+67
-47
lines changed

lib/syntax_tree/haml/format.rb

Lines changed: 59 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,40 @@ def visit_silent_script(node)
123123

124124
LiteralHashValue = Struct.new(:value)
125125

126+
# When formatting a tag, there are a lot of different kinds of things that
127+
# can be printed out. There's the tag name, the attributes, the content,
128+
# etc. This object is responsible for housing all of those parts.
129+
class PartList
130+
attr_reader :node, :parts
131+
132+
def initialize(node)
133+
@node = node
134+
@parts = []
135+
end
136+
137+
def <<(part)
138+
parts << part
139+
end
140+
141+
def empty?
142+
parts.empty?
143+
end
144+
145+
def format(q)
146+
if empty? && node.value[:name] == "div"
147+
# If we don't have any other parts to print and the tag is a div
148+
# then we need to make sure to add that to the beginning. Otherwise
149+
# it's implied by the presence of other operators.
150+
q.text("%div")
151+
else
152+
parts.inject(0) do |align, part|
153+
part.format(q, align)
154+
align + part.length
155+
end
156+
end
157+
end
158+
end
159+
126160
class PlainPart < Struct.new(:value)
127161
def format(q, align)
128162
q.text(value)
@@ -227,7 +261,7 @@ def self.hash_value(value)
227261

228262
# Visit a tag node.
229263
def visit_tag(node)
230-
parts = []
264+
parts = PartList.new(node)
231265

232266
# If we have a tag that isn't a div, then we need to print out that
233267
# name of that tag first. If it is a div, first we'll check if there
@@ -266,6 +300,7 @@ def visit_tag(node)
266300
node.value[:attributes].reject do |key, _|
267301
key == "class" || key == "id"
268302
end
303+
269304
parts << HashAttributesPart.new(static) if static.any?
270305

271306
# If there are dynamic attributes that don't use the newer syntax, then
@@ -300,55 +335,32 @@ def visit_tag(node)
300335

301336
# If there is a value part, then we're going to print slightly
302337
# differently as the value goes after the tag declaration.
303-
if node.value[:value]
304-
return(
305-
with_children(node) do
306-
q.group do
307-
align = 0
308-
309-
parts.each do |part|
310-
part.format(q, align)
311-
align += part.length
312-
end
313-
end
314-
315-
q.indent do
316-
# Split between the declaration of the tag and the contents of the
317-
# tag.
318-
q.breakable("")
319-
320-
if node.value[:parse] && node.value[:value].match?(/#[{$@]/)
321-
# There's a weird case here where if the value includes
322-
# interpolation and it's marked as { parse: true }, then we
323-
# don't actually want the = prefix, and we want to remove extra
324-
# escaping.
325-
q.if_break { q.text("") }.if_flat { q.text(" ") }
326-
q.text(node.value[:value][1...-1].gsub(/\\"/, "\""))
327-
elsif node.value[:parse]
328-
q.text("= ")
329-
q.text(node.value[:value])
330-
else
331-
q.if_break { q.text("") }.if_flat { q.text(" ") }
332-
q.text(node.value[:value])
333-
end
338+
if (value = node.value[:value]) && !value.empty?
339+
with_children(node) do
340+
q.group { parts.format(q) }
341+
q.indent do
342+
# Split between the declaration of the tag and the contents of the
343+
# tag.
344+
q.breakable("")
345+
346+
if node.value[:parse] && value.match?(/#[{$@]/)
347+
# There's a weird case here where if the value includes
348+
# interpolation and it's marked as { parse: true }, then we
349+
# don't actually want the = prefix, and we want to remove extra
350+
# escaping.
351+
q.if_break { q.text("") }.if_flat { q.text(" ") }
352+
q.text(value[1...-1].gsub(/\\"/, "\""))
353+
elsif node.value[:parse]
354+
q.text("= ")
355+
q.text(value)
356+
else
357+
q.if_break { q.text("") }.if_flat { q.text(" ") }
358+
q.text(value)
334359
end
335360
end
336-
)
337-
end
338-
339-
# In case none of the other if statements have matched and we're
340-
# printing a div, we need to explicitly add it back into the array.
341-
if parts.empty? && node.value[:name] == "div"
342-
parts << PlainPart.new("%div")
343-
end
344-
345-
with_children(node) do
346-
align = 0
347-
348-
parts.each do |part|
349-
part.format(q, align)
350-
align += part.length
351361
end
362+
else
363+
with_children(node) { parts.format(q) }
352364
end
353365
end
354366

test/tag_test.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@
33
require "test_helper"
44

55
class TagTest < Minitest::Test
6+
def test_plain
7+
assert_format("%div")
8+
end
9+
10+
def test_value
11+
assert_format("%div Hello, world!")
12+
end
13+
614
def test_class
715
assert_format("%p.foo")
816
end

0 commit comments

Comments
 (0)