Skip to content

Commit f8559fe

Browse files
authored
Supports ERB-tags with if-else-end in same tag (#61)
- Fixes #60 - Release v0.10.3
1 parent f24718a commit f8559fe

File tree

8 files changed

+96
-45
lines changed

8 files changed

+96
-45
lines changed

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,21 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
66

77
## [Unreleased]
88

9+
## [0.10.3] - 2023-08-27
10+
11+
## Fixes
12+
13+
- Allows parsing ERB-tags with if, else and end in the same tag
14+
15+
```erb
16+
<%= if true
17+
what
18+
end %>
19+
```
20+
21+
This opens the possibility for formatting all if-statements with SyntaxTree properly
22+
and removes the fix where any if-statement was force to one line.
23+
924
## [0.10.2] - 2023-08-22
1025

1126
### Fixes

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: .
33
specs:
4-
w_syntax_tree-erb (0.10.2)
4+
w_syntax_tree-erb (0.10.3)
55
prettier_print (~> 1.2, >= 1.2.0)
66
syntax_tree (~> 6.1, >= 6.1.1)
77

lib/syntax_tree/erb/format.rb

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ def visit_erb(node)
114114
q.text(" ")
115115
visit(node.keyword)
116116
end
117-
node.content.nil? ? q.text(" ") : visit(node.content)
117+
node.content.blank? ? q.text(" ") : visit(node.content)
118118

119119
visit(node.closing_tag)
120120
end
@@ -163,7 +163,8 @@ def visit_erb_content(node)
163163

164164
def format_statement(statement)
165165
formatter =
166-
SyntaxTree::Formatter.new("", [], erb_print_width(statement))
166+
SyntaxTree::Formatter.new("", [], SyntaxTree::ERB::MAX_WIDTH)
167+
167168
formatter.format(statement)
168169
formatter.flush
169170
rows = formatter.output.join.split("\n")
@@ -305,24 +306,6 @@ def node_new_line_count(node)
305306
node.respond_to?(:new_line) ? node.new_line&.count || 0 : 0
306307
end
307308

308-
def erb_print_width(node)
309-
# Set the width to maximum if we have an IfNode or IfOp,
310-
# we cannot format them purely with SyntaxTree because the ERB-syntax will be unparseable.
311-
check_for_if_statement(node) ? 999_999 : SyntaxTree::ERB::MAX_WIDTH
312-
end
313-
314-
def check_for_if_statement(node)
315-
return false if node.nil?
316-
317-
if node.is_a?(SyntaxTree::IfNode) || node.is_a?(SyntaxTree::IfOp)
318-
return true
319-
end
320-
321-
node.child_nodes.any? do |child_node|
322-
check_for_if_statement(child_node)
323-
end
324-
end
325-
326309
def handle_child_nodes(child_nodes)
327310
group = []
328311

lib/syntax_tree/erb/nodes.rb

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -295,16 +295,7 @@ def initialize(
295295
)
296296
end
297297

298-
@content =
299-
if content.is_a?(ErbContent)
300-
content
301-
else
302-
# Set content to nil if it is empty
303-
content ||= []
304-
content = content.map(&:value).join if content.is_a?(Array)
305-
ErbContent.new(value: content) unless content.strip.empty?
306-
end
307-
298+
@content = prepare_content(content)
308299
@closing_tag = closing_tag
309300
end
310301

@@ -338,6 +329,24 @@ def deconstruct_keys(keys)
338329
closing_tag: closing_tag
339330
)
340331
end
332+
333+
private
334+
335+
def prepare_content(content)
336+
if content.is_a?(ErbContent)
337+
content
338+
else
339+
# Set content to nil if it is empty
340+
content ||= []
341+
342+
ErbContent.new(value: content)
343+
end
344+
rescue SyntaxTree::Parser::ParseError
345+
# Try to add the keyword to see if it parses
346+
result = ErbContent.new(value: [keyword, *content])
347+
@keyword = nil
348+
result
349+
end
341350
end
342351

343352
class ErbBlock < Block
@@ -413,7 +422,7 @@ def accept(visitor)
413422

414423
class ErbElse < ErbIf
415424
def accept(visitor)
416-
visitor.visit_erb_if(self)
425+
visitor.visit_erb_else(self)
417426
end
418427
end
419428

@@ -448,16 +457,23 @@ def accept(visitor)
448457
end
449458

450459
class ErbContent < Node
451-
attr_reader(:value, :unparsed_value)
460+
attr_reader(:value)
452461

