tamtam 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: