roadie 3.5.1 → 5.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +46 -0
  3. data/.rubocop.yml +5 -0
  4. data/.solargraph.yml +16 -0
  5. data/Changelog.md +35 -4
  6. data/Gemfile +7 -2
  7. data/README.md +14 -14
  8. data/Rakefile +4 -3
  9. data/lib/roadie/asset_provider.rb +5 -1
  10. data/lib/roadie/asset_scanner.rb +8 -6
  11. data/lib/roadie/cached_provider.rb +3 -0
  12. data/lib/roadie/deduplicator.rb +3 -0
  13. data/lib/roadie/document.rb +24 -17
  14. data/lib/roadie/errors.rb +22 -16
  15. data/lib/roadie/filesystem_provider.rb +15 -3
  16. data/lib/roadie/inliner.rb +51 -19
  17. data/lib/roadie/markup_improver.rb +24 -31
  18. data/lib/roadie/net_http_provider.rb +27 -12
  19. data/lib/roadie/null_provider.rb +20 -5
  20. data/lib/roadie/null_url_rewriter.rb +11 -3
  21. data/lib/roadie/path_rewriter_provider.rb +6 -1
  22. data/lib/roadie/provider_list.rb +17 -11
  23. data/lib/roadie/rspec/asset_provider.rb +6 -1
  24. data/lib/roadie/rspec/cache_store.rb +2 -0
  25. data/lib/roadie/rspec.rb +4 -2
  26. data/lib/roadie/selector.rb +18 -5
  27. data/lib/roadie/style_attribute_builder.rb +4 -1
  28. data/lib/roadie/style_block.rb +5 -3
  29. data/lib/roadie/style_property.rb +5 -2
  30. data/lib/roadie/stylesheet.rb +4 -13
  31. data/lib/roadie/url_generator.rb +26 -8
  32. data/lib/roadie/url_rewriter.rb +12 -9
  33. data/lib/roadie/utils.rb +3 -1
  34. data/lib/roadie/version.rb +1 -1
  35. data/lib/roadie.rb +25 -23
  36. data/roadie.gemspec +23 -23
  37. data/spec/hash_as_cache_store_spec.rb +3 -1
  38. data/spec/integration_spec.rb +75 -44
  39. data/spec/lib/roadie/asset_scanner_spec.rb +11 -5
  40. data/spec/lib/roadie/cached_provider_spec.rb +6 -4
  41. data/spec/lib/roadie/css_not_found_spec.rb +10 -5
  42. data/spec/lib/roadie/deduplicator_spec.rb +5 -3
  43. data/spec/lib/roadie/document_spec.rb +57 -28
  44. data/spec/lib/roadie/filesystem_provider_spec.rb +10 -11
  45. data/spec/lib/roadie/inliner_spec.rb +42 -45
  46. data/spec/lib/roadie/markup_improver_spec.rb +19 -26
  47. data/spec/lib/roadie/net_http_provider_spec.rb +16 -14
  48. data/spec/lib/roadie/null_provider_spec.rb +4 -3
  49. data/spec/lib/roadie/null_url_rewriter_spec.rb +4 -3
  50. data/spec/lib/roadie/path_rewriter_provider_spec.rb +6 -4
  51. data/spec/lib/roadie/provider_list_spec.rb +27 -22
  52. data/spec/lib/roadie/selector_spec.rb +7 -5
  53. data/spec/lib/roadie/style_attribute_builder_spec.rb +7 -5
  54. data/spec/lib/roadie/style_block_spec.rb +3 -2
  55. data/spec/lib/roadie/style_property_spec.rb +10 -8
  56. data/spec/lib/roadie/stylesheet_spec.rb +4 -21
  57. data/spec/lib/roadie/test_provider_spec.rb +6 -4
  58. data/spec/lib/roadie/url_generator_spec.rb +3 -2
  59. data/spec/lib/roadie/url_rewriter_spec.rb +10 -7
  60. data/spec/lib/roadie/utils_spec.rb +2 -0
  61. data/spec/shared_examples/asset_provider.rb +2 -0
  62. data/spec/shared_examples/url_rewriter.rb +5 -3
  63. data/spec/spec_helper.rb +10 -8
  64. data/spec/support/have_attribute_matcher.rb +3 -2
  65. data/spec/support/have_node_matcher.rb +5 -3
  66. data/spec/support/have_selector_matcher.rb +4 -3
  67. data/spec/support/have_styling_matcher.rb +12 -11
  68. data/spec/support/have_xpath_matcher.rb +4 -3
  69. data/spec/support/test_provider.rb +2 -0
  70. metadata +24 -8
  71. data/.travis.yml +0 -22
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
 
