roadie 2.4.3 → 3.0.0
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.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/.travis.yml +10 -14
- data/.yardopts +1 -1
- data/Changelog.md +38 -5
- data/Gemfile +3 -4
- data/Guardfile +12 -1
- data/README.md +168 -164
- data/Rakefile +2 -19
- data/lib/roadie.rb +15 -68
- data/lib/roadie/asset_provider.rb +7 -58
- data/lib/roadie/asset_scanner.rb +92 -0
- data/lib/roadie/document.rb +103 -0
- data/lib/roadie/errors.rb +57 -0
- data/lib/roadie/filesystem_provider.rb +30 -60
- data/lib/roadie/inliner.rb +72 -217
- data/lib/roadie/markup_improver.rb +88 -0
- data/lib/roadie/null_provider.rb +13 -0
- data/lib/roadie/null_url_rewriter.rb +12 -0
- data/lib/roadie/provider_list.rb +71 -0
- data/lib/roadie/rspec.rb +1 -0
- data/lib/roadie/rspec/asset_provider.rb +49 -0
- data/lib/roadie/selector.rb +43 -18
- data/lib/roadie/style_attribute_builder.rb +25 -0
- data/lib/roadie/style_block.rb +32 -0
- data/lib/roadie/style_property.rb +93 -0
- data/lib/roadie/stylesheet.rb +65 -0
- data/lib/roadie/upgrade_guide.rb +36 -0
- data/lib/roadie/url_generator.rb +126 -0
- data/lib/roadie/url_rewriter.rb +84 -0
- data/lib/roadie/version.rb +1 -1
- data/roadie.gemspec +8 -11
- data/spec/fixtures/big_em.css +1 -0
- data/spec/fixtures/stylesheets/green.css +1 -0
- data/spec/integration_spec.rb +125 -95
- data/spec/lib/roadie/asset_scanner_spec.rb +153 -0
- data/spec/lib/roadie/css_not_found_spec.rb +17 -0
- data/spec/lib/roadie/document_spec.rb +123 -0
- data/spec/lib/roadie/filesystem_provider_spec.rb +44 -68
- data/spec/lib/roadie/inliner_spec.rb +105 -537
- data/spec/lib/roadie/markup_improver_spec.rb +78 -0
- data/spec/lib/roadie/null_provider_spec.rb +21 -0
- data/spec/lib/roadie/null_url_rewriter_spec.rb +19 -0
- data/spec/lib/roadie/provider_list_spec.rb +89 -0
- data/spec/lib/roadie/selector_spec.rb +15 -10
- data/spec/lib/roadie/style_attribute_builder_spec.rb +29 -0
- data/spec/lib/roadie/style_block_spec.rb +35 -0
- data/spec/lib/roadie/style_property_spec.rb +82 -0
- data/spec/lib/roadie/stylesheet_spec.rb +41 -0
- data/spec/lib/roadie/test_provider_spec.rb +29 -0
- data/spec/lib/roadie/url_generator_spec.rb +121 -0
- data/spec/lib/roadie/url_rewriter_spec.rb +79 -0
- data/spec/shared_examples/asset_provider.rb +11 -0
- data/spec/shared_examples/url_rewriter.rb +23 -0
- data/spec/spec_helper.rb +6 -60
- data/spec/support/have_attribute_matcher.rb +2 -2
- data/spec/support/have_node_matcher.rb +4 -4
- data/spec/support/have_selector_matcher.rb +3 -3
- data/spec/support/have_styling_matcher.rb +51 -15
- data/spec/support/test_provider.rb +13 -0
- metadata +86 -175
- data/Appraisals +0 -15
- data/gemfiles/rails_3.0.gemfile +0 -7
- data/gemfiles/rails_3.0.gemfile.lock +0 -123
- data/gemfiles/rails_3.1.gemfile +0 -7
- data/gemfiles/rails_3.1.gemfile.lock +0 -126
- data/gemfiles/rails_3.2.gemfile +0 -7
- data/gemfiles/rails_3.2.gemfile.lock +0 -124
- data/gemfiles/rails_4.0.gemfile +0 -7
- data/gemfiles/rails_4.0.gemfile.lock +0 -119
- data/lib/roadie/action_mailer_extensions.rb +0 -95
- data/lib/roadie/asset_pipeline_provider.rb +0 -28
- data/lib/roadie/css_file_not_found.rb +0 -22
- data/lib/roadie/railtie.rb +0 -39
- data/lib/roadie/style_declaration.rb +0 -42
- data/spec/fixtures/app/assets/stylesheets/integration.css +0 -10
- data/spec/fixtures/public/stylesheets/integration.css +0 -10
- data/spec/fixtures/views/integration_mailer/marketing.html.erb +0 -2
- data/spec/fixtures/views/integration_mailer/notification.html.erb +0 -8
- data/spec/fixtures/views/integration_mailer/notification.text.erb +0 -6
- data/spec/lib/roadie/action_mailer_extensions_spec.rb +0 -227
- data/spec/lib/roadie/asset_pipeline_provider_spec.rb +0 -65
- data/spec/lib/roadie/css_file_not_found_spec.rb +0 -29
- data/spec/lib/roadie/style_declaration_spec.rb +0 -49
- data/spec/lib/roadie_spec.rb +0 -101
- data/spec/shared_examples/asset_provider_examples.rb +0 -11
- data/spec/support/anonymous_mailer.rb +0 -21
- data/spec/support/change_url_options.rb +0 -5
- data/spec/support/parse_styling.rb +0 -25
@@ -0,0 +1,78 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
module Roadie
|
5
|
+
describe MarkupImprover do
|
6
|
+
def improve(html)
|
7
|
+
dom = Nokogiri::HTML.parse html
|
8
|
+
MarkupImprover.new(dom, html).improve
|
9
|
+
dom
|
10
|
+
end
|
11
|
+
|
12
|
+
# JRuby up to at least 1.6.0 has a bug where the doctype of a document cannot be changed.
|
13
|
+
# See https://github.com/sparklemotion/nokogiri/issues/984
|
14
|
+
def pending_for_buggy_jruby
|
15
|
+
# No reason to check for version yet since no existing version has a fix.
|
16
|
+
skip "Pending until Nokogiri issue #984 is fixed and released" if defined?(JRuby)
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "automatic doctype" do
|
20
|
+
it "inserts a HTML5 doctype if no doctype is present" do
|
21
|
+
pending_for_buggy_jruby
|
22
|
+
expect(improve("<html></html>").internal_subset.to_xml).to eq("<!DOCTYPE html>")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "does not insert duplicate doctypes" do
|
26
|
+
html = improve('<!DOCTYPE html><html><body></body></html>').to_html
|
27
|
+
expect(html.scan('DOCTYPE').size).to eq(1)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "leaves other doctypes alone" do
|
31
|
+
dtd = "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">"
|
32
|
+
html = "#{dtd}<html></html>"
|
33
|
+
expect(improve(html).internal_subset.to_xml.strip).to eq(dtd)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "basic HTML structure" do
|
38
|
+
it "inserts a <html> element as the root" do
|
39
|
+
expect(improve("<h1>Hey!</h1>")).to have_selector("html h1")
|
40
|
+
expect(improve("<html></html>").css('html').size).to eq(1)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "inserts <head> if not present" do
|
44
|
+
expect(improve('<html><body></body></html>')).to have_selector('html > head + body')
|
45
|
+
expect(improve('<html></html>')).to have_selector('html > head')
|
46
|
+
expect(improve('Foo')).to have_selector('html > head')
|
47
|
+
expect(improve('<html><head></head></html>').css('head').size).to eq(1)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "inserts <body> if not present" do
|
51
|
+
expect(improve('<h1>Hey!</h1>')).to have_selector('html > body > h1')
|
52
|
+
expect(improve('<html><h1>Hey!</h1></html>')).to have_selector('html > body > h1')
|
53
|
+
expect(improve('<html><body><h1>Hey!</h1></body></html>').css('body').size).to eq(1)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "charset declaration" do
|
58
|
+
it "is inserted if missing" do
|
59
|
+
dom = improve('<html><head></head><body></body></html>')
|
60
|
+
|
61
|
+
expect(dom).to have_selector('head meta')
|
62
|
+
meta = dom.at_css('head meta')
|
63
|
+
expect(meta['http-equiv']).to eq('Content-Type')
|
64
|
+
expect(meta['content']).to eq('text/html; charset=UTF-8')
|
65
|
+
end
|
66
|
+
|
67
|
+
it "is left alone when predefined" do
|
68
|
+
expect(improve(<<-HTML).xpath('//meta')).to have(1).item
|
69
|
+
<html>
|
70
|
+
<head>
|
71
|
+
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
|
72
|
+
</head>
|
73
|
+
</html>
|
74
|
+
HTML
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'shared_examples/asset_provider'
|
4
|
+
|
5
|
+
module Roadie
|
6
|
+
describe NullProvider do
|
7
|
+
it_behaves_like "asset provider role"
|
8
|
+
|
9
|
+
def expect_empty_stylesheet(stylesheet)
|
10
|
+
expect(stylesheet).not_to be_nil
|
11
|
+
expect(stylesheet.name).to eq("(null)")
|
12
|
+
expect(stylesheet).to have(0).blocks
|
13
|
+
expect(stylesheet.to_s).to be_empty
|
14
|
+
end
|
15
|
+
|
16
|
+
it "finds an empty stylesheet for every name" do
|
17
|
+
expect_empty_stylesheet NullProvider.new.find_stylesheet("omg wtf bbq")
|
18
|
+
expect_empty_stylesheet NullProvider.new.find_stylesheet!("omg wtf bbq")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'shared_examples/url_rewriter'
|
4
|
+
|
5
|
+
module Roadie
|
6
|
+
describe NullUrlRewriter do
|
7
|
+
let(:generator) { double "URL generator" }
|
8
|
+
subject(:rewriter) { NullUrlRewriter.new(generator) }
|
9
|
+
|
10
|
+
it_behaves_like "url rewriter"
|
11
|
+
|
12
|
+
it "does nothing when transforming DOM" do
|
13
|
+
dom = double "DOM tree"
|
14
|
+
expect {
|
15
|
+
NullUrlRewriter.new(generator).transform_dom dom
|
16
|
+
}.to_not raise_error
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'roadie/rspec'
|
4
|
+
|
5
|
+
module Roadie
|
6
|
+
describe ProviderList do
|
7
|
+
let(:test_provider) { TestProvider.new }
|
8
|
+
subject(:provider) { ProviderList.new([test_provider]) }
|
9
|
+
|
10
|
+
it_behaves_like "roadie asset provider", valid_name: "valid", invalid_name: "invalid" do
|
11
|
+
let(:test_provider) { TestProvider.new "valid" => "" }
|
12
|
+
end
|
13
|
+
|
14
|
+
it "finds using all given providers" do
|
15
|
+
first = TestProvider.new "foo.css" => "foo { color: green; }"
|
16
|
+
second = TestProvider.new "bar.css" => "bar { color: green; }"
|
17
|
+
provider = ProviderList.new [first, second]
|
18
|
+
|
19
|
+
expect(provider.find_stylesheet("foo.css").to_s).to include "foo"
|
20
|
+
expect(provider.find_stylesheet("bar.css").to_s).to include "bar"
|
21
|
+
expect(provider.find_stylesheet("baz.css")).to be_nil
|
22
|
+
end
|
23
|
+
|
24
|
+
it "is enumerable" do
|
25
|
+
expect(provider).to be_kind_of(Enumerable)
|
26
|
+
expect(provider).to respond_to(:each)
|
27
|
+
expect(provider.each.to_a).to eq([test_provider])
|
28
|
+
end
|
29
|
+
|
30
|
+
it "has a size" do
|
31
|
+
expect(provider.size).to eq(1)
|
32
|
+
expect(provider).not_to be_empty
|
33
|
+
end
|
34
|
+
|
35
|
+
it "has a first and a last element" do
|
36
|
+
providers = [double("1"), double("2"), double("3")]
|
37
|
+
list = ProviderList.new(providers)
|
38
|
+
expect(list.first).to eq(providers.first)
|
39
|
+
expect(list.last).to eq(providers.last)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "can have providers pushed and popped" do
|
43
|
+
other = double "Some other provider"
|
44
|
+
|
45
|
+
expect {
|
46
|
+
provider.push other
|
47
|
+
provider << other
|
48
|
+
}.to change(provider, :size).by(2)
|
49
|
+
|
50
|
+
expect {
|
51
|
+
expect(provider.pop).to eq(other)
|
52
|
+
}.to change(provider, :size).by(-1)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "can have providers shifted and unshifted" do
|
56
|
+
other = double "Some other provider"
|
57
|
+
|
58
|
+
expect {
|
59
|
+
provider.unshift other
|
60
|
+
}.to change(provider, :size).by(1)
|
61
|
+
|
62
|
+
expect {
|
63
|
+
expect(provider.shift).to eq(other)
|
64
|
+
}.to change(provider, :size).by(-1)
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "wrapping" do
|
68
|
+
it "creates provider lists with the arguments" do
|
69
|
+
expect(ProviderList.wrap(test_provider)).to be_instance_of(ProviderList)
|
70
|
+
expect(ProviderList.wrap(test_provider, test_provider).size).to eq(2)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "flattens arrays" do
|
74
|
+
expect(ProviderList.wrap([test_provider, test_provider], test_provider).size).to eq(3)
|
75
|
+
expect(ProviderList.wrap([test_provider, test_provider]).size).to eq(2)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "combines with providers from other lists" do
|
79
|
+
other_list = ProviderList.new([test_provider, test_provider])
|
80
|
+
expect(ProviderList.wrap(test_provider, other_list).size).to eq(3)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "returns the passed list if only a single ProviderList is passed" do
|
84
|
+
other_list = ProviderList.new([test_provider])
|
85
|
+
expect(ProviderList.wrap(other_list)).to eql other_list
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -4,11 +4,11 @@ require 'spec_helper'
|
|
4
4
|
module Roadie
|
5
5
|
describe Selector do
|
6
6
|
it "can be coerced into String" do
|
7
|
-
("I love " + Selector.new("html")).
|
7
|
+
expect("I love " + Selector.new("html")).to eq("I love html")
|
8
8
|
end
|
9
9
|
|
10
10
|
it "can be inlined when simple" do
|
11
|
-
Selector.new("html body #main p.class").
|
11
|
+
expect(Selector.new("html body #main p.class")).to be_inlinable
|
12
12
|
end
|
13
13
|
|
14
14
|
it "cannot be inlined when containing pseudo functions" do
|
@@ -27,32 +27,37 @@ module Roadie
|
|
27
27
|
p:disabled
|
28
28
|
p:checked
|
29
29
|
].each do |bad_selector|
|
30
|
-
Selector.new(bad_selector).
|
30
|
+
expect(Selector.new(bad_selector)).not_to be_inlinable
|
31
31
|
end
|
32
32
|
|
33
|
-
Selector.new('p.active').
|
33
|
+
expect(Selector.new('p.active')).to be_inlinable
|
34
34
|
end
|
35
35
|
|
36
36
|
it "cannot be inlined when containing pseudo elements" do
|
37
|
-
Selector.new('p::some-element').
|
37
|
+
expect(Selector.new('p::some-element')).not_to be_inlinable
|
38
38
|
end
|
39
39
|
|
40
40
|
it "cannot be inlined when selector is an at-rule" do
|
41
|
-
Selector.new('@keyframes progress-bar-stripes').
|
41
|
+
expect(Selector.new('@keyframes progress-bar-stripes')).not_to be_inlinable
|
42
42
|
end
|
43
43
|
|
44
44
|
it "has a calculated specificity" do
|
45
45
|
selector = "html p.active.nice #main.deep-selector"
|
46
|
-
Selector.new(selector).specificity.
|
46
|
+
expect(Selector.new(selector).specificity).to eq(CssParser.calculate_specificity(selector))
|
47
|
+
end
|
48
|
+
|
49
|
+
it "can be told about the specificity at initialization" do
|
50
|
+
selector = "html p.active.nice #main.deep-selector"
|
51
|
+
expect(Selector.new(selector, 1337).specificity).to eq(1337)
|
47
52
|
end
|
48
53
|
|
49
54
|
it "is equal to other selectors when they match the same things" do
|
50
|
-
Selector.new("foo").
|
51
|
-
Selector.new("foo").
|
55
|
+
expect(Selector.new("foo")).to eq(Selector.new("foo "))
|
56
|
+
expect(Selector.new("foo")).not_to eq("foo")
|
52
57
|
end
|
53
58
|
|
54
59
|
it "strips the given selector" do
|
55
|
-
Selector.new(" foo \n").to_s.
|
60
|
+
expect(Selector.new(" foo \n").to_s).to eq(Selector.new("foo").to_s)
|
56
61
|
end
|
57
62
|
end
|
58
63
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Roadie
|
4
|
+
describe StyleAttributeBuilder do
|
5
|
+
it "sorts the added properties" do
|
6
|
+
builder = StyleAttributeBuilder.new
|
7
|
+
|
8
|
+
builder << StyleProperty.new("color", "green", true, 1)
|
9
|
+
builder << StyleProperty.new("font-size", "110%", false, 15)
|
10
|
+
builder << StyleProperty.new("color", "red", false, 15)
|
11
|
+
|
12
|
+
expect(builder.attribute_string).to eq "font-size:110%;color:red;color:green !important"
|
13
|
+
end
|
14
|
+
|
15
|
+
it "preserves the order of added attributes with the same specificity" do
|
16
|
+
builder = StyleAttributeBuilder.new
|
17
|
+
|
18
|
+
builder << StyleProperty.new("color", "pink", false, 50)
|
19
|
+
builder << StyleProperty.new("color", "red", false, 50)
|
20
|
+
builder << StyleProperty.new("color", "green", false, 50)
|
21
|
+
|
22
|
+
# We need one different element to trigger the problem with Ruby's
|
23
|
+
# unstable sort
|
24
|
+
builder << StyleProperty.new("background", "white", false, 1)
|
25
|
+
|
26
|
+
expect(builder.attribute_string).to eq "background:white;color:pink;color:red;color:green"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
module Roadie
|
5
|
+
describe StyleBlock do
|
6
|
+
it "has a selector and a list of properties" do
|
7
|
+
properties = []
|
8
|
+
selector = double "Selector"
|
9
|
+
|
10
|
+
block = StyleBlock.new(selector, properties)
|
11
|
+
expect(block.selector).to eq(selector)
|
12
|
+
expect(block.properties).to eq(properties)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "delegates #specificity to the selector" do
|
16
|
+
selector = double "Selector", specificity: 45
|
17
|
+
expect(StyleBlock.new(selector, []).specificity).to eq(45)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "delegates #inlinable? to the selector" do
|
21
|
+
selector = double "Selector", inlinable?: "maybe"
|
22
|
+
expect(StyleBlock.new(selector, []).inlinable?).to eq("maybe")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "delegates #selector_string to selector#to_s" do
|
26
|
+
selector = double "Selector", to_s: "yey"
|
27
|
+
expect(StyleBlock.new(selector, []).selector_string).to eq("yey")
|
28
|
+
end
|
29
|
+
|
30
|
+
it "has a string representation" do
|
31
|
+
properties = [double(to_s: "bar"), double(to_s: "baz")]
|
32
|
+
expect(StyleBlock.new(double(to_s: "foo"), properties).to_s).to eq("foo{bar;baz}")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Roadie
|
4
|
+
describe StyleProperty do
|
5
|
+
it "is initialized with a property, value, if it is marked as important, and the specificity" do
|
6
|
+
StyleProperty.new('color', 'green', true, 45).tap do |declaration|
|
7
|
+
expect(declaration.property).to eq('color')
|
8
|
+
expect(declaration.value).to eq('green')
|
9
|
+
expect(declaration).to be_important
|
10
|
+
expect(declaration.specificity).to eq(45)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "string representation" do
|
15
|
+
it "is the property and the value joined with a colon" do
|
16
|
+
expect(StyleProperty.new('color', 'green', false, 1).to_s).to eq('color:green')
|
17
|
+
expect(StyleProperty.new('font-size', '1.1em', false, 1).to_s).to eq('font-size:1.1em')
|
18
|
+
end
|
19
|
+
|
20
|
+
it "contains the !important flag when set" do
|
21
|
+
expect(StyleProperty.new('color', 'green', true, 1).to_s).to eq('color:green !important')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "comparing" do
|
26
|
+
def declaration(specificity, important = false)
|
27
|
+
StyleProperty.new('color', 'green', important, specificity)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "compares on specificity" do
|
31
|
+
expect(declaration(5)).to eq(declaration(5))
|
32
|
+
expect(declaration(4)).to be < declaration(5)
|
33
|
+
expect(declaration(6)).to be > declaration(5)
|
34
|
+
end
|
35
|
+
|
36
|
+
context "with an important declaration" do
|
37
|
+
it "is less than the important declaration regardless of the specificity" do
|
38
|
+
expect(declaration(99, false)).to be < declaration(1, true)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "compares like normal when both declarations are important" do
|
42
|
+
expect(declaration(5, true)).to eq(declaration(5, true))
|
43
|
+
expect(declaration(4, true)).to be < declaration(5, true)
|
44
|
+
expect(declaration(6, true)).to be > declaration(5, true)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "parsing" do
|
50
|
+
def parsing(declaration, specificity)
|
51
|
+
property = StyleProperty.parse(declaration, specificity)
|
52
|
+
[property.property, property.value, property.important?, property.specificity]
|
53
|
+
end
|
54
|
+
|
55
|
+
it "understands simple declarations" do
|
56
|
+
expect(parsing("color: green", 1)).to eq(["color", "green", false, 1])
|
57
|
+
expect(parsing(" color:green; ", 1)).to eq(["color", "green", false, 1])
|
58
|
+
expect(parsing("color: green ", 1)).to eq(["color", "green", false, 1])
|
59
|
+
expect(parsing("color: green ; ", 1)).to eq(["color", "green", false, 1])
|
60
|
+
end
|
61
|
+
|
62
|
+
it "understands more complex values" do
|
63
|
+
expect(parsing("padding:0 1px 5rem 9%;", 89)).to eq(["padding", "0 1px 5rem 9%", false, 89])
|
64
|
+
end
|
65
|
+
|
66
|
+
it "understands more complex names" do
|
67
|
+
expect(parsing("font-size: 50%", 10)).to eq(["font-size", "50%", false, 10])
|
68
|
+
end
|
69
|
+
|
70
|
+
it "correctly reads !important declarations" do
|
71
|
+
expect(parsing("color: green !important", 1)).to eq(["color", "green", true, 1])
|
72
|
+
expect(parsing("color: green !important;", 1)).to eq(["color", "green", true, 1])
|
73
|
+
end
|
74
|
+
|
75
|
+
it "raises an error on unparseable declarations" do
|
76
|
+
expect {
|
77
|
+
parsing("I want a red apple!", 1)
|
78
|
+
}.to raise_error(Roadie::UnparseableDeclaration, /red apple/)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
module Roadie
|
5
|
+
describe Stylesheet do
|
6
|
+
it "is initialized with a name and CSS" do
|
7
|
+
stylesheet = Stylesheet.new("foo.css", "body { color: green; }")
|
8
|
+
expect(stylesheet.name).to eq("foo.css")
|
9
|
+
end
|
10
|
+
|
11
|
+
it "has a list of blocks" do
|
12
|
+
stylesheet = Stylesheet.new("foo.css", <<-CSS)
|
13
|
+
body { color: green !important; font-size: 200%; }
|
14
|
+
a, i { color: red; }
|
15
|
+
CSS
|
16
|
+
expect(stylesheet).to have(3).blocks
|
17
|
+
expect(stylesheet.blocks.map(&:to_s)).to eq([
|
18
|
+
"body{color:green !important;font-size:200%}",
|
19
|
+
"a{color:red}",
|
20
|
+
"i{color:red}",
|
21
|
+
])
|
22
|
+
end
|
23
|
+
|
24
|
+
it "can iterate all inlinable blocks" do
|
25
|
+
inlinable = double(inlinable?: true, selector: "good", properties: "props")
|
26
|
+
bad = double(inlinable?: false, selector: "bad", properties: "props")
|
27
|
+
|
28
|
+
stylesheet = Stylesheet.new("example.css", "")
|
29
|
+
allow(stylesheet).to receive_messages blocks: [bad, inlinable, bad]
|
30
|
+
|
31
|
+
expect(stylesheet.each_inlinable_block.to_a).to eq([
|
32
|
+
["good", "props"],
|
33
|
+
])
|
34
|
+
end
|
35
|
+
|
36
|
+
it "has a string representation of the contents" do
|
37
|
+
stylesheet = Stylesheet.new("example.css", "body { color: green;}a{ color: red; font-size: small }")
|
38
|
+
expect(stylesheet.to_s).to eq("body{color:green}\na{color:red;font-size:small}")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|