1
0
Fork 0
mirror of https://github.com/haml/haml.git synced 2022-11-09 12:33:31 -05:00

[Haml] [html2haml] Use Erubis and ruby_parser to figure out where ERB blocks start and end.

This commit is contained in:
Nathan Weizenbaum 2009-10-23 01:45:09 -07:00
parent a6d42ba7f3
commit 642e9de2cf
2 changed files with 89 additions and 22 deletions

View file

@ -122,8 +122,8 @@ module Haml
Haml::Util.check_encoding(template) {|msg, line| raise Haml::Error.new(msg, line)} Haml::Util.check_encoding(template) {|msg, line| raise Haml::Error.new(msg, line)}
if @options[:erb] if @options[:erb]
match_to_html(template, /<%=(.*?)-?%>/m, 'loud') require 'haml/html/erb'
match_to_html(template, /<%-?(.*?)-?%>/m, 'silent') template = ERB.compile(template)
end end
method = @options[:xhtml] ? Hpricot.method(:XML) : method(:Hpricot) method = @options[:xhtml] ? Hpricot.method(:XML) : method(:Hpricot)
@ -228,7 +228,15 @@ module Haml
output = tabulate(tabs) output = tabulate(tabs)
if options[:erb] && name[0...5] == 'haml:' if options[:erb] && name[0...5] == 'haml:'
return output + send("haml_tag_#{name[5..-1]}", CGI.unescapeHTML(self.inner_text)) case name[5..-1]
when "loud"
return output + "= #{CGI.unescapeHTML(inner_text).gsub(/\n\s*/, ' ').strip}\n"
when "silent"
return output + CGI.unescapeHTML(inner_text).split("\n").
map {|line| "- #{line.strip}\n"}.join
when "block"
return render_children("", tabs, options)
end
end end
output << "%#{name}" unless name == 'div' && output << "%#{name}" unless name == 'div' &&
@ -265,12 +273,16 @@ module Haml
end end
end end
(self.children || []).inject(output + "\n") do |output, child| render_children(output + "\n", tabs, options)
output + child.to_haml(tabs + 1, options)
end
end end
private private
def render_children(so_far, tabs, options)
(self.children || []).inject(so_far) do |output, child|
output + child.to_haml(tabs + 1, options)
end
end
def dynamic_attributes def dynamic_attributes
@dynamic_attributes ||= begin @dynamic_attributes ||= begin
@ -305,14 +317,6 @@ module Haml
"#{tabulate(tabs)}:javascript\n#{content}" "#{tabulate(tabs)}:javascript\n#{content}"
end end
def haml_tag_loud(text)
"= #{text.gsub(/\n\s*/, ' ').strip}\n"
end
def haml_tag_silent(text)
text.split("\n").map { |line| "- #{line.strip}\n" }.join
end
def static_attribute?(name, options) def static_attribute?(name, options)
attributes[name] and !dynamic_attribute?(name, options) attributes[name] and !dynamic_attribute?(name, options)
end end
@ -340,13 +344,5 @@ module Haml
"{#{attrs.join(', ')}}" "{#{attrs.join(', ')}}"
end end
end end
private
def match_to_html(string, regex, tag)
string.gsub!(regex) do
"<haml:#{tag}>#{CGI.escapeHTML($1)}</haml:#{tag}>"
end
end
end end
end end

71
lib/haml/html/erb.rb Normal file
View file

@ -0,0 +1,71 @@
require 'cgi'
require 'erubis'
require 'ruby_parser'
module Haml
class HTML
class ERB < Erubis::Basic::Engine
def self.compile(template)
new(template).src
end
def escaped_expr(code)
raise "html2haml doesn't support escaped expressions."
end
def add_preamble(src); end
def add_postamble(src); end
def add_text(src, text)
src << text
end
def add_stmt(src, code)
src << '</haml:block>' if block_closer?(code) || mid_block?(code)
src << '<haml:silent>' << h(code) << '</haml:silent>' unless code.strip == "end"
src << '<haml:block>' if block_opener?(code) || mid_block?(code)
end
def add_expr_literal(src, code)
src << '<haml:loud>' << h(code) << '</haml:loud>'
src << '<haml:block>' if block_opener?(code)
end
def add_expr_debug(src, code)
raise "html2haml doesn't support debugging expressions."
end
private
def h(code)
CGI.escapeHTML(code)
end
# Returns whether the code is valid Ruby code on its own
def valid_ruby?(code)
RubyParser.new.parse(code)
rescue Racc::ParseError => e
false
end
# Checks if the Ruby code opens a block
def block_opener?(code)
valid_ruby?(code + "\nend") ||
valid_ruby?(code + "\nwhen foo\nend")
end
# Checks if the Ruby code closes a block
def block_closer?(code)
valid_ruby?("begin\n" + code)
end
# Checks if the Ruby code comes in the middle of a block
def mid_block?(code)
return if valid_ruby?(code)
valid_ruby?("if foo\n#{code}\nend") || # else, elsif
valid_ruby?("begin\n#{code}\nend") || # rescue, ensure
valid_ruby?("case foo\n#{code}\nend") # when
end
end
end
end