3
5
  module Roadie
@@ -7,13 +9,13 @@ module Roadie
7
9
  ["a", "1"],
8
10
  ["b", "2"],
9
11
  ["a", "3"],
10
- ["a", "1"],
12
+ ["a", "1"]
11
13
  ]
12
14
 
13
15
  expect(Deduplicator.apply(input)).to eq [
14
16
  ["b", "2"],
15
17
  ["a", "3"],
16
- ["a", "1"],
18
+ ["a", "1"]
17
19
  ]
18
20
  end
19
21
 
@@ -21,7 +23,7 @@ module Roadie
21
23
  input = [
22
24
  ["a", "1"],
23
25
  ["a", "3"],
24
- ["a", "2"],
26
+ ["a", "2"]
25
27
  ]
26
28
 
27
29
  expect(Deduplicator.apply(input)).to eq input
@@ -1,5 +1,6 @@
1
- # encoding: UTF-8
2
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
3
4
 
4
5
  module Roadie
5
6
  describe Document do
@@ -16,6 +17,16 @@ module Roadie
16
17
  expect(document.url_options).to eq({host: "foo.bar"})
17
18
  end
18
19
 
20
+ it "has an accessor for serialization options" do
21
+ serialization_options = Nokogiri::XML::Node::SaveOptions::FORMAT |
22
+ Nokogiri::XML::Node::SaveOptions::NO_EMPTY_TAGS
23
+ document.serialization_options = serialization_options
24
+ expect(document.serialization_options).to eq(serialization_options)
25
+
26
+ document.serialization_options = nil
27
+ expect(document.serialization_options).to eq(0)
28
+ end
29
+
19
30
  it "has a setting for keeping uninlinable styles" do
20
31
  expect(document.keep_uninlinable_css).to be true
21
32
  document.keep_uninlinable_css = false
@@ -69,6 +80,9 @@ module Roadie
69
80
 
70
81
  document.mode = :html
71
82
  expect(document.mode).to eq(:html)
83
+
84
+ document.mode = :xml
85
+ expect(document.mode).to eq(:xml)
72
86
  end
73
87
 
74
88
  it "does not allow unknown modes" do
@@ -90,8 +104,8 @@ module Roadie
90
104
  describe "transforming" do
91
105
  it "runs the before and after callbacks" do
92
106
  document = Document.new "<body></body>"
93
- before = ->{}
94
- after = ->{}
107
+ before = -> {}
108
+ after = -> {}
95
109
  document.before_transformation = before
96
110
  document.after_transformation = after
97
111
 
@@ -102,21 +116,6 @@ module Roadie
102
116
  document.transform
103
117
  end
104
118
 
105
- # TODO: Remove on next major version.
106
- it "works on callables that don't expect more than one argument" do
107
- document = Document.new "<body></body>"
108
- document.before_transformation = ->(first) { }
109
- document.after_transformation = ->(first = nil) { }
110
-
111
- expect { document.transform }.to_not raise_error
112
-
113
- # It still supplies the second argument, if possible.
114
- document.after_transformation = ->(first, second = nil) {
115
- raise "Oops" unless second
116
- }
117
- expect { document.transform }.to_not raise_error
118
- end
119
-
120
119
  context "in HTML mode" do
121
120
  it "does not escape curly braces" do
122
121
  document = Document.new "<body><a href='https://google.com/{{hello}}'>Hello</a></body>"
@@ -125,26 +124,41 @@ module Roadie
125
124
  expect(document.transform).to include("{{hello}}")
126
125
  end
127
126
  end
127
+
128
+ context "in XML mode" do
129
+ it "doesn't replace empty tags with self-closed ones" do
130
+ document = Document.new "<img src='https://google.com/image.png'></img>"
131
+ document.mode = :xml
132
+
133
+ expect(document.transform_partial).to end_with("</img>")
134
+ end
135
+
136
+ it "does not escape curly braces" do
137
+ document = Document.new "<a href='https://google.com/{{hello}}'>Hello</a>"
138
+ document.mode = :xml
139
+ expect(document.transform_partial).to include("{{hello}}")
140
+ end
141
+ end
128
142
  end
129
143
 
130
144
  describe "partial transforming" do
131
145
  it "runs the before and after callbacks" do
132
146
  document = Document.new "<p></p>"
133
- before = ->{}
134
- after = ->{}
147
+ before = -> {}
148
+ after = -> {}
135
149
  document.before_transformation = before
136
150
  document.after_transformation = after
137
151
 
138
152
  expect(before).to receive(:call).with(
139
153
  instance_of(Nokogiri::HTML::DocumentFragment),
140
- document,
154
+ document
141
155
  ).ordered
142
156
 
143
157
  expect(Inliner).to receive(:new).ordered.and_return double.as_null_object
144
158
 
145
159
  expect(after).to receive(:call).with(
146
160
  instance_of(Nokogiri::HTML::DocumentFragment),
147
- document,
161
+ document
148
162
  ).ordered
149
163
 
150
164
  document.transform_partial
@@ -158,6 +172,21 @@ module Roadie
158
172
  expect(document.transform_partial).to include("{{hello}}")
159
173
  end
160
174
  end
175
+
176
+ context "in XML mode" do
177
+ it "doesn't replace empty tags with self-closed ones" do
178
+ document = Document.new "<img src='https://google.com/image.png'></img>"
179
+ document.mode = :xml
180
+
181
+ expect(document.transform_partial).to end_with("</img>")
182
+ end
183
+
184
+ it "does not escape curly braces" do
185
+ document = Document.new "<a href='https://google.com/{{hello}}'>Hello</a>"
186
+ document.mode = :xml
187
+ expect(document.transform_partial).to include("{{hello}}")
188
+ end
189
+ end
161
190
  end
162
191
  end
163
192
 
@@ -178,11 +207,11 @@ module Roadie
178
207
 
179
208
  result = Nokogiri::HTML.parse document.transform
180
209
 
181
- expect(result).to have_selector('html > head > title')
182
- expect(result.at_css('title').text).to eq("Greetings")
210
+ expect(result).to have_selector("html > head > title")
211
+ expect(result.at_css("title").text).to eq("Greetings")
183
212
 
184
- expect(result).to have_selector('html > body > p')
185
- paragraph = result.at_css('p')
213
+ expect(result).to have_selector("html > body > p")
214
+ paragraph = result.at_css("p")
186
215
  expect(paragraph.text).to eq("Hello, world!")
187
216
  expect(paragraph.to_xml).to eq('<p style="color:green">Hello, world!</p>')
188
217
  end
@@ -201,7 +230,7 @@ module Roadie
201
230
  HTML
202
231
 
203
232
  document.asset_providers = TestProvider.new({
204
- "/sample.css" => "p { color: red; text-align: right; }",
233
+ "/sample.css" => "p { color: red; text-align: right; }"
205
234
  })
206
235
 
207
236
  document.add_css "p { color: green; text-size: 2em; }"
@@ -1,7 +1,8 @@
1
- # encoding: UTF-8
2
- require 'spec_helper'
3
- require 'roadie/rspec'
4
- require 'shared_examples/asset_provider'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "roadie/rspec"
5
+ require "shared_examples/asset_provider"
5
6
 
6
7
  module Roadie
7
8
  describe FilesystemProvider do
@@ -62,13 +63,11 @@ module Roadie
62
63
  end
63
64
 
64
65
  it "shows that the query string is ignored inside raised errors" do
