roadie 3.0.5 → 3.1.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -7
- data/.travis.yml +1 -5
- data/Changelog.md +20 -1
- data/Guardfile +2 -1
- data/README.md +193 -53
- data/lib/roadie.rb +3 -2
- data/lib/roadie/asset_scanner.rb +30 -10
- data/lib/roadie/cached_provider.rb +77 -0
- data/lib/roadie/document.rb +29 -10
- data/lib/roadie/errors.rb +43 -1
- data/lib/roadie/filesystem_provider.rb +3 -1
- data/lib/roadie/inliner.rb +57 -27
- data/lib/roadie/markup_improver.rb +2 -1
- data/lib/roadie/net_http_provider.rb +70 -0
- data/lib/roadie/null_provider.rb +3 -0
- data/lib/roadie/path_rewriter_provider.rb +64 -0
- data/lib/roadie/provider_list.rb +19 -1
- data/lib/roadie/rspec.rb +1 -0
- data/lib/roadie/rspec/cache_store.rb +25 -0
- data/lib/roadie/stylesheet.rb +1 -0
- data/lib/roadie/url_generator.rb +2 -1
- data/lib/roadie/utils.rb +9 -0
- data/lib/roadie/version.rb +1 -1
- data/roadie.gemspec +2 -1
- data/spec/hash_as_cache_store_spec.rb +7 -0
- data/spec/integration_spec.rb +91 -0
- data/spec/lib/roadie/asset_scanner_spec.rb +79 -25
- data/spec/lib/roadie/cached_provider_spec.rb +52 -0
- data/spec/lib/roadie/document_spec.rb +43 -7
- data/spec/lib/roadie/filesystem_provider_spec.rb +5 -0
- data/spec/lib/roadie/inliner_spec.rb +72 -15
- data/spec/lib/roadie/net_http_provider_spec.rb +89 -0
- data/spec/lib/roadie/path_rewriter_provider_spec.rb +39 -0
- data/spec/lib/roadie/provider_list_spec.rb +31 -8
- data/spec/lib/roadie/stylesheet_spec.rb +14 -8
- data/spec/lib/roadie/utils_spec.rb +7 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/support/have_styling_matcher.rb +1 -0
- metadata +40 -9
- data/lib/roadie/upgrade_guide.rb +0 -36
@@ -0,0 +1,70 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'set'
|
3
|
+
require 'uri'
|
4
|
+
require 'net/http'
|
5
|
+
|
6
|
+
module Roadie
|
7
|
+
# @api public
|
8
|
+
# External asset provider that downloads stylesheets from some other server
|
9
|
+
# using Ruby's built-in {Net::HTTP} library.
|
10
|
+
#
|
11
|
+
# You can pass a whitelist of hosts that downloads are allowed on.
|
12
|
+
#
|
13
|
+
# @example Allowing all downloads
|
14
|
+
# provider = Roadie::NetHttpProvider.new
|
15
|
+
#
|
16
|
+
# @example Only allowing your own app domains
|
17
|
+
# provider = Roadie::NetHttpProvider.new(
|
18
|
+
# whitelist: ["myapp.com", "assets.myapp.com", "www.myapp.com"]
|
19
|
+
# )
|
20
|
+
class NetHttpProvider
|
21
|
+
attr_reader :whitelist
|
22
|
+
|
23
|
+
# @option options [Array<String>] :whitelist ([]) A list of host names that downloads are allowed from. Empty set means everything is allowed.
|
24
|
+
def initialize(options = {})
|
25
|
+
@whitelist = Array(options.fetch(:whitelist, [])).to_set
|
26
|
+
end
|
27
|
+
|
28
|
+
def find_stylesheet(url)
|
29
|
+
find_stylesheet!(url)
|
30
|
+
rescue CssNotFound
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
|
34
|
+
def find_stylesheet!(url)
|
35
|
+
response = download(url)
|
36
|
+
if response.kind_of? Net::HTTPSuccess
|
37
|
+
Stylesheet.new url, response.body
|
38
|
+
else
|
39
|
+
raise CssNotFound.new(url, "Server returned #{response.code}: #{truncate response.body}", self)
|
40
|
+
end
|
41
|
+
rescue Timeout::Error
|
42
|
+
raise CssNotFound.new(url, "Timeout", self)
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_s() inspect end
|
46
|
+
def inspect() "#<#{self.class} whitelist: #{whitelist.inspect}>" end
|
47
|
+
|
48
|
+
private
|
49
|
+
def download(url)
|
50
|
+
uri = URI.parse(url)
|
51
|
+
if access_granted_to?(uri.host)
|
52
|
+
Net::HTTP.get_response(uri)
|
53
|
+
else
|
54
|
+
raise CssNotFound.new(url, "#{uri.host} is not part of whitelist!", self)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def access_granted_to?(host)
|
59
|
+
whitelist.empty? || whitelist.include?(host)
|
60
|
+
end
|
61
|
+
|
62
|
+
def truncate(string)
|
63
|
+
if string.length > 50
|
64
|
+
string[0, 49] + "…"
|
65
|
+
else
|
66
|
+
string
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/roadie/null_provider.rb
CHANGED
@@ -0,0 +1,64 @@
|
|
1
|
+
module Roadie
|
2
|
+
# @api public
|
3
|
+
# This provider acts a bit like a pipeline in normal UNIX parlour by enabling
|
4
|
+
# you to make changes to the requested path. Some uses of this include:
|
5
|
+
#
|
6
|
+
# * Convert absolute URLs into local filesystem paths.
|
7
|
+
# * Convert between external DNS name into internal naming.
|
8
|
+
# * Changing path structure of filenames.
|
9
|
+
# * Removing digests from filenames.
|
10
|
+
# * Handle query string logic.
|
11
|
+
# * Skipping known-bad paths.
|
12
|
+
#
|
13
|
+
# There might be other useful things you could use it for. The basic premise
|
14
|
+
# is that a path is sent in to this provider, maybe modified and then passed
|
15
|
+
# on to the "upstream" provider (or {ProviderList}).
|
16
|
+
#
|
17
|
+
# If the block returns {nil} or {false}, the upstream provider will not be
|
18
|
+
# invoked and it will be treated as "not found". This makes it possible to
|
19
|
+
# use this provider as a filter only.
|
20
|
+
#
|
21
|
+
# @example Simple regex
|
22
|
+
# provider = Roadie::PathRewriterProvider.new(other_provider) { |path|
|
23
|
+
# path.gsub(/-[a-f0-9]+\.css$/, '.css')
|
24
|
+
# }
|
25
|
+
#
|
26
|
+
# @example Filtering assets
|
27
|
+
# # Only assets containing "email" in the path will be considered by other_provider
|
28
|
+
# only_email_provider = Roadie::PathRewriterProvider.new(other_provider) { |path|
|
29
|
+
# path =~ /email/ ? path : nil
|
30
|
+
# }
|
31
|
+
#
|
32
|
+
# @example Handling "external" app assets as local assets
|
33
|
+
# document.external_asset_providers = [
|
34
|
+
# # Look for assets from "myapp.com" just like if we just specified a local path
|
35
|
+
# Roadie::PathRewriterProvider.new(document.asset_providers) { |url|
|
36
|
+
# uri = URI.parse(url)
|
37
|
+
# uri.path if uri.host == "myapp.com"
|
38
|
+
# },
|
39
|
+
# # Any other asset should be downloaded like normal
|
40
|
+
# Roadie::NetHttpProvider.new
|
41
|
+
# ]
|
42
|
+
class PathRewriterProvider
|
43
|
+
attr_reader :provider, :filter
|
44
|
+
|
45
|
+
def initialize(provider, &filter)
|
46
|
+
@provider = provider
|
47
|
+
@filter = filter
|
48
|
+
end
|
49
|
+
|
50
|
+
def find_stylesheet(path)
|
51
|
+
new_path = filter.call(path)
|
52
|
+
provider.find_stylesheet(new_path) if new_path
|
53
|
+
end
|
54
|
+
|
55
|
+
def find_stylesheet!(path)
|
56
|
+
new_path = filter.call(path)
|
57
|
+
if new_path
|
58
|
+
provider.find_stylesheet!(new_path)
|
59
|
+
else
|
60
|
+
raise CssNotFound, "Filter returned #{new_path.inspect}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/lib/roadie/provider_list.rb
CHANGED
@@ -9,7 +9,6 @@ module Roadie
|
|
9
9
|
class ProviderList
|
10
10
|
extend Forwardable
|
11
11
|
include Enumerable
|
12
|
-
include AssetProvider
|
13
12
|
|
14
13
|
# Wrap a single provider, or a list of providers into a {ProviderList}.
|
15
14
|
#
|
@@ -31,6 +30,9 @@ module Roadie
|
|
31
30
|
end
|
32
31
|
end
|
33
32
|
|
33
|
+
# Returns a new empty list.
|
34
|
+
def self.empty() new([]) end
|
35
|
+
|
34
36
|
def initialize(providers)
|
35
37
|
@providers = providers
|
36
38
|
end
|
@@ -44,6 +46,22 @@ module Roadie
|
|
44
46
|
nil
|
45
47
|
end
|
46
48
|
|
49
|
+
# Tries to find the given stylesheet and raises an {ProvidersFailed} error
|
50
|
+
# if no provider could find the asset.
|
51
|
+
#
|
52
|
+
# @return [Stylesheet]
|
53
|
+
def find_stylesheet!(name)
|
54
|
+
errors = []
|
55
|
+
@providers.each do |provider|
|
56
|
+
begin
|
57
|
+
return provider.find_stylesheet!(name)
|
58
|
+
rescue CssNotFound => error
|
59
|
+
errors << error
|
60
|
+
end
|
61
|
+
end
|
62
|
+
raise ProvidersFailed.new(name, self, errors)
|
63
|
+
end
|
64
|
+
|
47
65
|
def to_s
|
48
66
|
list = @providers.map { |provider|
|
49
67
|
# Indent every line one level
|
data/lib/roadie/rspec.rb
CHANGED
@@ -0,0 +1,25 @@
|
|
1
|
+
shared_examples_for "roadie cache store" do
|
2
|
+
it "allows storing Stylesheets" do
|
3
|
+
stylesheet = Roadie::Stylesheet.new("foo.css", "body { color: green; }")
|
4
|
+
expect(subject["foo"] = stylesheet).to eql stylesheet
|
5
|
+
end
|
6
|
+
|
7
|
+
it "allows retreiving stored stylesheets" do
|
8
|
+
stylesheet = Roadie::Stylesheet.new("foo.css", "body { color: green; }")
|
9
|
+
subject["foo"] = stylesheet
|
10
|
+
stored_stylesheet = subject["foo"]
|
11
|
+
expect(stored_stylesheet.to_s).to eq stylesheet.to_s
|
12
|
+
end
|
13
|
+
|
14
|
+
it "defaults to nil when cache does not contain path" do
|
15
|
+
expect(subject["bar"]).to be_nil
|
16
|
+
end
|
17
|
+
|
18
|
+
it "accepts nil assignments to clear cache" do
|
19
|
+
subject["foo"] = Roadie::Stylesheet.new("", "")
|
20
|
+
expect {
|
21
|
+
subject["foo"] = nil
|
22
|
+
}.to_not raise_error
|
23
|
+
expect(subject["foo"]).to be_nil
|
24
|
+
end
|
25
|
+
end
|
data/lib/roadie/stylesheet.rb
CHANGED
@@ -20,6 +20,7 @@ module Roadie
|
|
20
20
|
# @yield [selector, properties]
|
21
21
|
# @yieldparam [Selector] selector
|
22
22
|
# @yieldparam [Array<StyleProperty>] properties
|
23
|
+
# @deprecated Iterate over the #{blocks} instead. Will be removed on version 4.0.
|
23
24
|
def each_inlinable_block(&block)
|
24
25
|
# #map and then #each in order to support chained enumerations, etc. if
|
25
26
|
# no block is provided
|
data/lib/roadie/url_generator.rb
CHANGED
data/lib/roadie/utils.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
module Roadie
|
2
2
|
module Utils
|
3
|
+
# @api private
|
3
4
|
def path_is_absolute?(path)
|
4
5
|
# Ruby's URI is pretty unforgiving, but roadie aims to be. Don't involve
|
5
6
|
# URI for URLs that's easy to determine to be absolute.
|
@@ -15,6 +16,14 @@ module Roadie
|
|
15
16
|
raise InvalidUrlPath.new(path, error)
|
16
17
|
end
|
17
18
|
end
|
19
|
+
# @api private
|
18
20
|
module_function :path_is_absolute?
|
21
|
+
|
22
|
+
# @api private
|
23
|
+
def warn(message)
|
24
|
+
Kernel.warn("Roadie: #{message}")
|
25
|
+
end
|
26
|
+
# @api private
|
27
|
+
module_function :warn
|
19
28
|
end
|
20
29
|
end
|
data/lib/roadie/version.rb
CHANGED
data/roadie.gemspec
CHANGED
@@ -17,11 +17,12 @@ Gem::Specification.new do |s|
|
|
17
17
|
|
18
18
|
s.required_ruby_version = ">= 1.9"
|
19
19
|
|
20
|
-
s.add_dependency 'nokogiri', '
|
20
|
+
s.add_dependency 'nokogiri', '>= 1.5.0', '< 1.7.0'
|
21
21
|
s.add_dependency 'css_parser', '~> 1.3.4'
|
22
22
|
|
23
23
|
s.add_development_dependency 'rspec', '~> 3.0'
|
24
24
|
s.add_development_dependency 'rspec-collection_matchers', '~> 1.0'
|
25
|
+
s.add_development_dependency 'webmock', '~> 1.21.0'
|
25
26
|
|
26
27
|
s.extra_rdoc_files = %w[README.md Changelog.md]
|
27
28
|
s.require_paths = %w[lib]
|
data/spec/integration_spec.rb
CHANGED
@@ -48,6 +48,51 @@ describe "Roadie functionality" do
|
|
48
48
|
expect(result).to have_styling('color' => 'red').at_selector('p > em')
|
49
49
|
end
|
50
50
|
|
51
|
+
it "stores styles that cannot be inlined in the <head>" do
|
52
|
+
document = Roadie::Document.new <<-HTML
|
53
|
+
<html>
|
54
|
+
<body>
|
55
|
+
<h1>Hello world!</h1>
|
56
|
+
<p>Check out these <em>awesome</em> prices!</p>
|
57
|
+
</body>
|
58
|
+
</html>
|
59
|
+
HTML
|
60
|
+
css = <<-CSS
|
61
|
+
em:hover { color: red; }
|
62
|
+
p:fung-shuei { color: spirit; }
|
63
|
+
CSS
|
64
|
+
document.add_css css
|
65
|
+
expect(Roadie::Utils).to receive(:warn).with(/fung-shuei/)
|
66
|
+
|
67
|
+
result = parse_html document.transform
|
68
|
+
expect(result).to have_selector("html > head > style")
|
69
|
+
|
70
|
+
styles = result.at_css("html > head > style").text
|
71
|
+
expect(styles).to include Roadie::Stylesheet.new("", css).to_s
|
72
|
+
end
|
73
|
+
|
74
|
+
it "can be configured to skip styles that cannot be inlined" do
|
75
|
+
document = Roadie::Document.new <<-HTML
|
76
|
+
<html>
|
77
|
+
<body>
|
78
|
+
<h1>Hello world!</h1>
|
79
|
+
<p>Check out these <em>awesome</em> prices!</p>
|
80
|
+
</body>
|
81
|
+
</html>
|
82
|
+
HTML
|
83
|
+
css = <<-CSS
|
84
|
+
em:hover { color: red; }
|
85
|
+
p:fung-shuei { color: spirit; }
|
86
|
+
CSS
|
87
|
+
document.add_css css
|
88
|
+
document.keep_uninlinable_css = false
|
89
|
+
|
90
|
+
expect(Roadie::Utils).to receive(:warn).with(/fung-shuei/)
|
91
|
+
|
92
|
+
result = parse_html document.transform
|
93
|
+
expect(result).to_not have_selector("html > head > style")
|
94
|
+
end
|
95
|
+
|
51
96
|
it "inlines css from disk" do
|
52
97
|
document = Roadie::Document.new <<-HTML
|
53
98
|
<!DOCTYPE html>
|
@@ -85,6 +130,52 @@ describe "Roadie functionality" do
|
|
85
130
|
expect { document.transform }.to_not raise_error
|
86
131
|
end
|
87
132
|
|
133
|
+
it "ignores external css if no external providers are added" do
|
134
|
+
document = Roadie::Document.new <<-HTML
|
135
|
+
<!DOCTYPE html>
|
136
|
+
<html>
|
137
|
+
<head>
|
138
|
+
<title>Hello world!</title>
|
139
|
+
<link rel="stylesheet" href="http://example.com/big_em.css">
|
140
|
+
</head>
|
141
|
+
<body>
|
142
|
+
<h1>Hello world!</h1>
|
143
|
+
<p>Check out these <em>awesome</em> prices!</p>
|
144
|
+
</body>
|
145
|
+
</html>
|
146
|
+
HTML
|
147
|
+
|
148
|
+
document.external_asset_providers = []
|
149
|
+
|
150
|
+
result = parse_html document.transform
|
151
|
+
expect(result).to have_selector('head > link')
|
152
|
+
expect(result).to have_styling([]).at_selector('p > em')
|
153
|
+
end
|
154
|
+
|
155
|
+
it "inlines external css if configured" do
|
156
|
+
document = Roadie::Document.new <<-HTML
|
157
|
+
<!DOCTYPE html>
|
158
|
+
<html>
|
159
|
+
<head>
|
160
|
+
<title>Hello world!</title>
|
161
|
+
<link rel="stylesheet" href="http://example.com/big_em.css">
|
162
|
+
</head>
|
163
|
+
<body>
|
164
|
+
<h1>Hello world!</h1>
|
165
|
+
<p>Check out these <em>awesome</em> prices!</p>
|
166
|
+
</body>
|
167
|
+
</html>
|
168
|
+
HTML
|
169
|
+
|
170
|
+
document.external_asset_providers = TestProvider.new(
|
171
|
+
"http://example.com/big_em.css" => "em { font-size: 200%; }"
|
172
|
+
)
|
173
|
+
|
174
|
+
result = parse_html document.transform
|
175
|
+
expect(result).to have_styling('font-size' => '200%').at_selector('p > em')
|
176
|
+
expect(result).to_not have_selector('head > link')
|
177
|
+
end
|
178
|
+
|
88
179
|
it "makes URLs absolute" do
|
89
180
|
document = Roadie::Document.new <<-HTML
|
90
181
|
<!DOCTYPE html>
|
@@ -3,21 +3,23 @@ require 'spec_helper'
|
|
3
3
|
|
4
4
|
module Roadie
|
5
5
|
describe AssetScanner do
|
6
|
-
let(:
|
6
|
+
let(:normal_provider) { TestProvider.new }
|
7
|
+
let(:external_provider) { ProviderList.empty }
|
7
8
|
let(:dom) { dom_document "<html></html>" }
|
8
9
|
|
9
10
|
def dom_fragment(html); Nokogiri::HTML.fragment html; end
|
10
11
|
def dom_document(html); Nokogiri::HTML.parse html; end
|
11
12
|
|
12
|
-
it "is initialized with a DOM tree and
|
13
|
-
scanner = AssetScanner.new dom,
|
13
|
+
it "is initialized with a DOM tree, a normal asset provider set, and an external asset provider set" do
|
14
|
+
scanner = AssetScanner.new dom, normal_provider, external_provider
|
14
15
|
expect(scanner.dom).to eq(dom)
|
15
|
-
expect(scanner.
|
16
|
+
expect(scanner.normal_asset_provider).to eq(normal_provider)
|
17
|
+
expect(scanner.external_asset_provider).to eq(external_provider)
|
16
18
|
end
|
17
19
|
|
18
20
|
describe "finding" do
|
19
21
|
it "returns nothing when no stylesheets are referenced" do
|
20
|
-
scanner = AssetScanner.new dom,
|
22
|
+
scanner = AssetScanner.new dom, normal_provider, external_provider
|
21
23
|
expect(scanner.find_css).to eq([])
|
22
24
|
end
|
23
25
|
|
@@ -34,7 +36,7 @@ module Roadie
|
|
34
36
|
</body>
|
35
37
|
</html>
|
36
38
|
HTML
|
37
|
-
scanner = AssetScanner.new dom,
|
39
|
+
scanner = AssetScanner.new dom, normal_provider, external_provider
|
38
40
|
|
39
41
|
stylesheets = scanner.find_css
|
40
42
|
|
@@ -54,43 +56,56 @@ module Roadie
|
|
54
56
|
</head>
|
55
57
|
</html>
|
56
58
|
HTML
|
57
|
-
scanner = AssetScanner.new dom,
|
59
|
+
scanner = AssetScanner.new dom, normal_provider, external_provider
|
58
60
|
expect(scanner.find_css).to have(1).stylesheet
|
59
61
|
end
|
60
62
|
|
61
|
-
it "finds referenced stylesheets through the provider" do
|
63
|
+
it "finds normal referenced stylesheets through the normal provider" do
|
62
64
|
stylesheet = double "A stylesheet"
|
63
|
-
expect(
|
65
|
+
expect(normal_provider).to receive(:find_stylesheet!).with("/some/url.css").and_return stylesheet
|
64
66
|
|
65
67
|
dom = dom_fragment %(<link rel="stylesheet" href="/some/url.css">)
|
66
|
-
scanner = AssetScanner.new dom,
|
68
|
+
scanner = AssetScanner.new dom, normal_provider, external_provider
|
69
|
+
|
70
|
+
expect(scanner.find_css).to eq([stylesheet])
|
71
|
+
end
|
72
|
+
|
73
|
+
it "finds external referenced stylesheets through the external provider" do
|
74
|
+
stylesheet = double "A stylesheet"
|
75
|
+
external_provider = TestProvider.new
|
76
|
+
expect(external_provider).to receive(:find_stylesheet!).with("//example.com/style.css").and_return stylesheet
|
77
|
+
|
78
|
+
dom = dom_fragment %(<link rel="stylesheet" href="//example.com/style.css">)
|
79
|
+
scanner = AssetScanner.new dom, normal_provider, external_provider
|
67
80
|
|
68
81
|
expect(scanner.find_css).to eq([stylesheet])
|
69
82
|
end
|
70
83
|
|
71
84
|
it "ignores referenced print stylesheets" do
|
72
85
|
dom = dom_fragment %(<link rel="stylesheet" href="/error.css" media="print">)
|
73
|
-
expect(
|
86
|
+
expect(normal_provider).not_to receive(:find_stylesheet!)
|
74
87
|
|
75
|
-
scanner = AssetScanner.new dom,
|
88
|
+
scanner = AssetScanner.new dom, normal_provider, external_provider
|
76
89
|
|
77
90
|
expect(scanner.find_css).to eq([])
|
78
91
|
end
|
79
92
|
|
80
|
-
it "does not look for externally referenced stylesheets" do
|
93
|
+
it "does not look for externally referenced stylesheets from empty ProviderList" do
|
94
|
+
external_provider = ProviderList.empty
|
95
|
+
|
81
96
|
dom = dom_fragment %(<link rel="stylesheet" href="//example.com/assets/style.css">)
|
82
|
-
expect(
|
97
|
+
expect(external_provider).not_to receive(:find_stylesheet!)
|
83
98
|
|
84
|
-
scanner = AssetScanner.new dom,
|
99
|
+
scanner = AssetScanner.new dom, normal_provider, external_provider
|
85
100
|
|
86
101
|
expect(scanner.find_css).to eq([])
|
87
102
|
end
|
88
103
|
|
89
104
|
it "does not look for ignored referenced stylesheets" do
|
90
105
|
dom = dom_fragment %(<link rel="stylesheet" href="/error.css" data-roadie-ignore>)
|
91
|
-
expect(
|
106
|
+
expect(normal_provider).not_to receive(:find_stylesheet!)
|
92
107
|
|
93
|
-
scanner = AssetScanner.new dom,
|
108
|
+
scanner = AssetScanner.new dom, normal_provider, external_provider
|
94
109
|
|
95
110
|
expect(scanner.find_css).to eq([])
|
96
111
|
end
|
@@ -103,7 +118,7 @@ module Roadie
|
|
103
118
|
-->
|
104
119
|
]]></style>)
|
105
120
|
|
106
|
-
scanner = AssetScanner.new dom,
|
121
|
+
scanner = AssetScanner.new dom, normal_provider, external_provider
|
107
122
|
stylesheet = scanner.find_css.first
|
108
123
|
|
109
124
|
expect(stylesheet.to_s).to include("green")
|
@@ -119,7 +134,7 @@ module Roadie
|
|
119
134
|
</script>
|
120
135
|
HTML
|
121
136
|
|
122
|
-
scanner = AssetScanner.new dom,
|
137
|
+
scanner = AssetScanner.new dom, normal_provider, external_provider
|
123
138
|
expect(scanner.find_css).to eq([])
|
124
139
|
end
|
125
140
|
end
|
@@ -133,15 +148,15 @@ module Roadie
|
|
133
148
|
<style>span { color: green; }</style>
|
134
149
|
<link rel="stylesheet" href="/some/url.css">
|
135
150
|
<link rel="stylesheet" href="/error.css" media="print">
|
136
|
-
<link rel="stylesheet" href="/cool.css" data-roadie-ignore>
|
151
|
+
<link rel="stylesheet" href="/cool.css" data-roadie-ignore class="totally-ignored">
|
137
152
|
</head>
|
138
153
|
<body>
|
139
|
-
<style data-roadie-ignore>a { color: red; }</style>
|
154
|
+
<style data-roadie-ignore class="totally-ignored">a { color: red; }</style>
|
140
155
|
</body>
|
141
156
|
</html>
|
142
157
|
HTML
|
143
|
-
|
144
|
-
scanner = AssetScanner.new dom,
|
158
|
+
normal_provider = TestProvider.new "/some/url.css" => "body { color: green; }"
|
159
|
+
scanner = AssetScanner.new dom, normal_provider, external_provider
|
145
160
|
|
146
161
|
stylesheets = scanner.extract_css
|
147
162
|
|
@@ -150,13 +165,52 @@ module Roadie
|
|
150
165
|
expect(stylesheets[1].to_s).to include("body")
|
151
166
|
|
152
167
|
expect(dom).to have_selector("html > head > title")
|
153
|
-
expect(dom).to have_selector("html > body > style
|
154
|
-
expect(dom).to have_selector("link
|
168
|
+
expect(dom).to have_selector("html > body > style.totally-ignored")
|
169
|
+
expect(dom).to have_selector("link.totally-ignored")
|
155
170
|
expect(dom).to have_selector("link[media=print]")
|
156
171
|
|
157
172
|
expect(dom).not_to have_selector("html > head > style")
|
158
173
|
expect(dom).not_to have_selector("html > head > link[href='/some/url.css']")
|
159
174
|
end
|
175
|
+
|
176
|
+
it "removes external references if provider is not empty" do
|
177
|
+
dom = dom_document <<-HTML
|
178
|
+
<html>
|
179
|
+
<head>
|
180
|
+
<link rel="stylesheet" href="//some/url.css">
|
181
|
+
<link rel="stylesheet" href="//other/url.css" data-roadie-ignore>
|
182
|
+
</head>
|
183
|
+
</html>
|
184
|
+
HTML
|
185
|
+
external_provider = ProviderList.wrap(NullProvider.new)
|
186
|
+
scanner = AssetScanner.new dom, normal_provider, external_provider
|
187
|
+
|
188
|
+
stylesheets = scanner.extract_css
|
189
|
+
|
190
|
+
expect(stylesheets).to have(1).stylesheets
|
191
|
+
|
192
|
+
expect(dom).to_not have_selector("link[href*=some]")
|
193
|
+
expect(dom).to have_selector("link[href*=other]")
|
194
|
+
end
|
195
|
+
|
196
|
+
it "removes the data-roadie-ignore markers" do
|
197
|
+
dom = dom_document <<-HTML
|
198
|
+
<html>
|
199
|
+
<head>
|
200
|
+
<link rel="stylesheet" href="/cool.css" data-roadie-ignore id="first">
|
201
|
+
</head>
|
202
|
+
<body>
|
203
|
+
<style data-roadie-ignore id="second">a { color: red; }</style>
|
204
|
+
</body>
|
205
|
+
</html>
|
206
|
+
HTML
|
207
|
+
scanner = AssetScanner.new dom, TestProvider.new, external_provider
|
208
|
+
|
209
|
+
scanner.extract_css
|
210
|
+
|
211
|
+
expect(dom.at_css("#first").attributes).to_not include("data-roadie-ignore")
|
212
|
+
expect(dom.at_css("#second").attributes).to_not include("data-roadie-ignore")
|
213
|
+
end
|
160
214
|
end
|
161
215
|
end
|
162
216
|
end
|