Pastie now auto-senses if line-wrap is a bad or good idea. Feedback?
## mark a section (Learn more)
This paste will be private.
diff --git a/lib/haml/engine.rb b/lib/haml/engine.rb index dd4c7a2..d491d77 100644 --- a/lib/haml/engine.rb +++ b/lib/haml/engine.rb @@ -37,7 +37,7 @@ module Haml @options = { :suppress_eval => false, :attr_wrapper => "'", - :autoclose => ['meta', 'img', 'link', 'br', 'hr', 'input', 'area'], + :autoclose => %w(meta img link br hr input area param col base), :filters => { 'sass' => Haml::Filters::Sass, 'plain' => Haml::Filters::Plain, @@ -47,7 +47,8 @@ module Haml 'textile' => Haml::Filters::Textile, 'markdown' => Haml::Filters::Markdown }, :filename => '(haml)', - :ugly => false + :ugly => false, + :html4 => false } @options.rec_merge! options diff --git a/lib/haml/precompiler.rb b/lib/haml/precompiler.rb index e79438e..922e434 100644 --- a/lib/haml/precompiler.rb +++ b/lib/haml/precompiler.rb @@ -473,8 +473,9 @@ END result.compact.sort.join end - def prerender_tag(name, atomic, attributes) - "<#{name}#{Precompiler.build_attributes(@options[:attr_wrapper], attributes)}#{atomic ? ' />' : '>'}" + def prerender_tag(name, self_close, attributes) + attributes_string = Precompiler.build_attributes(@options[:attr_wrapper], attributes) + "<#{name}#{attributes_string}#{self_close && !@options[:html4] ? ' /' : ''}>" end # Parses a line into tag_name, attributes, attributes_hash, object_ref, action, value @@ -502,7 +503,7 @@ END raise SyntaxError.new("Illegal element: classes and ids must have values.") if attributes =~ /[\.#](\.|#|\z)/ case action - when '/'; atomic = true + when '/'; atomic = !@options[:html4] when '~'; parse = flattened = true when '=' parse = true @@ -521,12 +522,12 @@ END attributes = parse_class_and_id(attributes) Buffer.merge_attrs(attributes, static_attributes) if static_attributes - raise SyntaxError.new("Illegal Nesting: Nesting within an atomic tag is illegal.") if @block_opened && atomic - raise SyntaxError.new("Illegal Nesting: Content can't be both given on the same line as %#{tag_name} and nested within it.") if @block_opened && !value.empty? - raise SyntaxError.new("Tag has no content.") if parse && value.empty? - raise SyntaxError.new("Atomic tags can't have content.") if atomic && !value.empty? + raise SyntaxError, "Illegal Nesting: Nesting within an atomic tag is illegal." if @block_opened && atomic + raise SyntaxError, "Illegal Nesting: Content can't be both given on the same line as %#{tag_name} and nested within it." if @block_opened && !value.empty? + raise SyntaxError, "Tag has no content." if parse && value.empty? + raise SyntaxError, "Atomic tags can't have content." if atomic && !value.empty? - atomic = true if !@block_opened && value.empty? && @options[:autoclose].include?(tag_name) + atomic ||= !!( !@block_opened && value.empty? && @options[:autoclose].include?(tag_name) ) if object_ref == "nil" && attributes_hash.nil? && !flattened && (parse || Buffer.one_liner?(value)) # This means that we can render the tag directly to text and not process it in the buffer @@ -600,22 +601,32 @@ END def text_for_doctype(text) text = text[3..-1].lstrip.downcase if text[0...3] == "xml" + return nil if @options[:html4] wrapper = @options[:attr_wrapper] return "<?xml version=#{wrapper}1.0#{wrapper} encoding=#{wrapper}#{text.split(' ')[1] || "utf-8"}#{wrapper} ?>" end version, type = text.scan(DOCTYPE_REGEX)[0] - if version == "1.1" - return '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">' - end + + unless @options[:html4] + if version == "1.1" + return '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">' + end - case type - when "strict"; return '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">' - when "frameset"; return '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">' - else return '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' + case type + when "strict"; return '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">' + when "frameset"; return '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">' + else return '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' + end + else + case type + when "strict"; return '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">' + when "frameset"; return '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">' + else return '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">' + end end end - + # Starts a filtered block. def start_filtered(name) raise SyntaxError.new('Filters must have nested text.') unless @block_opened diff --git a/test/haml/engine_test.rb b/test/haml/engine_test.rb index 7bc9842..5e5644c 100644 --- a/test/haml/engine_test.rb +++ b/test/haml/engine_test.rb @@ -394,4 +394,28 @@ class EngineTest < Test::Unit::TestCase assert_equal("<p>#{'s' * 75}</p>\n", render("%p= 's' * 75", :ugly => true)) end + + # HTML 4.0 + + def test_html_has_no_self_closing_tags + assert_equal "<p>\n <br>\n</p>\n", render("%p\n %br", :html4 => :true) + assert_equal "<br>\n", render("%br/", :html4 => :true) + end + + def test_html_renders_empty_node_with_closing_tag + assert_equal %{<div class='foo'>\n</div>\n}, render(".foo", :html4 => :true) + end + + def test_html_ignores_explicit_self_closing_declaration + assert_equal "<a>\n</a>\n", render("%a/", :html4 => :true) + end + + def test_html_ignores_xml_prolog_declaration + assert_equal "\n", render('!!! XML', :html4 => :true) + end + + def test_html_has_different_doctype + assert_equal %{<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">\n}, + render('!!!', :html4 => :true) + end end
Pasted February 26, 2008 5:34AM EDT
by Mislav
Channel #caboose on irc.freenode.com
Embed