453462
def initialize(value:)
454-
@unparsed_value = value
455-
begin
456-
@value = SyntaxTree.parse(value.strip)
457-
rescue SyntaxTree::Parser::ParseError
458-
# Removes leading and trailing whitespace
459-
@value = value&.lstrip&.rstrip
463+
if value.is_a?(Array)
464+
value =
465+
value.map { |token| token.is_a?(Token) ? token.value : token }.join
460466
end
467+
@value = SyntaxTree.parse(value.strip)
468+
end
469+
470+
def blank?
471+
value.nil? ||
472+
value
473+
.statements
474+
.child_nodes
475+
.reject { |node| node.is_a?(SyntaxTree::VoidStmt) }
476+
.empty?
461477
end
462478

463479
def accept(visitor)

lib/syntax_tree/erb/parser.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,7 @@ def parse_erb_tag
588588
location: opening_tag.location.to(closing_tag.location)
589589
)
590590

591-
case keyword&.type
591+
case erb_node.keyword&.type
592592
when :erb_if, :erb_unless, :erb_elsif
593593
parse_erb_if(erb_node)
594594
when :erb_case, :erb_when

lib/syntax_tree/erb/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22

33
module SyntaxTree
44
module ERB
5-
VERSION = "0.10.2"
5+
VERSION = "0.10.3"
66
end
77
end

test/erb_test.rb

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,44 @@ def test_erb_code_with_non_ascii
3535
assert_instance_of(SyntaxTree::ERB::ErbNode, parsed.elements.first)
3636
end
3737

38+
def test_if_and_end_in_same_output_tag_short
39+
source = "<%= if true\n what\nend %>"
40+
expected = "<%= what if true %>\n"
41+
42+
assert_formatting(source, expected)
43+
end
44+
45+
def test_if_and_end_in_same_tag
46+
source = "<% if true then this elsif false then that else maybe end %>"
47+
expected =
48+
"<% if true\n this\nelsif false\n that\nelse\n maybe\nend %>\n"
49+
50+
assert_formatting(source, expected)
51+
end
52+
3853
def test_long_if_statement
3954
source =
4055
"<%=number_to_percentage(@reports&.first&.stability*100,precision: 1) if @reports&.first&.other&.stronger&.longer %>"
4156
expected =
42-
"<%= number_to_percentage(@reports&.first&.stability * 100, precision: 1) if @reports&.first&.other&.stronger&.longer %>\n"
57+
"<%= if @reports&.first&.other&.stronger&.longer\n number_to_percentage(@reports&.first&.stability * 100, precision: 1)\nend %>\n"
58+
59+
assert_formatting(source, expected)
60+
end
61+
62+
def test_erb_else_if_statement
63+
source =
64+
"<%if this%>\n <h1>A</h1>\n<%elsif that%>\n <h1>B</h1>\n<%else%>\n <h1>C</h1>\n<%end%>"
65+
expected =
66+
"<% if this %>\n <h1>A</h1>\n<% elsif that %>\n <h1>B</h1>\n<% else %>\n <h1>C</h1>\n<% end %>\n"
67+
68+
assert_formatting(source, expected)
69+
end
70+
71+
def test_long_ternary
72+
source =
73+
"<%= number_to_percentage(@reports&.first&.stability * 100, precision: @reports&.first&.stability ? 'Stable' : 'Unstable') %>"
74+
expected =
75+
"<%= number_to_percentage(\n @reports&.first&.stability * 100,\n precision: @reports&.first&.stability ? \"Stable\" : \"Unstable\"\n) %>\n"
4376

4477
assert_formatting(source, expected)
4578
end
@@ -73,9 +106,9 @@ def test_erb_only_erb_comment
73106

74107
def test_erb_ternary_as_argument_without_parentheses
75108
source =
76-
"<%= f.submit f.object.id.present? ? t('buttons.titles.save'):t('buttons.titles.create') %>"
109+
"<%= f.submit( f.object.id.present? ? t('buttons.titles.save'):t('buttons.titles.create')) %>"
77110
expected =
78-
"<%= f.submit f.object.id.present? ? t(\"buttons.titles.save\") : t(\"buttons.titles.create\") %>\n"
111+
"<%= f.submit(\n f.object.id.present? ? t(\"buttons.titles.save\") : t(\"buttons.titles.create\")\n) %>\n"
79112

80113
assert_formatting(source, expected)
81114
end

test/fixture/if_statements_formatted.html.erb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,8 @@
1919
<% end %>
2020
</h1>
2121

22-
<%= @model ? @model.name : t("views.more_than_80_characters_long_row.categories.shared.version.default") %>
22+
<%= if @model
23+
@model.name
24+
else
25+
t("views.more_than_80_characters_long_row.categories.shared.version.default")
26+
end %>

0 commit comments

Comments
 (0)