grammar Rhtml
rule doc
space node space x:doc? {
def convert
if x.empty?
node.convert
else
node.convert + x.convert
end
end
}
end
rule node
hprintlet / printlet / scriptlet / doctype / self_closing_tag / imgtag / closetag / opentag / text
end
rule scriptlet
'<%' space code space '%>' {
def convert
text = code.text_value.strip
if text =~ /\bdo( |.*|)?$/
line_in text
elsif text == "end"
line_out text
else
line text
end
end
}
end
rule printlet
'<%=' space code space '%>' {
def convert
line "rawtext #{code.convert}"
end
}
end
rule hprintlet
'<%=' space 'h' ' '+ code space '%>' {
def convert
line "text #{code.convert}"
end
}
end
rule code
(('%' !'>') / [^%])* {
def convert
code = text_value.strip
# matches a word, followed by either a word, a string, or a symbol
result = code.gsub(/^(\w+) ([\w:"'].*)$/, '\1(\2)')
# Convert yield, for layouts
#result.gsub!(/^yield$/, '@content')
result
end
}
end
rule doctype
']* '>' {
def convert
line "rawtext '#{text_value}'"
end
}
end
rule tagname
[A-Za-z0-9_:-]+
end
rule self_closing_tag
'<' tag_name:tagname attrs:attributes? space '/>' {
def convert
line "#{tag_name.text_value}#{attrs.blank? ? "" : attrs.convert}"
end
}
end
rule opentag
'<' tag_name:tagname attrs:attributes? space '>' {
def convert
line_in "#{tag_name.text_value}#{attrs.blank? ? "" : attrs.convert} do"
end
}
end
rule imgtag
'<' tag_name:'img' attrs:attributes? space '>' {
def convert
line "#{tag_name.text_value}#{attrs.blank? ? "" : attrs.convert}"
end
}
end
rule closetag
'' tag_name:tagname '>' {
def convert
line_out "end"
end
}
end
rule text
(([<>] !(tagname / [/%!])) / [^<>])+ {
def convert
stripped = text_value.strip
if stripped.blank?
""
else
line "text '#{text_value.strip.html_unescape}'"
end
end
}
end
rule attributes
first:attribute rest:attributes* {
def convert
" " + first.convert +
if rest.blank?
""
else
",#{rest.elements.first.convert}" # this is hacky -- is there a better way?
end
end
}
end
rule attribute
space n:(tagname) space '=' space v:quoted space {
def convert
attr_name = (n.text_value =~ /[-:]/) ? "'#{n.text_value}'" : ":#{n.text_value}"
"#{attr_name} => '#{v.value.html_unescape.escape_single_quotes}'"
end
}
end
rule quoted
(('"' val:([^"]*) '"') / ('\'' val:([^']*) '\'')) {
def value
val.text_value
end
}
end
rule space
' '*
end
end