inline-style 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/Manifest.txt +14 -0
- data/README.rdoc +129 -0
- data/Rakefile +26 -0
- data/example.rb +6 -0
- data/inline-style.gemspec +46 -0
- data/lib/inline-style.rb +54 -0
- data/lib/inline-style/rack/middleware.rb +35 -0
- data/rack-inline-styles.gemspec +37 -0
- data/spec/as_middleware_spec.rb +57 -0
- data/spec/css_inlining_spec.rb +30 -0
- data/spec/fixtures/style.css +4 -0
- data/spec/fixtures/with-style-tag.html +55 -0
- data/spec/spec_helper.rb +35 -0
- metadata +116 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
History.txt
|
2
|
+
Manifest.txt
|
3
|
+
README.rdoc
|
4
|
+
Rakefile
|
5
|
+
example.rb
|
6
|
+
inline-style.gemspec
|
7
|
+
lib/inline-style.rb
|
8
|
+
lib/inline-style/rack/middleware.rb
|
9
|
+
rack-inline-styles.gemspec
|
10
|
+
spec/as_middleware_spec.rb
|
11
|
+
spec/css_inlining_spec.rb
|
12
|
+
spec/fixtures/style.css
|
13
|
+
spec/fixtures/with-style-tag.html
|
14
|
+
spec/spec_helper.rb
|
data/README.rdoc
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
= inline-style
|
2
|
+
|
3
|
+
* http://github.com/maca/inline-style
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
Simple utility for "inlining" all CSS in the style attribute for the html tags. Useful for html emails that won't
|
8
|
+
correctly render stylesheets in some clients such as gmail.
|
9
|
+
|
10
|
+
* Includes a Rack middleware for using with Rails, Sinatra, etc...
|
11
|
+
* It takes into account selector specificity.
|
12
|
+
|
13
|
+
== USAGE
|
14
|
+
require 'inline-style'
|
15
|
+
|
16
|
+
html = File.read("#{ dir }/index.html")
|
17
|
+
puts InlineStyle.process(html, "#{ dir }/styles")
|
18
|
+
|
19
|
+
index.html contains:
|
20
|
+
|
21
|
+
<style type="text/css" media="screen">
|
22
|
+
* {
|
23
|
+
font-family: "Lucida Grande", Lucida, Verdana, sans-serif;
|
24
|
+
margin: 4px 3px 2px 1px;
|
25
|
+
padding: 0;
|
26
|
+
}
|
27
|
+
|
28
|
+
#list {
|
29
|
+
margin: 10;
|
30
|
+
}
|
31
|
+
|
32
|
+
#list li {
|
33
|
+
font-family: Arial;
|
34
|
+
}
|
35
|
+
|
36
|
+
.element {
|
37
|
+
padding: 10;
|
38
|
+
}
|
39
|
+
|
40
|
+
.odd {
|
41
|
+
background-color: black;
|
42
|
+
}
|
43
|
+
|
44
|
+
.pair {
|
45
|
+
background-color: red;
|
46
|
+
}
|
47
|
+
|
48
|
+
</style>
|
49
|
+
|
50
|
+
|
51
|
+
<ul id='number' class='listing inlined' style='background-color: yellow'>
|
52
|
+
<li class='list-element odd'>
|
53
|
+
<span>1</span>
|
54
|
+
</li>
|
55
|
+
<li class='list-element pair'>
|
56
|
+
<span>2</span>
|
57
|
+
</li>
|
58
|
+
<li class='list-element odd'>
|
59
|
+
<span>3</span>
|
60
|
+
</li>
|
61
|
+
<li class='list-element pair'>
|
62
|
+
<span>4</span>
|
63
|
+
</li>
|
64
|
+
</ul>
|
65
|
+
|
66
|
+
Will output:
|
67
|
+
|
68
|
+
<ul id="number" class="listing inlined" style='font-family: "Lucida Grande", Lucida, Verdana, sans-serif;margin: 4.0px 3.0px 2.0px 1.0px;padding: 0.0;background-color: yellow;'>
|
69
|
+
<li class="list-element odd" style='font-family: "Lucida Grande", Lucida, Verdana, sans-serif;margin: 4.0px 3.0px 2.0px 1.0px;padding: 0.0;background-color: black;'>
|
70
|
+
<span style='font-family: "Lucida Grande", Lucida, Verdana, sans-serif;margin: 4.0px 3.0px 2.0px 1.0px;padding: 0.0;'>1</span>
|
71
|
+
</li>
|
72
|
+
<li class="list-element pair" style='font-family: "Lucida Grande", Lucida, Verdana, sans-serif;margin: 4.0px 3.0px 2.0px 1.0px;padding: 0.0;background-color: red;'>
|
73
|
+
<span style='font-family: "Lucida Grande", Lucida, Verdana, sans-serif;margin: 4.0px 3.0px 2.0px 1.0px;padding: 0.0;'>2</span>
|
74
|
+
</li>
|
75
|
+
<li class="list-element odd" style='font-family: "Lucida Grande", Lucida, Verdana, sans-serif;margin: 4.0px 3.0px 2.0px 1.0px;padding: 0.0;background-color: black;'>
|
76
|
+
<span style='font-family: "Lucida Grande", Lucida, Verdana, sans-serif;margin: 4.0px 3.0px 2.0px 1.0px;padding: 0.0;'>3</span>
|
77
|
+
</li>
|
78
|
+
<li class="list-element pair" style='font-family: "Lucida Grande", Lucida, Verdana, sans-serif;margin: 4.0px 3.0px 2.0px 1.0px;padding: 0.0;background-color: red;'>
|
79
|
+
<span style='font-family: "Lucida Grande", Lucida, Verdana, sans-serif;margin: 4.0px 3.0px 2.0px 1.0px;padding: 0.0;'>4</span>
|
80
|
+
</li>
|
81
|
+
</ul>
|
82
|
+
|
83
|
+
As rack middleware:
|
84
|
+
|
85
|
+
# Process all routes:
|
86
|
+
use InlineStyle::Rack::Middleware
|
87
|
+
|
88
|
+
# Restrict processing to single route:
|
89
|
+
use InlineStyle::Rack::Middleware, :paths => %r(/mails/.*)
|
90
|
+
|
91
|
+
# Restrict processing to some routes:
|
92
|
+
use InlineStyle::Rack::Middleware, :paths => [%r(/mails/.*), "/somepath"]
|
93
|
+
|
94
|
+
== ISSUES:
|
95
|
+
|
96
|
+
* Doesn't work with relative stylesheet links
|
97
|
+
|
98
|
+
== REQUIREMENTS:
|
99
|
+
|
100
|
+
tenderlove's nokogiri and csspool
|
101
|
+
|
102
|
+
== INSTALL:
|
103
|
+
|
104
|
+
* FIX (sudo gem install, anything else)
|
105
|
+
|
106
|
+
== LICENSE:
|
107
|
+
|
108
|
+
(The MIT License)
|
109
|
+
|
110
|
+
Copyright (c) 2009 Macario Ortega
|
111
|
+
|
112
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
113
|
+
a copy of this software and associated documentation files (the
|
114
|
+
'Software'), to deal in the Software without restriction, including
|
115
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
116
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
117
|
+
permit persons to whom the Software is furnished to do so, subject to
|
118
|
+
the following conditions:
|
119
|
+
|
120
|
+
The above copyright notice and this permission notice shall be
|
121
|
+
included in all copies or substantial portions of the Software.
|
122
|
+
|
123
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
124
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
125
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
126
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
127
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
128
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
129
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rubygems' unless ENV['NO_RUBYGEMS']
|
2
|
+
%w[rake rake/clean fileutils newgem rubigen].each { |f| require f }
|
3
|
+
require File.dirname(__FILE__) + '/lib/inline-style'
|
4
|
+
|
5
|
+
$hoe = Hoe.new('inline-style', InlineStyle::VERSION) do |p|
|
6
|
+
p.developer('Macario Ortega', 'macarui@gmail.com')
|
7
|
+
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
|
8
|
+
p.rubyforge_name = p.name
|
9
|
+
p.extra_deps = [
|
10
|
+
['nokogiri','>= 1.3.3'],
|
11
|
+
['csspool', '>= 2.0.0']
|
12
|
+
]
|
13
|
+
p.extra_dev_deps = [
|
14
|
+
['newgem', ">= #{::Newgem::VERSION}"]
|
15
|
+
]
|
16
|
+
|
17
|
+
p.clean_globs |= %w[**/.DS_Store tmp *.log]
|
18
|
+
path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
|
19
|
+
p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
|
20
|
+
p.rsync_args = '-av --delete --ignore-errors'
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'newgem/tasks'
|
24
|
+
Dir['tasks/**/*.rake'].each { |t| load t }
|
25
|
+
|
26
|
+
|
data/example.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{inline-style}
|
5
|
+
s.version = "0.0.1"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Macario Ortega"]
|
9
|
+
s.date = %q{2009-10-22}
|
10
|
+
s.description = %q{Simple utility for "inlining" all CSS in the style attribute for the html tags. Useful for html emails that won't
|
11
|
+
correctly render stylesheets in some clients such as gmail.
|
12
|
+
|
13
|
+
* Includes a Rack middleware for using with Rails, Sinatra, etc...
|
14
|
+
* It takes into account selector specificity.}
|
15
|
+
s.email = ["macarui@gmail.com"]
|
16
|
+
s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.rdoc"]
|
17
|
+
s.files = ["History.txt", "Manifest.txt", "README.rdoc", "Rakefile", "example.rb", "inline-style.gemspec", "lib/inline-style.rb", "lib/inline-style/rack/middleware.rb", "rack-inline-styles.gemspec", "spec/as_middleware_spec.rb", "spec/css_inlining_spec.rb", "spec/fixtures/style.css", "spec/fixtures/with-style-tag.html", "spec/spec_helper.rb"]
|
18
|
+
s.homepage = %q{http://github.com/maca/inline-style}
|
19
|
+
s.rdoc_options = ["--main", "README.rdoc"]
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
s.rubyforge_project = %q{inline-style}
|
22
|
+
s.rubygems_version = %q{1.3.5}
|
23
|
+
s.summary = %q{Simple utility for "inlining" all CSS in the style attribute for the html tags}
|
24
|
+
|
25
|
+
if s.respond_to? :specification_version then
|
26
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
27
|
+
s.specification_version = 3
|
28
|
+
|
29
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
30
|
+
s.add_runtime_dependency(%q<nokogiri>, [">= 1.3.3"])
|
31
|
+
s.add_runtime_dependency(%q<csspool>, [">= 2.0.0"])
|
32
|
+
s.add_development_dependency(%q<newgem>, [">= 1.4.1"])
|
33
|
+
s.add_development_dependency(%q<hoe>, [">= 1.8.0"])
|
34
|
+
else
|
35
|
+
s.add_dependency(%q<nokogiri>, [">= 1.3.3"])
|
36
|
+
s.add_dependency(%q<csspool>, [">= 2.0.0"])
|
37
|
+
s.add_dependency(%q<newgem>, [">= 1.4.1"])
|
38
|
+
s.add_dependency(%q<hoe>, [">= 1.8.0"])
|
39
|
+
end
|
40
|
+
else
|
41
|
+
s.add_dependency(%q<nokogiri>, [">= 1.3.3"])
|
42
|
+
s.add_dependency(%q<csspool>, [">= 2.0.0"])
|
43
|
+
s.add_dependency(%q<newgem>, [">= 1.4.1"])
|
44
|
+
s.add_dependency(%q<hoe>, [">= 1.8.0"])
|
45
|
+
end
|
46
|
+
end
|
data/lib/inline-style.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'open-uri'
|
3
|
+
require 'csspool'
|
4
|
+
|
5
|
+
require "#{ File.dirname( __FILE__ ) }/inline-style/rack/middleware"
|
6
|
+
|
7
|
+
module InlineStyle
|
8
|
+
VERSION = '0.0.1'
|
9
|
+
|
10
|
+
def self.process html, document_root
|
11
|
+
nokogiri_doc_given = Nokogiri::HTML::Document === html
|
12
|
+
|
13
|
+
html = nokogiri_doc_given ? html : Nokogiri.HTML(html)
|
14
|
+
css = extract_css html, document_root
|
15
|
+
nodes = {}
|
16
|
+
|
17
|
+
css.rule_sets.each do |rule_set|
|
18
|
+
rule_set.selectors.each do |selector|
|
19
|
+
html.css("body #{ selector }").each do |node|
|
20
|
+
nodes[node] ||= []
|
21
|
+
nodes[node].push selector
|
22
|
+
|
23
|
+
next unless node['style']
|
24
|
+
|
25
|
+
path = node.css_path
|
26
|
+
path << "##{ node['id'] }" if node['id']
|
27
|
+
path << ".#{ node['class'].scan(/\S+/).join('.') }" if node['class']
|
28
|
+
|
29
|
+
CSSPool.CSS("#{ path }{#{ node['style'] }}").rule_sets.each{ |rule| nodes[node].push *rule.selectors}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
nodes.each_pair do |node, style|
|
35
|
+
style = style.sort_by{ |sel| "#{ sel.specificity }#{ style.index sel }" } #TO fix
|
36
|
+
style.map!{ |sel| sel.declarations.map{ |d| d.to_css.strip }.join } and style.uniq!
|
37
|
+
node['style'] = style.join
|
38
|
+
end
|
39
|
+
|
40
|
+
nokogiri_doc_given ? html : html.to_s
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.extract_css html, document_root
|
44
|
+
CSSPool.CSS html.css('style, link').collect { |e|
|
45
|
+
next unless e['media'].nil? or e['media'].match /\bscreen\b/
|
46
|
+
next(e.remove and e.content) if e.name == 'style'
|
47
|
+
next unless e['rel'] == 'stylesheet'
|
48
|
+
e.remove
|
49
|
+
next open(e['href']).read if %r{^https?://} === e['href']
|
50
|
+
File.read File.join(document_root, e['href'])
|
51
|
+
}.join("\n")
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module InlineStyle
|
2
|
+
module Rack
|
3
|
+
|
4
|
+
class Middleware
|
5
|
+
# Options:
|
6
|
+
# +document_root+
|
7
|
+
# File system path for app's public directory where the stylesheets are to be found, defaults to
|
8
|
+
# env['DOCUMENT_ROOT']
|
9
|
+
#
|
10
|
+
# +paths+
|
11
|
+
# Limit processing to the passed absolute paths
|
12
|
+
# Can be an array of strings or regular expressions, a single string or regular expression
|
13
|
+
# If not passed will process output for every path
|
14
|
+
def initialize app, opts = {}
|
15
|
+
@app = app
|
16
|
+
@document_root = opts[:document_root]
|
17
|
+
@paths = Regexp.new [*opts[:paths]].join('|')
|
18
|
+
end
|
19
|
+
|
20
|
+
def call env
|
21
|
+
response = @app.call env
|
22
|
+
return response unless @paths === env['PATH_INFO']
|
23
|
+
|
24
|
+
status, headers, content = response
|
25
|
+
response = ::Rack::Response.new '', status, headers
|
26
|
+
body = content.respond_to?(:body) ? content.body : content
|
27
|
+
|
28
|
+
response.write InlineStyle.process(body, @document_root || env['DOCUMENT_ROOT'])
|
29
|
+
response.finish
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{rack-inline-styles}
|
5
|
+
s.version = "0.0.1"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Macario Ortega"]
|
9
|
+
s.date = %q{2009-10-16}
|
10
|
+
s.description = %q{FIX (describe your package)}
|
11
|
+
s.email = ["macarui@gmail.com"]
|
12
|
+
s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.rdoc"]
|
13
|
+
s.files = [".git/HEAD", ".git/config", ".git/description", ".git/hooks/applypatch-msg", ".git/hooks/commit-msg", ".git/hooks/post-commit", ".git/hooks/post-receive", ".git/hooks/post-update", ".git/hooks/pre-applypatch", ".git/hooks/pre-commit", ".git/hooks/pre-rebase", ".git/hooks/update", ".git/index", ".git/info/exclude", ".git/objects/14/fa7459b8ceed4fef2dae431412c51591335354", ".git/objects/2c/0095bcd01468cbafdbb01befcd08cd60ccfb78", ".git/objects/37/04bf0d18ced6f7c6a85467ca3ae017e87d9bf4", ".git/objects/55/8a5df09d6f6b75f07504dd86ead7a0078c9031", ".git/objects/a6/cfe2d2693a7d73be08898b26a1f44886878c21", ".git/objects/e4/f29ca4d0099d827535a935fed78a2aa70fb3e7", ".git/objects/f0/4fbfb5595b8187bf753bdedebb89ee835c28ef", "History.txt", "Manifest.txt", "README.rdoc", "Rakefile", "lib/rack/inline-styles.rb", "rack-inline-styles.gemspec", "spec/spec_helper.rb"]
|
14
|
+
s.has_rdoc = true
|
15
|
+
s.homepage = %q{http://github.com/#{github_username}/#{project_name}}
|
16
|
+
s.rdoc_options = ["--main", "README.rdoc"]
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.rubyforge_project = %q{rack-inline-styles}
|
19
|
+
s.rubygems_version = %q{1.3.1}
|
20
|
+
s.summary = %q{FIX (describe your package)}
|
21
|
+
|
22
|
+
if s.respond_to? :specification_version then
|
23
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
24
|
+
s.specification_version = 2
|
25
|
+
|
26
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
27
|
+
s.add_development_dependency(%q<newgem>, [">= 1.4.1"])
|
28
|
+
s.add_development_dependency(%q<hoe>, [">= 1.8.0"])
|
29
|
+
else
|
30
|
+
s.add_dependency(%q<newgem>, [">= 1.4.1"])
|
31
|
+
s.add_dependency(%q<hoe>, [">= 1.8.0"])
|
32
|
+
end
|
33
|
+
else
|
34
|
+
s.add_dependency(%q<newgem>, [">= 1.4.1"])
|
35
|
+
s.add_dependency(%q<hoe>, [">= 1.8.0"])
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require "#{ File.dirname __FILE__ }/spec_helper"
|
2
|
+
|
3
|
+
describe InlineStyle::Rack::Middleware do
|
4
|
+
|
5
|
+
def get_response path, body, opts = {}
|
6
|
+
content_type = opts.delete(:content_type) || 'text/html'
|
7
|
+
app = Rack::Builder.new do
|
8
|
+
use InlineStyle::Rack::Middleware, opts
|
9
|
+
run lambda { |env| env['DOCUMENT_ROOT'] = FIXTURES; [200, {'Content-Type' => content_type}, body ] }
|
10
|
+
end
|
11
|
+
Nokogiri.HTML Rack::MockRequest.new(app).get(path).body
|
12
|
+
end
|
13
|
+
|
14
|
+
before do
|
15
|
+
@html = File.read("#{ FIXTURES }/with-style-tag.html")
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should inline css" do
|
19
|
+
get_response('/', @html, :stylesheets_path => FIXTURES).should have_inline_style_for('.list-element')
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'Path inclusion' do
|
23
|
+
|
24
|
+
it "should inline style for string path" do
|
25
|
+
paths = "/some/path"
|
26
|
+
get_response('/some/path', @html, :stylesheets_path => FIXTURES, :paths => paths).should have_inline_style_for('.list-element')
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should not inline style for string path" do
|
30
|
+
paths = "/some/path"
|
31
|
+
get_response('/some/other/path', @html, :stylesheets_path => FIXTURES, :paths => paths).should_not have_inline_style_for('.list-element')
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should inline style for regexp path" do
|
35
|
+
paths = %r{some/.*}
|
36
|
+
get_response('/some/path', @html, :stylesheets_path => FIXTURES, :paths => paths).should have_inline_style_for('.list-element')
|
37
|
+
get_response('/some/other/path', @html, :stylesheets_path => FIXTURES, :paths => paths).should have_inline_style_for('.list-element')
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should not inline style for regexp path" do
|
41
|
+
paths = %r{some/.*}
|
42
|
+
get_response('/other/path', @html, :stylesheets_path => FIXTURES, :paths => paths).should_not have_inline_style_for('.list-element')
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should inline style for array regexp path" do
|
46
|
+
paths = [%r{some/path}, %r{/some/other/path}]
|
47
|
+
get_response('/some/path', @html, :stylesheets_path => FIXTURES, :paths => paths).should have_inline_style_for('.list-element')
|
48
|
+
get_response('/some/other/path', @html, :stylesheets_path => FIXTURES, :paths => paths).should have_inline_style_for('.list-element')
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should not inline style for array regexp path" do
|
52
|
+
paths = [%r{some/path}, %r{/some/other/path}]
|
53
|
+
get_response('/path', @html, :stylesheets_path => FIXTURES, :paths => paths).should_not have_inline_style_for('.list-element')
|
54
|
+
get_response('/other/path', @html, :stylesheets_path => FIXTURES, :paths => paths).should_not have_inline_style_for('.list-element')
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "#{ dir = File.dirname(__FILE__) }/../lib/inline-style"
|
2
|
+
|
3
|
+
describe InlineStyle do
|
4
|
+
describe 'CSS extraction' do
|
5
|
+
it "should extract from style tag"
|
6
|
+
it "should extract from link"
|
7
|
+
end
|
8
|
+
|
9
|
+
describe 'CSS processing' do
|
10
|
+
it 'should separate terms by space'
|
11
|
+
it 'should separate terms by coma'
|
12
|
+
it 'should order selectors by specificity'
|
13
|
+
it 'should order selectors by specificity and defininition order'
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
# It should order selectors by specificity
|
23
|
+
# it should order selectors by specificity and defininition order
|
24
|
+
# It should apply inline style by tag
|
25
|
+
# It should apply inline style by universal selector
|
26
|
+
# It should apply inline style for class
|
27
|
+
# It should apply inline style for id
|
28
|
+
# It should overwrite rule with less specificity
|
29
|
+
# It should overwrite rule previously defined
|
30
|
+
# It should not overwrite rules defined inline
|
@@ -0,0 +1,55 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
2
|
+
"http://www.w3.org/TR/html4/loose.dtd">
|
3
|
+
|
4
|
+
<html lang="en">
|
5
|
+
<head>
|
6
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
7
|
+
|
8
|
+
<style type="text/css" media="screen">
|
9
|
+
* {
|
10
|
+
font-family: "Lucida Grande", Lucida, Verdana, sans-serif;
|
11
|
+
margin: 4px 3px 2px 1px;
|
12
|
+
padding: 0;
|
13
|
+
}
|
14
|
+
|
15
|
+
#list {
|
16
|
+
margin: 10;
|
17
|
+
}
|
18
|
+
|
19
|
+
#list li {
|
20
|
+
font-family: Arial;
|
21
|
+
}
|
22
|
+
|
23
|
+
.element {
|
24
|
+
padding: 10;
|
25
|
+
}
|
26
|
+
|
27
|
+
.odd {
|
28
|
+
background-color: black;
|
29
|
+
}
|
30
|
+
|
31
|
+
.pair {
|
32
|
+
background-color: red;
|
33
|
+
}
|
34
|
+
|
35
|
+
</style>
|
36
|
+
<link rel="stylesheet" href="style.css" type="text/css" media="screen" title="no title" charset="utf-8">
|
37
|
+
|
38
|
+
</head>
|
39
|
+
<body>
|
40
|
+
<ul id='number' class='listing inlined' style='background-color: yellow'>
|
41
|
+
<li class='list-element odd'>
|
42
|
+
<span>1</span>
|
43
|
+
</li>
|
44
|
+
<li class='list-element pair'>
|
45
|
+
<span>2</span>
|
46
|
+
</li>
|
47
|
+
<li class='list-element odd'>
|
48
|
+
<span>3</span>
|
49
|
+
</li>
|
50
|
+
<li class='list-element pair'>
|
51
|
+
<span>4</span>
|
52
|
+
</li>
|
53
|
+
</ul>
|
54
|
+
</body>
|
55
|
+
</html>
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'spec'
|
3
|
+
require "#{ DIR = File.dirname(__FILE__) }/../lib/inline-style"
|
4
|
+
require 'rack'
|
5
|
+
require 'rack/mock'
|
6
|
+
|
7
|
+
FIXTURES = "#{ DIR }/fixtures"
|
8
|
+
|
9
|
+
|
10
|
+
module HaveInlineStyleMatcher
|
11
|
+
class HaveInlineStyle
|
12
|
+
def initialize selector
|
13
|
+
@selector = selector
|
14
|
+
end
|
15
|
+
|
16
|
+
def matches? html
|
17
|
+
@html = html
|
18
|
+
@html.css(@selector).inject(true){ |bool, e| bool and !e['style'].nil? }
|
19
|
+
end
|
20
|
+
|
21
|
+
def failure_message
|
22
|
+
"expected elements with selector #{ @selector } style attribute not to be nil"
|
23
|
+
end
|
24
|
+
|
25
|
+
def negative_failure_message
|
26
|
+
"expected elements with selector #{ @selector } style attribute to be nil"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def have_inline_style_for selector
|
31
|
+
HaveInlineStyle.new selector
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
Spec::Runner.configure { |config| config.include HaveInlineStyleMatcher }
|
metadata
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: inline-style
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Macario Ortega
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-10-22 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: nokogiri
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.3.3
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: csspool
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.0.0
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: newgem
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.4.1
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: hoe
|
47
|
+
type: :development
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.8.0
|
54
|
+
version:
|
55
|
+
description: |-
|
56
|
+
Simple utility for "inlining" all CSS in the style attribute for the html tags. Useful for html emails that won't
|
57
|
+
correctly render stylesheets in some clients such as gmail.
|
58
|
+
|
59
|
+
* Includes a Rack middleware for using with Rails, Sinatra, etc...
|
60
|
+
* It takes into account selector specificity.
|
61
|
+
email:
|
62
|
+
- macarui@gmail.com
|
63
|
+
executables: []
|
64
|
+
|
65
|
+
extensions: []
|
66
|
+
|
67
|
+
extra_rdoc_files:
|
68
|
+
- History.txt
|
69
|
+
- Manifest.txt
|
70
|
+
- README.rdoc
|
71
|
+
files:
|
72
|
+
- History.txt
|
73
|
+
- Manifest.txt
|
74
|
+
- README.rdoc
|
75
|
+
- Rakefile
|
76
|
+
- example.rb
|
77
|
+
- inline-style.gemspec
|
78
|
+
- lib/inline-style.rb
|
79
|
+
- lib/inline-style/rack/middleware.rb
|
80
|
+
- rack-inline-styles.gemspec
|
81
|
+
- spec/as_middleware_spec.rb
|
82
|
+
- spec/css_inlining_spec.rb
|
83
|
+
- spec/fixtures/style.css
|
84
|
+
- spec/fixtures/with-style-tag.html
|
85
|
+
- spec/spec_helper.rb
|
86
|
+
has_rdoc: true
|
87
|
+
homepage: http://github.com/maca/inline-style
|
88
|
+
licenses: []
|
89
|
+
|
90
|
+
post_install_message:
|
91
|
+
rdoc_options:
|
92
|
+
- --main
|
93
|
+
- README.rdoc
|
94
|
+
require_paths:
|
95
|
+
- lib
|
96
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: "0"
|
101
|
+
version:
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: "0"
|
107
|
+
version:
|
108
|
+
requirements: []
|
109
|
+
|
110
|
+
rubyforge_project: inline-style
|
111
|
+
rubygems_version: 1.3.5
|
112
|
+
signing_key:
|
113
|
+
specification_version: 3
|
114
|
+
summary: Simple utility for "inlining" all CSS in the style attribute for the html tags
|
115
|
+
test_files: []
|
116
|
+
|