65
- begin
66
- provider.find_stylesheet!("/foo.css?query-string")
67
- fail "No error was raised"
68
- rescue CssNotFound => error
69
- expect(error.css_name).to eq("foo.css")
70
- expect(error.to_s).to include("/foo.css?query-string")
71
- end
66
+ provider.find_stylesheet!("/foo.css?query-string")
67
+ fail "No error was raised"
68
+ rescue CssNotFound => error
69
+ expect(error.css_name).to eq("foo.css")
70
+ expect(error.to_s).to include("/foo.css?query-string")
72
71
  end
73
72
  end
74
73
  end
@@ -1,10 +1,13 @@
1
- # encoding: UTF-8
2
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
3
4
 
4
5
  module Roadie
5
6
  describe Inliner do
6
- before { @stylesheet = "".freeze }
7
- def use_css(css) @stylesheet = Stylesheet.new("example", css) end
7
+ before { @stylesheet = "" }
8
+ def use_css(css)
9
+ @stylesheet = Stylesheet.new("example", css)
10
+ end
8
11
 
9
12
  def rendering(html, stylesheet = @stylesheet)
10
13
  dom = Nokogiri::HTML.parse html
@@ -14,17 +17,17 @@ module Roadie
14
17
 
15
18
  describe "inlining styles" do
16
19
  it "inlines simple attributes" do
17
- use_css 'p { color: green }'
18
- expect(rendering('<p></p>')).to have_styling('color' => 'green')
20
+ use_css "p { color: green }"
21
+ expect(rendering("<p></p>")).to have_styling("color" => "green")
19
22
  end
20
23
 
21
24
  it "keeps multiple versions of the same property to support progressive enhancement" do
22
25
  # https://github.com/premailer/css_parser/issues/44
23
26
  pending "css_parser issue #44"
24
27
 
