tamtam 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lib/tamtam.rb +99 -0
  2. metadata +54 -0
data/lib/tamtam.rb ADDED
@@ -0,0 +1,99 @@
1
+ require "rubygems"
2
+ require "hpricot"
3
+
4
+ # Takes CSS + HTML and converts it to inline styles.
5
+ # css <= '#foo { font-color: blue; }'
6
+ # html <= '<div id="foo">woot</div>'
7
+ # output => '<div id="foo" style="font-color: blue;">woot</div>'
8
+ #
9
+ # The class uses regular expressions to parse the CSS.
10
+ # The regular expressions are based on CPAN's CSS::Parse::Lite.
11
+ #
12
+ # Author: Dave Hoover of Obtiva Corp.
13
+ # Sponsor: Gary Levitt of MadMimi.com
14
+ class TamTam
15
+ UNSUPPORTED = /(::first-letter|:link|:visited|:hover|:active)$/
16
+
17
+ class << self
18
+ def inline(args)
19
+ css, doc = process(args)
20
+ raw_styles(css).each do |raw_style|
21
+ style, contents = parse(raw_style)
22
+ next if style.match(UNSUPPORTED)
23
+ (doc/style).each do |element|
24
+ apply_to(element, style, contents)
25
+ end
26
+ end
27
+ doc.to_s
28
+ end
29
+
30
+ private
31
+
32
+ def process(args)
33
+ if args[:document]
34
+ doc = Hpricot(args[:document])
35
+ style = (doc/"style").first
36
+ [(style && style.inner_html), doc]
37
+ else
38
+ [args[:css], Hpricot(args[:body])]
39
+ end
40
+ end
41
+
42
+ def raw_styles(css)
43
+ return [] if css.nil?
44
+ css = css.gsub(/[\r\n]/, " ")
45
+ validate(css)
46
+ # jamming brackets back on, wishing for look-behinds
47
+ styles = css.strip.split("}").map { |style| style + "}" }
48
+ # running backward to allow for "last one wins"
49
+ styles.reverse
50
+ end
51
+
52
+ def validate(css)
53
+ lefts = bracket_count(css, "{")
54
+ rights = bracket_count(css, "}")
55
+ if lefts != rights
56
+ raise InvalidStyleException, "Found #{lefts} left brackets and #{rights} right brackets in:\n #{css}"
57
+ end
58
+ end
59
+
60
+ def bracket_count(css, bracket)
61
+ css.scan(Regexp.new(Regexp.escape(bracket))).size
62
+ end
63
+
64
+ def parse(raw_style)
65
+ # Regex from CSS::Parse::Lite
66
+ data = raw_style.match(/^\s*([^{]+?)\s*\{(.*)\}\s*$/)
67
+ raise "Invalid style: #{style}" if data.nil?
68
+ data.captures.map { |s| s.strip }
69
+ end
70
+
71
+ def apply_to(element, style, contents)
72
+ return unless element.respond_to?(:get_attribute)
73
+ current_style = to_hash(element.get_attribute(:style))
74
+ new_styles = to_hash(contents).merge(current_style)
75
+ element.set_attribute(:style, prepare(new_styles))
76
+ rescue Exception => e
77
+ raise Exception.new(e), "Trouble on style #{style} on element #{element}: #{e}"
78
+ end
79
+
80
+ def to_hash(style)
81
+ return {} if style.nil?
82
+ hash = {}
83
+ pieces = style.strip.split(";").map { |s| s.strip.split(":").map { |kv| kv.strip } }
84
+ pieces.each do |key, value|
85
+ hash[key] = value
86
+ end
87
+ hash
88
+ end
89
+
90
+ def prepare(style_hash)
91
+ sorted_styles = style_hash.keys.sort.map { |key| key + ": " + style_hash[key] }
92
+ sorted_styles.join("; ").strip + ";"
93
+ end
94
+ end
95
+ end
96
+
97
+ class InvalidStyleException < Exception
98
+ end
99
+ # "Man Chocolate" (don't ask)
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.2
3
+ specification_version: 1
4
+ name: tamtam
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.0.1
7
+ date: 2007-10-05 00:00:00 -05:00
8
+ summary: Inline a CSS stylesheet into an HTML document.
9
+ require_paths:
10
+ - .
11
+ email: dave@obtiva.com
12
+ homepage: http://tamtam.rubyforge.org/
13
+ rubyforge_project: tamtam
14
+ description: Email services like GMail and Hotmail don't like stylesheets. The only way around it is to use inline tags. Replacing stylesheet references with inline tags is a pain in the arse. Use this tool to do the dirty work for you.
15
+ autorequire: tamtam
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: false
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Dave Hoover
31
+ files:
32
+ - lib/tamtam.rb
33
+ test_files: []
34
+
35
+ rdoc_options: []
36
+
37
+ extra_rdoc_files: []
38
+
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ requirements: []
44
+
45
+ dependencies:
46
+ - !ruby/object:Gem::Dependency
47
+ name: hpricot
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Version::Requirement
50
+ requirements:
51
+ - - ">"
52
+ - !ruby/object:Gem::Version
53
+ version: 0.0.0
54
+ version: