Tech Talk

Bytefull of Tech Talk (http://tech.bytefull.com)

style2inline.rb (for html newsletters)

Dreamweaver CS 3 has a facility to rearrange inline styles in a <style> tag. Well, here’s a utility that does the opposite: it converts css in style tags to inline css. Yeah, I hear you. Why would anyone want to do that ?!

Sending HTML Newsletters is a nightmare. Most of the email clients, bar Eudora Light, support css. However, not all properties are supported, and Gmail, one of the major web-based email clients, supports only inline styles.

You need Ruby, and Hpricot installed to run this. Duh, it runs on windows too !

EDIT: fixed a bug & added NOTES

Here’s the code:

#!/bin/env ruby
# style2inline.rb - v0.2
# http://tech.bytefull.com
 
# NOTES:
# CSS must not contain any comments
# the last attribute-value pair must end in a semi-colon, example:
#  a {font-family: Verdana; font-size: 18pt;}
 
# uncomment this if you have hpricot installed as a gem
# require 'rubygems'
require 'hpricot'
 
def style_to_inline(filename)
  doc = open(filename) {|f| Hpricot(f)}
  css = ""
  elems = doc.search('head/style')
  # combine the content of all style tags
  elems.map {|x| css &lt;&lt; x.inner_html}
  # remove the style tags - we don't need them in our output doc
  elems.remove
  # collapse all newlines
  css.gsub!("\n", " ")
  # Regexp by Nick Franceschina
  # http://regexlib.com/REDetails.aspx?regexp_id=916
  dec_block = '((\s*([^,{]+)\s*,?\s*)*?){((\s*([^:]+)\s*:\s*([^;]+?)\s*;\s*)*?)}'
  regexp = Regexp.new(dec_block, Regexp::IGNORECASE)
  results = css.scan(regexp)
  results.each do |res|
    res[0].split(',').each do |css_sel|
      doc.search(css_sel.strip).each do |elem|
        if elem.elem? # added in version 0.2,
                      # to avoid operating on a Hpricot::Text element
          if elem[:style] then
            # append to the existing style information
            elem[:style] = elem[:style] + res[3]
          else
            # add a style attribute
            elem[:style] = res[3]
          end
          # we don't need the class attribute
          elem.remove_attribute(:class)
        end
      end
    end
  end
# output
  File.open("s2i_#{filename}", 'w') {|file| file.write(doc) }
end
 
ARGV.each {|x| style_to_inline(x)}

Invoke it with ruby style2inline.rb [FILENAME], and it will output a file of the same name prepended with ’s2i’, e.g s2i-filename.html.

June 3rd, 2007 | ahsan | No Comments | Code, Ruby

puts “introduction”

Hi,

I intend to jot down stuff that people might find useful, code snippets, links, and my thoughts on the latest technologies.

I’m currently working on a Ruby on Rails project, so expect to see that covered.

June 3rd, 2007 | ahsan | No Comments | Other

Next Entries »