def to_inline_css
doc = @processed_doc
@unmergable_rules = CssParser::Parser.new
doc.search("*[@style]").each do |el|
el['style'] = '[SPEC=1000[' + el.attributes['style'] + ']]'
end
@css_parser.each_selector(:all) do |selector, declaration, specificity, media_types|
selector.gsub!(/:link([\s]*)+/i) { |m| $1 }
selector.gsub!(/([\s]|^)([\w]+)/) { |m| $1.to_s + $2.to_s.downcase }
if Premailer.is_media_query?(media_types) || selector =~ Premailer::RE_UNMERGABLE_SELECTORS
@unmergable_rules.add_rule_set!(CssParser::RuleSet.new(selector, declaration), media_types) unless @options[:preserve_styles]
else
begin
if selector =~ Premailer::RE_RESET_SELECTORS
@unmergable_rules.add_rule_set!(CssParser::RuleSet.new(selector, declaration)) unless !@options[:preserve_reset]
end
selector.gsub!(/\A\#([\w_\-]+)\Z/, '*[@id=\1]')
doc.search(selector).each do |el|
if el.elem? and (el.name != 'head' and el.parent.name != 'head')
block = "[SPEC=#{specificity}[#{declaration}]]"
el['style'] = (el.attributes['style'].to_s ||= '') + ' ' + block
end
end
rescue ::Nokogiri::SyntaxError, RuntimeError, ArgumentError
$stderr.puts "CSS syntax error with selector: #{selector}" if @options[:verbose]
next
end
end
end
if @options[:remove_scripts]
doc.search("script").remove
end
doc.search("*[@style]").each do |el|
style = el.attributes['style'].to_s
declarations = []
style.scan(/\[SPEC\=([\d]+)\[(.[^\]\]]*)\]\]/).each do |declaration|
rs = CssParser::RuleSet.new(nil, declaration[1].to_s, declaration[0].to_i)
declarations << rs
end
merged = CssParser.merge(declarations)
merged.expand_shorthand!
if Premailer::RELATED_ATTRIBUTES.has_key?(el.name)
Premailer::RELATED_ATTRIBUTES[el.name].each do |css_att, html_att|
el[html_att] = merged[css_att].gsub(/url\(['|"](.*)['|"]\)/, '\1').gsub(/;$|\s*!important/, '').strip if el[html_att].nil? and not merged[css_att].empty?
end
end
merged.create_shorthand!
attributes = Premailer.escape_string(merged.declarations_to_s).split(';').map(&:strip)
attributes = attributes.map { |attr| [attr.split(':').first, attr] }.sort_by { |pair| pair.first }.map { |pair| pair[1] }
el['style'] = attributes.join('; ')
end
doc = write_unmergable_css_rules(doc, @unmergable_rules)
if @options[:remove_classes] or @options[:remove_comments]
doc.traverse do |el|
if el.comment? and @options[:remove_comments]
el.remove
elsif el.element?
el.remove_attribute('class') if @options[:remove_classes]
end
end
end
if @options[:remove_ids]
targets = []
doc.search("a[@href^='#']").each do |el|
target = el.get_attribute('href')[1..-1]
targets << target
el.set_attribute('href', "#" + Digest::MD5.hexdigest(target))
end
doc.search("*[@id]").each do |el|
id = el.get_attribute('id')
if targets.include?(id)
el.set_attribute('id', Digest::MD5.hexdigest(id))
else
el.remove_attribute('id')
end
end
end
if @options[:reset_contenteditable]
doc.search('*[@contenteditable]').each do |el|
el.remove_attribute('contenteditable')
end
end
@processed_doc = doc
if is_xhtml?
@processed_doc.to_xhtml(:encoding => @options[:output_encoding]).gsub(/&\#(xD|13);/i, "\r")
else
@processed_doc.to_html(:encoding => @options[:output_encoding])
end
end