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 '' { 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