diff --git a/lib/premailer/adapter/hpricot.rb b/lib/premailer/adapter/hpricot.rb index c1a24221..ea62c065 100644 --- a/lib/premailer/adapter/hpricot.rb +++ b/lib/premailer/adapter/hpricot.rb @@ -143,7 +143,7 @@ def write_unmergable_css_rules(doc, unmergable_rules) # :nodoc: unless styles.empty? style_tag = "\n\n" - if head = doc.search('head') + if @options[:keep_unmergable_in_head] && head = doc.search('head') head.append(style_tag) elsif body = doc.search('body') body.append(style_tag) diff --git a/lib/premailer/adapter/nokogiri.rb b/lib/premailer/adapter/nokogiri.rb index 09bd5bad..94377955 100644 --- a/lib/premailer/adapter/nokogiri.rb +++ b/lib/premailer/adapter/nokogiri.rb @@ -143,15 +143,19 @@ def write_unmergable_css_rules(doc, unmergable_rules) # :nodoc: styles = unmergable_rules.to_s unless styles.empty? - style_tag = "" - unless (body = doc.search('body')).empty? - if doc.at_css('body').children && !doc.at_css('body').children.empty? - doc.at_css('body').children.before(::Nokogiri::XML.fragment(style_tag)) + style_tag = "\n" + if @options[:keep_unmergable_in_head] && !doc.search('head').empty? + doc.at_css('head').add_child(::Nokogiri::XML.fragment(style_tag)) + else + unless doc.search('body').empty? + if doc.at_css('body').children && !doc.at_css('body').children.empty? + doc.at_css('body').children.before(::Nokogiri::XML.fragment(style_tag)) + else + doc.at_css('body').add_child(::Nokogiri::XML.fragment(style_tag)) + end else - doc.at_css('body').add_child(::Nokogiri::XML.fragment(style_tag)) + doc.inner_html = style_tag += doc.inner_html end - else - doc.inner_html = style_tag += doc.inner_html end end doc diff --git a/lib/premailer/premailer.rb b/lib/premailer/premailer.rb index 298ff1eb..3f07ff8b 100755 --- a/lib/premailer/premailer.rb +++ b/lib/premailer/premailer.rb @@ -163,6 +163,7 @@ module Warnings # @option options [Boolean] :verbose Whether to print errors and warnings to $stderr. Default is false. # @option options [Boolean] :include_link_tags Whether to include css from link rel=stylesheet tags. Default is true. # @option options [Boolean] :include_style_tags Whether to include css from style tags. Default is true. + # @option options [Boolean] :keep_unmergable_in_head Whether to leave unmergable styles in the head or default to the body. Default is false. # @option options [String] :input_encoding Manually specify the source documents encoding. This is a good idea. Default is ASCII-8BIT. # @option options [Boolean] :replace_html_entities Convert HTML entities to actual characters. Default is false. # @option options [Boolean] :escape_url_attributes URL Escapes href, src, and background attributes on elements. Default is true. @@ -189,6 +190,7 @@ def initialize(html, options = {}) :io_exceptions => false, :include_link_tags => true, :include_style_tags => true, + :keep_unmergable_in_head => false, :input_encoding => 'ASCII-8BIT', :output_encoding => nil, :replace_html_entities => false, diff --git a/test/test_misc.rb b/test/test_misc.rb index 0e326685..8489fa86 100644 --- a/test/test_misc.rb +++ b/test/test_misc.rb @@ -123,10 +123,7 @@ def test_preserving_styles # should be preserved as unmergeable - ## BUG: for hpricot adapter,processed_doc.at('body style') is nil - unless adapter == :hpricot - assert_match /color: red/i, premailer.processed_doc.at('body style').inner_html - end + assert_match /color: red/i, premailer.processed_doc.at('body style').inner_html assert_match /a:hover/i, premailer.processed_doc.at('style').inner_html end @@ -172,18 +169,15 @@ def test_unmergable_media_queries style_tag = premailer.processed_doc.at('body style') - # BUG: for hpricot adapter, style_tag is nil - unless adapter == :hpricot - assert style_tag, "#{adapter} failed to add a body style tag" - style_tag_contents = style_tag.inner_html - - assert_equal "color: blue", premailer.processed_doc.at('a').attributes['style'].to_s, - "#{adapter}: Failed to inline the default style" - assert_match /@media \(min-width:500px\) \{.*?a \{.*?color: red;.*?\}.*?\}/m, style_tag_contents, - "#{adapter}: Failed to add media query with no type to style" - assert_match /@media screen and \(orientation: portrait\) \{.*?a \{.*?color: green;.*?\}.*?\}/m, style_tag_contents, - "#{adapter}: Failed to add media query with type to style" - end + assert style_tag, "#{adapter} failed to add a body style tag" + style_tag_contents = style_tag.inner_html + + assert_match "color: blue", premailer.processed_doc.at('a').attributes['style'].to_s, + "#{adapter}: Failed to inline the default style" + assert_match /@media \(min-width:500px\) \{.*?a \{.*?color: red;.*?\}.*?\}/m, style_tag_contents, + "#{adapter}: Failed to add media query with no type to style" + assert_match /@media screen and \(orientation: portrait\) \{.*?a \{.*?color: green;.*?\}.*?\}/m, style_tag_contents, + "#{adapter}: Failed to add media query with type to style" end end diff --git a/test/test_premailer.rb b/test/test_premailer.rb index 63614b09..58361f40 100644 --- a/test/test_premailer.rb +++ b/test/test_premailer.rb @@ -354,4 +354,32 @@ def test_empty_html_nokogiri end end + def test_media_queries_when_keep_unmergable_in_head_flag_is_true + html = <<-___ + + + + + +
Test
+ + ___ + adapters.each do |adapter| + pm = Premailer.new(html, :with_html_string => true, :adapter => adapter, keep_unmergable_in_head: true) + pm.to_inline_css + doc = pm.processed_doc + refute_nil doc.at('head > style') + asserted = + if adapter == :hpricot + doc.at('head > style').html + elsif adapter == :nokogiri + doc.at('head > style').text + end + assert_equal(asserted, "\n@media only screen and (max-width:480px) {\n table {\n color: red;\n }\n}\n") + end + end + end