25
- use_css 'p { color: #eee; color: rgba(255, 255, 255, 0.9); }'
26
- expect(rendering('<p></p>')).to have_styling(
27
- [['color', 'green'], ['color', 'rgba(255, 255, 255, 0.9)']]
28
+ use_css "p { color: #eee; color: rgba(255, 255, 255, 0.9); }"
29
+ expect(rendering("<p></p>")).to have_styling(
30
+ [["color", "green"], ["color", "rgba(255, 255, 255, 0.9)"]]
28
31
  )
29
32
  end
30
33
 
@@ -35,35 +38,35 @@ module Roadie
35
38
  .positive { color: green; }
36
39
  '
37
40
  expect(rendering('<p class="message positive"></p>')).to have_styling(
38
- [['color', 'blue'], ['color', 'green']]
41
+ [["color", "blue"], ["color", "green"]]
39
42
  )
40
43
  end
41
44
 
42
45
  it "inlines browser-prefixed attributes" do
43
- use_css 'p { -vendor-color: green }'
44
- expect(rendering('<p></p>')).to have_styling('-vendor-color' => 'green')
46
+ use_css "p { -vendor-color: green }"
47
+ expect(rendering("<p></p>")).to have_styling("-vendor-color" => "green")
45
48
  end
46
49
 
47
50
  it "inlines CSS3 attributes" do
48
- use_css 'p { border-radius: 2px; }'
49
- expect(rendering('<p></p>')).to have_styling('border-radius' => '2px')
51
+ use_css "p { border-radius: 2px; }"
52
+ expect(rendering("<p></p>")).to have_styling("border-radius" => "2px")
50
53
  end
51
54
 
52
55
  it "keeps the order of the styles that are inlined" do
53
- use_css 'h1 { padding: 2px; margin: 5px; }'
54
- expect(rendering('<h1></h1>')).to have_styling([['padding', '2px'], ['margin', '5px']])
56
+ use_css "h1 { padding: 2px; margin: 5px; }"
57
+ expect(rendering("<h1></h1>")).to have_styling([["padding", "2px"], ["margin", "5px"]])
55
58
  end
56
59
 
57
60
  it "combines multiple selectors into one" do
58
61
  use_css 'p { color: green; }
59
62
  .tip { float: right; }'
60
- expect(rendering('<p class="tip"></p>')).to have_styling([['color', 'green'], ['float', 'right']])
63
+ expect(rendering('<p class="tip"></p>')).to have_styling([["color", "green"], ["float", "right"]])
61
64
  end
62
65
 
63
66
  it "uses the attributes with the highest specificity when conflicts arises" do
64
67
  use_css ".safe { color: green; }
65
68
  p { color: red; }"
66
- expect(rendering('<p class="safe"></p>')).to have_styling([['color', 'red'], ['color', 'green']])
69
+ expect(rendering('<p class="safe"></p>')).to have_styling([["color", "red"], ["color", "green"]])
67
70
  end
68
71
 
69
72
  it "sorts styles by specificity order" do
@@ -81,10 +84,10 @@ module Roadie
81
84
  end
82
85
 
83
86
  it "supports multiple selectors for the same rules" do
84
- use_css 'p, a { color: green; }'
85
- rendering('<p></p><a></a>').tap do |document|
86
- expect(document).to have_styling('color' => 'green').at_selector('p')
87
- expect(document).to have_styling('color' => 'green').at_selector('a')
87
+ use_css "p, a { color: green; }"
88
+ rendering("<p></p><a></a>").tap do |document|
89
+ expect(document).to have_styling("color" => "green").at_selector("p")
90
+ expect(document).to have_styling("color" => "green").at_selector("a")
88
91
  end
89
92
  end
90
93
 
@@ -92,22 +95,22 @@ module Roadie
92
95
  use_css "a { text-decoration: underline !important; }
93
96
  a.hard-to-spot { text-decoration: none; }"
94
97
  expect(rendering('<a class="hard-to-spot"></a>')).to have_styling([
95
- ['text-decoration', 'none'], ['text-decoration', 'underline !important']
98
+ ["text-decoration", "none"], ["text-decoration", "underline !important"]
96
99
  ])
97
100
  end
98
101
 
99
102
  it "combines with already present inline styles" do
100
103
  use_css "p { color: green }"
101
- expect(rendering('<p style="font-size: 1.1em"></p>')).to have_styling([['color', 'green'], ['font-size', '1.1em']])
104
+ expect(rendering('<p style="font-size: 1.1em"></p>')).to have_styling([["color", "green"], ["font-size", "1.1em"]])
102
105
  end
103
106
 
104
107
  it "does not override inline styles" do
105
108
  use_css "p { text-transform: uppercase; color: red }"
106
109
  # The two color properties are kept to make css fallbacks work correctly
107
110
  expect(rendering('<p style="color: green"></p>')).to have_styling([
108
- ['text-transform', 'uppercase'],
109
- ['color', 'red'],
110
- ['color', 'green'],
111
+ ["text-transform", "uppercase"],
112
+ ["color", "red"],
113
+ ["color", "green"]
111
114
  ])
112
115
  end
113
116
 
@@ -122,7 +125,7 @@ module Roadie
122
125
 
123
126
  p.active { width: 100%; }
124
127
  "
125
- expect(rendering('<p class="active"></p>')).to have_styling('width' => '100%')
128
+ expect(rendering('<p class="active"></p>')).to have_styling("width" => "100%")
126
129
  end
127
130
 
128
131
  it "does not crash on any pseudo element selectors" do
@@ -130,7 +133,7 @@ module Roadie
130
133
  p.some-element { width: 100%; }
131
134
  p::some-element { color: red; }
132
135
  "
133
- expect(rendering('<p class="some-element"></p>')).to have_styling('width' => '100%')
136
+ expect(rendering('<p class="some-element"></p>')).to have_styling("width" => "100%")
134
137
  end
135
138
 
136
139
  it "warns on selectors that crash Nokogiri" do
@@ -139,7 +142,7 @@ module Roadie
139
142
  stylesheet = Stylesheet.new "foo.css", "p[%^=foo] { color: red; }"
140
143
  inliner = Inliner.new([stylesheet], dom)
141
144
  expect(Utils).to receive(:warn).with(
142
- %{Cannot inline "p[%^=foo]" from "foo.css" stylesheet. If this is valid CSS, please report a bug.}
145
+ %(Cannot inline "p[%^=foo]" from "foo.css" stylesheet. If this is valid CSS, please report a bug.)
143
146
  )
144
147
  inliner.inline
145
148
  end
@@ -151,8 +154,8 @@ module Roadie
151
154
  "
152
155
  result = rendering("<p></p> <p></p>")
153
156
 
154
- expect(result).to have_styling([['color', 'red']]).at_selector('p:first')
155
- expect(result).to have_styling([['color', 'red'], ['color', 'green']]).at_selector('p:last')
157
+ expect(result).to have_styling([["color", "red"]]).at_selector("p:first")
158
+ expect(result).to have_styling([["color", "red"], ["color", "green"]]).at_selector("p:last")
156
159
  end
157
160
 
158
161
  context "with uninlinable selectors" do
@@ -161,7 +164,7 @@ module Roadie
161
164
  end
162
165
 
163
166
  it "puts them in a new <style> element in the <head>" do
164
- use_css 'a:hover { color: red; }'
167
+ use_css "a:hover { color: red; }"
165
168
  result = rendering("
166
169
  <html>
167
170
  <head></head>
@@ -173,7 +176,7 @@ module Roadie
173
176
  end
174
177
 
175
178
  it "puts them in <head> on unexpected inlining problems" do
176
- use_css 'p:some-future-thing { color: red; }'
179
+ use_css "p:some-future-thing { color: red; }"
177
180
  result = rendering("
178
181
  <html>
179
182
  <head></head>
@@ -197,15 +200,9 @@ module Roadie
197
200
  }'
198
201
 
199
202
  use_css css
200
- result = rendering('<p></p>')
203
+ result = rendering("<p></p>")
201
204
 
202
205
  expect(result).to have_styling([]).at_selector("p")
203
-
204
- # css_parser actually sees an empty @keyframes on JRuby, and nothing
205
- # on the others
206
- if (style_element = result.at_css("head > style"))
207
- expect(style_element.text).to_not include "background-position"
208
- end
209
206
  end
210
207
 
211
208
  it "ignores them if told not to keep them" do
@@ -224,14 +221,14 @@ module Roadie
224
221
  end
225
222
 
226
223
  it "puts the <style> element at the root when told so" do
227
- stylesheet = use_css 'a:hover { color: red; }'
224
+ stylesheet = use_css "a:hover { color: red; }"
228
225
  dom = Nokogiri::HTML.fragment("
229
226
  <a></a>
230
227
  ")
231
228
 
232
229
  Inliner.new([stylesheet], dom).inline(
233
230
  keep_uninlinable_css: true,
234
- keep_uninlinable_in: :root,
231
+ keep_uninlinable_in: :root
235
232
  )
236
233
 
237
234
  expect(dom).to have_xpath("./a")
@@ -239,7 +236,7 @@ module Roadie
239
236
  end
240
237
 
241
238
  it "raises error when told to save styles in an unknown place" do
242
- stylesheet = use_css 'a:hover { color: red; }'
239
+ stylesheet = use_css "a:hover { color: red; }"
243
240
  dom = Nokogiri::HTML.fragment("
244
241
  <a></a>
245
242
  ")
@@ -248,7 +245,7 @@ module Roadie
248
245
  expect {
249
246
  inliner.inline(
250
247
  keep_uninlinable_css: true,
251
- keep_uninlinable_in: :unknown_place,
248
+ keep_uninlinable_in: :unknown_place
252
249
  )
253
250
  }.to raise_error(ArgumentError, /:unknown_place/)
254
251
  end
@@ -1,5 +1,6 @@
1
- # encoding: UTF-8
2
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
3
4
 
4
5
  module Roadie
5
6
  describe MarkupImprover do
@@ -9,22 +10,14 @@ module Roadie
9
10
  dom
10
11
  end
11
12
 
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
13
  describe "automatic doctype" do
20
14
  it "inserts a HTML5 doctype if no doctype is present" do
21
- pending_for_buggy_jruby
22
15
  expect(improve("<html></html>").internal_subset.to_xml).to eq("<!DOCTYPE html>")
23
16
  end
24
17
 
25
18
  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)
19
+ html = improve("<!DOCTYPE html><html><body></body></html>").to_html
20
+ expect(html.scan("DOCTYPE").size).to eq(1)
28
21
  end
29
22
 
30
23
  it "leaves other doctypes alone" do
@@ -38,35 +31,35 @@ module Roadie
38
31
  it "inserts a <html> element as the root" do
39
32
  expect(improve("")).to have_selector("html")
40
33
  expect(improve("<h1>Hey!</h1>")).to have_selector("html h1")
41
- expect(improve("<html></html>").css('html').size).to eq(1)
34
+ expect(improve("<html></html>").css("html").size).to eq(1)
42
35
  end
43
36
 
44
37
  it "inserts <head> if not present" do
45
- expect(improve('<html><body></body></html>')).to have_selector('html > head + body')
46
- expect(improve('<html></html>')).to have_selector('html > head')
47
- expect(improve('Foo')).to have_selector('html > head')
48
- expect(improve('<html><head></head></html>').css('head').size).to eq(1)
38
+ expect(improve("<html><body></body></html>")).to have_selector("html > head + body")
39
+ expect(improve("<html></html>")).to have_selector("html > head")
40
+ expect(improve("Foo")).to have_selector("html > head")
41
+ expect(improve("<html><head></head></html>").css("head").size).to eq(1)
49
42
  end
50
43
 
51
44
  it "inserts <body> if not present" do
52
- expect(improve('<h1>Hey!</h1>')).to have_selector('html > body > h1')
53
- expect(improve('<html><h1>Hey!</h1></html>')).to have_selector('html > body > h1')
54
- expect(improve('<html><body><h1>Hey!</h1></body></html>').css('body').size).to eq(1)
45
+ expect(improve("<h1>Hey!</h1>")).to have_selector("html > body > h1")
46
+ expect(improve("<html><h1>Hey!</h1></html>")).to have_selector("html > body > h1")
47
+ expect(improve("<html><body><h1>Hey!</h1></body></html>").css("body").size).to eq(1)
55
48
  end
56
49
  end
57
50
 
58
51
  describe "charset declaration" do
59
52
  it "is inserted if missing" do
60
- dom = improve('<html><head></head><body></body></html>')
53
+ dom = improve("<html><head></head><body></body></html>")
61
54
 
62
- expect(dom).to have_selector('head meta')
63
- meta = dom.at_css('head meta')
64
- expect(meta['http-equiv']).to eq('Content-Type')
65
- expect(meta['content']).to eq('text/html; charset=UTF-8')
55
+ expect(dom).to have_selector("head meta")
56
+ meta = dom.at_css("head meta")
57
+ expect(meta["http-equiv"]).to eq("Content-Type")
58
+ expect(meta["content"]).to eq("text/html; charset=UTF-8")
66
59
  end
67
60
 
68
61
  it "is left alone when predefined" do
69
- expect(improve(<<-HTML).xpath('//meta')).to have(1).item
62
+ expect(improve(<<-HTML).xpath("//meta")).to have(1).item
70
63
  <html>
71
64
  <head>
72
65
  <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
@@ -1,6 +1,8 @@
1
- require 'spec_helper'
2
- require 'roadie/rspec'
3
- require 'shared_examples/asset_provider'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "roadie/rspec"
5
+ require "shared_examples/asset_provider"
4
6
 
5
7
  module Roadie
6
8
  describe NetHttpProvider do
@@ -10,7 +12,7 @@ module Roadie
10
12
  WebMock.allow_net_connect!
11
13
  end
12
14
 
13
- url = "http://example.com/style.css".freeze
15
+ url = "http://example.com/style.css"
14
16
 
15
17
  it_behaves_like(
16
18
  "roadie asset provider",
@@ -18,13 +20,13 @@ module Roadie
18
20
  invalid_name: "http://example.com/red.css"
19
21
  ) do
20
22
  before do
21
- stub_request(:get, "http://example.com/green.css").and_return(body: "p { color: green; }")
23
+ stub_request(:get, "http://example.com/green.css").and_return(body: +"p { color: green; }")
22
24
  stub_request(:get, "http://example.com/red.css").and_return(status: 404, body: "Not here!")
23
25
  end
24
26
  end
25
27
 
26
28
  it "can download over HTTPS" do
27
- stub_request(:get, "https://example.com/style.css").and_return(body: "p { color: green; }")
29
+ stub_request(:get, "https://example.com/style.css").and_return(body: +"p { color: green; }")
28
30
  expect {
29
31
  NetHttpProvider.new.find_stylesheet!("https://example.com/style.css")
30
32
  }.to_not raise_error
@@ -37,7 +39,7 @@ module Roadie
37
39
  # asset inlining, but the scheme-less URL implies that there should exist
38
40
  # both a HTTP and a HTTPS endpoint. Let's take the secure one in that
39
41
  # case!
40
- stub_request(:get, "https://example.com/style.css").and_return(body: "p { color: green; }")
42
+ stub_request(:get, "https://example.com/style.css").and_return(body: +"p { color: green; }")
41
43
  expect {
42
44
  NetHttpProvider.new.find_stylesheet!("//example.com/style.css")
43
45
  }.to_not raise_error
@@ -48,8 +50,8 @@ module Roadie
48
50
  # (US-ASCII). The headers will indicate what charset the client should
49
51
  # use when trying to make sense of these bytes.
50
52
  stub_request(:get, url).and_return(
51
- body: %(p::before { content: "l\xF6ve" }).force_encoding("US-ASCII"),
52
- headers: {"Content-Type" => "text/css;charset=ISO-8859-1"},
53
+ body: (+%(p::before { content: "l\xF6ve" })).force_encoding("US-ASCII"),
54
+ headers: {"Content-Type" => "text/css;charset=ISO-8859-1"}
53
55
  )
54
56
 
55
57
  # Seems like CssParser strips out the non-ascii character for some
@@ -64,8 +66,8 @@ module Roadie
64
66
 
65
67
  it "assumes UTF-8 encoding if server headers do not specify a charset" do
66
68
  stub_request(:get, url).and_return(
67
- body: %(p::before { content: "Åh nej" }).force_encoding("US-ASCII"),
68
- headers: {"Content-Type" => "text/css"},
69
+ body: (+%(p::before { content: "Åh nej" })).force_encoding("US-ASCII"),
70
+ headers: {"Content-Type" => "text/css"}
69
71
  )
70
72
 
71
73
  # Seems like CssParser strips out the non-ascii characters for some
@@ -117,10 +119,10 @@ module Roadie
117
119
  provider = NetHttpProvider.new(whitelist: ["whitelisted.example.com"])
118
120
 
119
121
  whitelisted_url = "http://whitelisted.example.com/style.css"
120
- other_url = "http://www.example.com/style.css"
122
+ other_url = "http://www.example.com/style.css"
121
123
 
122
- whitelisted_request = stub_request(:get, whitelisted_url).and_return(body: "x")
123
- other_request = stub_request(:get, other_url).and_return(body: "x")
124
+ whitelisted_request = stub_request(:get, whitelisted_url).and_return(body: +"x")
125
+ other_request = stub_request(:get, other_url).and_return(body: +"x")
124
126
 
125
127
  expect(provider.find_stylesheet(other_url)).to be_nil
126
128
  expect {
@@ -1,6 +1,7 @@
1
- # encoding: UTF-8
2
- require 'spec_helper'
3
- require 'shared_examples/asset_provider'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "shared_examples/asset_provider"
4
5
 
5
6
  module Roadie
6
7
  describe NullProvider do
@@ -1,6 +1,7 @@
1
- # encoding: UTF-8
2
- require 'spec_helper'
3
- require 'shared_examples/url_rewriter'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "shared_examples/url_rewriter"
4
5
 
5
6
  module Roadie
6
7
  describe NullUrlRewriter do