Skip to content

Commit

Permalink
Support ruby 3.3 by handling yield (#78)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidwessman authored Apr 25, 2024
1 parent e8d9d95 commit 706a788
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 5 deletions.
1 change: 1 addition & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ jobs:
- "3.0"
- "3.1"
- "3.2"
- "3.3"
name: CI
runs-on: ubuntu-latest
env:
Expand Down
2 changes: 1 addition & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ruby 3.2.3
ruby 3.3.0
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a

## [Unreleased]

- Support Ruby 3.3 by handling yield in ERB specifically

## [0.11.0] - 2024-04-23

- ErbContent now has its value as child_nodes instead of empty array.
Expand Down
13 changes: 11 additions & 2 deletions lib/syntax_tree/erb/format.rb
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ def visit_erb_close(node)
visit(node.closing)
end

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

# Visit an ErbEnd node.
def visit_erb_end(node)
visit(node.opening_tag)
Expand Down Expand Up @@ -169,9 +173,14 @@ def format_statement(statement)

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

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

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

def output_rows(rows)
Expand Down
28 changes: 27 additions & 1 deletion lib/syntax_tree/erb/nodes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@ def prepare_content(content)
# Try to add the keyword to see if it parses
result = ErbContent.new(value: [keyword, *content])
@keyword = nil

result
end
end
Expand Down Expand Up @@ -489,7 +490,17 @@ class ErbContent < Node
def initialize(value:)
if value.is_a?(Array)
value =
value.map { |token| token.is_a?(Token) ? token.value : token }.join
value
.map do |token|
if token.is_a?(Token)
token.value
elsif token.is_a?(ErbYield)
ErbYield::PLACEHOLDER
else
token
end
end
.join
end
@value = SyntaxTree.parse(value.strip)
end
Expand Down Expand Up @@ -518,6 +529,21 @@ def deconstruct_keys(keys)
end
end

class ErbYield < Element
PLACEHOLDER = "qqqqy"
def initialize(new_line:, location:)
super(new_line: new_line, location: location)
end

def accept(visitor)
visitor.visit_erb_yield(self)
end

def child_nodes
[]
end
end

# An HtmlAttribute is a key-value pair within a tag. It contains the key, the
# equals sign, and the value.
class HtmlAttribute < Node
Expand Down
12 changes: 11 additions & 1 deletion lib/syntax_tree/erb/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,8 @@ def make_tokens
when /\A-?%>/
enum.yield :erb_close, $&, index, line
state.pop
when /\Ayield\b/
enum.yield :erb_yield, $&, index, line
when /\A[\p{L}\w]*\b/
# Split by word boundary while parsing the code
# This allows us to separate what_to_do vs do
Expand Down Expand Up @@ -648,7 +650,7 @@ def parse_until_erb_close
result =
atleast do
maybe { parse_erb_do_close } || maybe { parse_erb_close } ||
maybe { consume(:erb_code) }
maybe { parse_erb_yield } || maybe { consume(:erb_code) }
end

items << result
Expand Down Expand Up @@ -701,6 +703,14 @@ def parse_erb_do_close
)
end

def parse_erb_yield
token = consume(:erb_yield)

new_line = maybe { parse_new_line }

ErbYield.new(location: token.location, new_line: new_line)
end

def parse_html_string
opening =
maybe { consume(:string_open_double_quote) } ||
Expand Down
4 changes: 4 additions & 0 deletions lib/syntax_tree/erb/pretty_print.rb
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ def visit_erb_do_close(node)
visit_node("erb_do_close", node)
end

def visit_erb_yield(node)
visit_node("erb_yield", node)
end

# Visit a Doctype node.
def visit_doctype(node)
visit_node("doctype", node)
Expand Down

0 comments on commit 706a788

Please sign in to comment.