sanitize 6.1.3 → 7.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.
@@ -1,245 +1,246 @@
1
- # encoding: utf-8
2
- require_relative 'common'
1
+ # frozen_string_literal: true
3
2
 
4
- describe 'Sanitize::Transformers::CleanElement' do
3
+ require_relative "common"
4
+
5
+ describe "Sanitize::Transformers::CleanElement" do
5
6
  make_my_diffs_pretty!
6
7
  parallelize_me!
7
8
 
8
9
  strings = {
9
- :basic => {
10
- :html => '<b>Lo<!-- comment -->rem</b> <a href="pants" title="foo" style="text-decoration: underline;">ipsum</a> <a href="http://foo.com/"><strong>dolor</strong></a> sit<br/>amet <style>.foo { color: #fff; }</style> <script>alert("hello world");</script>',
11
- :default => 'Lorem ipsum dolor sit amet ',
12
- :restricted => '<b>Lorem</b> ipsum <strong>dolor</strong> sit amet ',
13
- :basic => '<b>Lorem</b> <a href="pants" rel="nofollow">ipsum</a> <a href="http://foo.com/" rel="nofollow"><strong>dolor</strong></a> sit<br>amet ',
14
- :relaxed => '<b>Lorem</b> <a href="pants" title="foo" style="text-decoration: underline;">ipsum</a> <a href="http://foo.com/"><strong>dolor</strong></a> sit<br>amet <style>.foo { color: #fff; }</style> '
10
+ basic: {
11
+ html: '<b>Lo<!-- comment -->rem</b> <a href="pants" title="foo" style="text-decoration: underline;">ipsum</a> <a href="http://foo.com/"><strong>dolor</strong></a> sit<br/>amet <style>.foo { color: #fff; }</style> <script>alert("hello world");</script>',
12
+ default: "Lorem ipsum dolor sit amet ",
13
+ restricted: "<b>Lorem</b> ipsum <strong>dolor</strong> sit amet ",
14
+ basic: '<b>Lorem</b> <a href="pants" rel="nofollow">ipsum</a> <a href="http://foo.com/" rel="nofollow"><strong>dolor</strong></a> sit<br>amet ',
15
+ relaxed: '<b>Lorem</b> <a href="pants" title="foo" style="text-decoration: underline;">ipsum</a> <a href="http://foo.com/"><strong>dolor</strong></a> sit<br>amet <style>.foo { color: #fff; }</style> '
15
16
  },
16
17
 
17
- :malformed => {
18
- :html => 'Lo<!-- comment -->rem</b> <a href=pants title="foo>ipsum <a href="http://foo.com/"><strong>dolor</a></strong> sit<br/>amet <script>alert("hello world");',
19
- :default => 'Lorem dolor sit amet ',
20
- :restricted => 'Lorem <strong>dolor</strong> sit amet ',
21
- :basic => 'Lorem <a href="pants" rel="nofollow"><strong>dolor</strong></a> sit<br>amet ',
22
- :relaxed => 'Lorem <a href="pants" title="foo>ipsum <a href="><strong>dolor</strong></a> sit<br>amet ',
18
+ malformed: {
19
+ html: 'Lo<!-- comment -->rem</b> <a href=pants title="foo>ipsum <a href="http://foo.com/"><strong>dolor</a></strong> sit<br/>amet <script>alert("hello world");',
20
+ default: "Lorem dolor sit amet ",
21
+ restricted: "Lorem <strong>dolor</strong> sit amet ",
22
+ basic: 'Lorem <a href="pants" rel="nofollow"><strong>dolor</strong></a> sit<br>amet ',
23
+ relaxed: 'Lorem <a href="pants" title="foo>ipsum <a href="><strong>dolor</strong></a> sit<br>amet '
23
24
  },
24
25
 
25
- :unclosed => {
26
- :html => '<p>a</p><blockquote>b',
27
- :default => ' a b ',
28
- :restricted => ' a b ',
29
- :basic => '<p>a</p><blockquote>b</blockquote>',
30
- :relaxed => '<p>a</p><blockquote>b</blockquote>'
26
+ unclosed: {
27
+ html: "<p>a</p><blockquote>b",
28
+ default: " a b ",
29
+ restricted: " a b ",
30
+ basic: "<p>a</p><blockquote>b</blockquote>",
31
+ relaxed: "<p>a</p><blockquote>b</blockquote>"
31
32
  },
32
33
 
33
- :malicious => {
34
- :html => '<b>Lo<!-- comment -->rem</b> <a href="javascript:pants" title="foo">ipsum</a> <a href="http://foo.com/"><strong>dolor</strong></a> sit<br/>amet <<foo>script>alert("hello world");</script>',
35
- :default => 'Lorem ipsum dolor sit amet &lt;script&gt;alert("hello world");',
36
- :restricted => '<b>Lorem</b> ipsum <strong>dolor</strong> sit amet &lt;script&gt;alert("hello world");',
37
- :basic => '<b>Lorem</b> <a rel="nofollow">ipsum</a> <a href="http://foo.com/" rel="nofollow"><strong>dolor</strong></a> sit<br>amet &lt;script&gt;alert("hello world");',
38
- :relaxed => '<b>Lorem</b> <a title="foo">ipsum</a> <a href="http://foo.com/"><strong>dolor</strong></a> sit<br>amet &lt;script&gt;alert("hello world");'
34
+ malicious: {
35
+ html: '<b>Lo<!-- comment -->rem</b> <a href="javascript:pants" title="foo">ipsum</a> <a href="http://foo.com/"><strong>dolor</strong></a> sit<br/>amet <<foo>script>alert("hello world");</script>',
36
+ default: 'Lorem ipsum dolor sit amet &lt;script&gt;alert("hello world");',
37
+ restricted: '<b>Lorem</b> ipsum <strong>dolor</strong> sit amet &lt;script&gt;alert("hello world");',
38
+ basic: '<b>Lorem</b> <a rel="nofollow">ipsum</a> <a href="http://foo.com/" rel="nofollow"><strong>dolor</strong></a> sit<br>amet &lt;script&gt;alert("hello world");',
39
+ relaxed: '<b>Lorem</b> <a title="foo">ipsum</a> <a href="http://foo.com/"><strong>dolor</strong></a> sit<br>amet &lt;script&gt;alert("hello world");'
39
40
  }
40
41
  }
41
42
 
42
43
  protocols = {
43
- 'protocol-based JS injection: simple, no spaces' => {
44
- :html => '<a href="javascript:alert(\'XSS\');">foo</a>',
45
- :default => 'foo',
46
- :restricted => 'foo',
47
- :basic => '<a rel="nofollow">foo</a>',
48
- :relaxed => '<a>foo</a>'
44
+ "protocol-based JS injection: simple, no spaces" => {
45
+ html: '<a href="javascript:alert(\'XSS\');">foo</a>',
46
+ default: "foo",
47
+ restricted: "foo",
48
+ basic: '<a rel="nofollow">foo</a>',
49
+ relaxed: "<a>foo</a>"
49
50
  },
50
51
 
51
- 'protocol-based JS injection: simple, spaces before' => {
52
- :html => '<a href="javascript :alert(\'XSS\');">foo</a>',
53
- :default => 'foo',
54
- :restricted => 'foo',
55
- :basic => '<a rel="nofollow">foo</a>',
56
- :relaxed => '<a>foo</a>'
52
+ "protocol-based JS injection: simple, spaces before" => {
53
+ html: '<a href="javascript :alert(\'XSS\');">foo</a>',
54
+ default: "foo",
55
+ restricted: "foo",
56
+ basic: '<a rel="nofollow">foo</a>',
57
+ relaxed: "<a>foo</a>"
57
58
  },
58
59
 
59
- 'protocol-based JS injection: simple, spaces after' => {
60
- :html => '<a href="javascript: alert(\'XSS\');">foo</a>',
61
- :default => 'foo',
62
- :restricted => 'foo',
63
- :basic => '<a rel="nofollow">foo</a>',
64
- :relaxed => '<a>foo</a>'
60
+ "protocol-based JS injection: simple, spaces after" => {
61
+ html: '<a href="javascript: alert(\'XSS\');">foo</a>',
62
+ default: "foo",
63
+ restricted: "foo",
64
+ basic: '<a rel="nofollow">foo</a>',
65
+ relaxed: "<a>foo</a>"
65
66
  },
66
67
 
67
- 'protocol-based JS injection: simple, spaces before and after' => {
68
- :html => '<a href="javascript : alert(\'XSS\');">foo</a>',
69
- :default => 'foo',
70
- :restricted => 'foo',
71
- :basic => '<a rel="nofollow">foo</a>',
72
- :relaxed => '<a>foo</a>'
68
+ "protocol-based JS injection: simple, spaces before and after" => {
69
+ html: '<a href="javascript : alert(\'XSS\');">foo</a>',
70
+ default: "foo",
71
+ restricted: "foo",
72
+ basic: '<a rel="nofollow">foo</a>',
73
+ relaxed: "<a>foo</a>"
73
74
  },
74
75
 
75
- 'protocol-based JS injection: preceding colon' => {
76
- :html => '<a href=":javascript:alert(\'XSS\');">foo</a>',
77
- :default => 'foo',
78
- :restricted => 'foo',
79
- :basic => '<a rel="nofollow">foo</a>',
80
- :relaxed => '<a>foo</a>'
76
+ "protocol-based JS injection: preceding colon" => {
77
+ html: '<a href=":javascript:alert(\'XSS\');">foo</a>',
78
+ default: "foo",
79
+ restricted: "foo",
80
+ basic: '<a rel="nofollow">foo</a>',
81
+ relaxed: "<a>foo</a>"
81
82
  },
82
83
 
83
- 'protocol-based JS injection: UTF-8 encoding' => {
84
- :html => '<a href="javascript&#58;">foo</a>',
85
- :default => 'foo',
86
- :restricted => 'foo',
87
- :basic => '<a rel="nofollow">foo</a>',
88
- :relaxed => '<a>foo</a>'
84
+ "protocol-based JS injection: UTF-8 encoding" => {
85
+ html: '<a href="javascript&#58;">foo</a>',
86
+ default: "foo",
87
+ restricted: "foo",
88
+ basic: '<a rel="nofollow">foo</a>',
89
+ relaxed: "<a>foo</a>"
89
90
  },
90
91
 
91
- 'protocol-based JS injection: long UTF-8 encoding' => {
92
- :html => '<a href="javascript&#0058;">foo</a>',
93
- :default => 'foo',
94
- :restricted => 'foo',
95
- :basic => '<a rel="nofollow">foo</a>',
96
- :relaxed => '<a>foo</a>'
92
+ "protocol-based JS injection: long UTF-8 encoding" => {
93
+ html: '<a href="javascript&#0058;">foo</a>',
94
+ default: "foo",
95
+ restricted: "foo",
96
+ basic: '<a rel="nofollow">foo</a>',
97
+ relaxed: "<a>foo</a>"
97
98
  },
98
99
 
99
- 'protocol-based JS injection: long UTF-8 encoding without semicolons' => {
100
- :html => '<a href=&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041>foo</a>',
101
- :default => 'foo',
102
- :restricted => 'foo',
103
- :basic => '<a rel="nofollow">foo</a>',
104
- :relaxed => '<a>foo</a>'
100
+ "protocol-based JS injection: long UTF-8 encoding without semicolons" => {
101
+ html: "<a href=&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041>foo</a>",
102
+ default: "foo",
103
+ restricted: "foo",
104
+ basic: '<a rel="nofollow">foo</a>',
105
+ relaxed: "<a>foo</a>"
105
106
  },
106
107
 
107
- 'protocol-based JS injection: hex encoding' => {
108
- :html => '<a href="javascript&#x3A;">foo</a>',
109
- :default => 'foo',
110
- :restricted => 'foo',
111
- :basic => '<a rel="nofollow">foo</a>',
112
- :relaxed => '<a>foo</a>'
108
+ "protocol-based JS injection: hex encoding" => {
109
+ html: '<a href="javascript&#x3A;">foo</a>',
110
+ default: "foo",
111
+ restricted: "foo",
112
+ basic: '<a rel="nofollow">foo</a>',
113
+ relaxed: "<a>foo</a>"
113
114
  },
114
115
 
115
- 'protocol-based JS injection: long hex encoding' => {
116
- :html => '<a href="javascript&#x003A;">foo</a>',
117
- :default => 'foo',
118
- :restricted => 'foo',
119
- :basic => '<a rel="nofollow">foo</a>',
120
- :relaxed => '<a>foo</a>'
116
+ "protocol-based JS injection: long hex encoding" => {
117
+ html: '<a href="javascript&#x003A;">foo</a>',
118
+ default: "foo",
119
+ restricted: "foo",
120
+ basic: '<a rel="nofollow">foo</a>',
121
+ relaxed: "<a>foo</a>"
121
122
  },
122
123
 
123
- 'protocol-based JS injection: hex encoding without semicolons' => {
124
- :html => '<a href=&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29>foo</a>',
125
- :default => 'foo',
126
- :restricted => 'foo',
127
- :basic => '<a rel="nofollow">foo</a>',
128
- :relaxed => '<a>foo</a>'
124
+ "protocol-based JS injection: hex encoding without semicolons" => {
125
+ html: "<a href=&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29>foo</a>",
126
+ default: "foo",
127
+ restricted: "foo",
128
+ basic: '<a rel="nofollow">foo</a>',
129
+ relaxed: "<a>foo</a>"
129
130
  },
130
131
 
131
- 'protocol-based JS injection: null char' => {
132
- :html => "<img src=java\0script:alert(\"XSS\")>",
133
- :default => '',
134
- :restricted => '',
135
- :basic => '',
136
- :relaxed => '<img>'
132
+ "protocol-based JS injection: null char" => {
133
+ html: "<img src=java\0script:alert(\"XSS\")>",
134
+ default: "",
135
+ restricted: "",
136
+ basic: "",
137
+ relaxed: "<img>"
137
138
  },
138
139
 
139
- 'protocol-based JS injection: invalid URL char' => {
140
- :html => '<img src=java\script:alert("XSS")>',
141
- :default => '',
142
- :restricted => '',
143
- :basic => '',
144
- :relaxed => '<img>'
140
+ "protocol-based JS injection: invalid URL char" => {
141
+ html: '<img src=java\script:alert("XSS")>',
142
+ default: "",
143
+ restricted: "",
144
+ basic: "",
145
+ relaxed: "<img>"
145
146
  },
146
147
 
147
- 'protocol-based JS injection: spaces and entities' => {
148
- :html => '<img src=" &#14; javascript:alert(\'XSS\');">',
149
- :default => '',
150
- :restricted => '',
151
- :basic => '',
152
- :relaxed => '<img>'
148
+ "protocol-based JS injection: spaces and entities" => {
149
+ html: '<img src=" &#14; javascript:alert(\'XSS\');">',
150
+ default: "",
151
+ restricted: "",
152
+ basic: "",
153
+ relaxed: "<img>"
153
154
  },
154
155
 
155
- 'protocol whitespace' => {
156
- :html => '<a href=" http://example.com/"></a>',
157
- :default => '',
158
- :restricted => '',
159
- :basic => '<a href="http://example.com/" rel="nofollow"></a>',
160
- :relaxed => '<a href="http://example.com/"></a>'
156
+ "protocol whitespace" => {
157
+ html: '<a href=" http://example.com/"></a>',
158
+ default: "",
159
+ restricted: "",
160
+ basic: '<a href="http://example.com/" rel="nofollow"></a>',
161
+ relaxed: '<a href="http://example.com/"></a>'
161
162
  }
162
163
  }
163
164
 
164
- describe 'Default config' do
165
- it 'should remove non-allowlisted elements, leaving safe contents behind' do
165
+ describe "Default config" do
166
+ it "should remove non-allowlisted elements, leaving safe contents behind" do
166
167
  _(Sanitize.fragment('foo <b>bar</b> <strong><a href="#a">baz</a></strong> quux'))
167
- .must_equal 'foo bar baz quux'
168
+ .must_equal "foo bar baz quux"
168
169
 
169
170
  _(Sanitize.fragment('<script>alert("<xss>");</script>'))
170
- .must_equal ''
171
+ .must_equal ""
171
172
 
172
173
  _(Sanitize.fragment('<<script>script>alert("<xss>");</<script>>'))
173
- .must_equal '&lt;'
174
+ .must_equal "&lt;"
174
175
 
175
176
  _(Sanitize.fragment('< script <>> alert("<xss>");</script>'))
176
177
  .must_equal '&lt; script &lt;&gt;&gt; alert("");'
177
178
  end
178
179
 
179
- it 'should surround the contents of :whitespace_elements with space characters when removing the element' do
180
- _(Sanitize.fragment('foo<div>bar</div>baz'))
181
- .must_equal 'foo bar baz'
180
+ it "should surround the contents of :whitespace_elements with space characters when removing the element" do
181
+ _(Sanitize.fragment("foo<div>bar</div>baz"))
182
+ .must_equal "foo bar baz"
182
183
 
183
- _(Sanitize.fragment('foo<br>bar<br>baz'))
184
- .must_equal 'foo bar baz'
184
+ _(Sanitize.fragment("foo<br>bar<br>baz"))
185
+ .must_equal "foo bar baz"
185
186
 
186
- _(Sanitize.fragment('foo<hr>bar<hr>baz'))
187
- .must_equal 'foo bar baz'
187
+ _(Sanitize.fragment("foo<hr>bar<hr>baz"))
188
+ .must_equal "foo bar baz"
188
189
  end
189
190
 
190
- it 'should not choke on several instances of the same element in a row' do
191
+ it "should not choke on several instances of the same element in a row" do
191
192
  _(Sanitize.fragment('<img src="http://www.google.com/intl/en_ALL/images/logo.gif"><img src="http://www.google.com/intl/en_ALL/images/logo.gif"><img src="http://www.google.com/intl/en_ALL/images/logo.gif"><img src="http://www.google.com/intl/en_ALL/images/logo.gif">'))
192
- .must_equal ''
193
+ .must_equal ""
193
194
  end
194
195
 
195
- it 'should not preserve the content of removed `iframe` elements' do
196
- _(Sanitize.fragment('<iframe>hello! <script>alert(0)</script></iframe>'))
197
- .must_equal ''
196
+ it "should not preserve the content of removed `iframe` elements" do
197
+ _(Sanitize.fragment("<iframe>hello! <script>alert(0)</script></iframe>"))
198
+ .must_equal ""
198
199
  end
199
200
 
200
- it 'should not preserve the content of removed `math` elements' do
201
- _(Sanitize.fragment('<math>hello! <script>alert(0)</script></math>'))
202
- .must_equal ''
201
+ it "should not preserve the content of removed `math` elements" do
202
+ _(Sanitize.fragment("<math>hello! <script>alert(0)</script></math>"))
203
+ .must_equal ""
203
204
  end
204
205
 
205
- it 'should not preserve the content of removed `noembed` elements' do
206
- _(Sanitize.fragment('<noembed>hello! <script>alert(0)</script></noembed>'))
207
- .must_equal ''
206
+ it "should not preserve the content of removed `noembed` elements" do
207
+ _(Sanitize.fragment("<noembed>hello! <script>alert(0)</script></noembed>"))
208
+ .must_equal ""
208
209
  end
209
210
 
210
- it 'should not preserve the content of removed `noframes` elements' do
211
- _(Sanitize.fragment('<noframes>hello! <script>alert(0)</script></noframes>'))
212
- .must_equal ''
211
+ it "should not preserve the content of removed `noframes` elements" do
212
+ _(Sanitize.fragment("<noframes>hello! <script>alert(0)</script></noframes>"))
213
+ .must_equal ""
213
214
  end
214
215
 
215
- it 'should not preserve the content of removed `noscript` elements' do
216
- _(Sanitize.fragment('<noscript>hello! <script>alert(0)</script></noscript>'))
217
- .must_equal ''
216
+ it "should not preserve the content of removed `noscript` elements" do
217
+ _(Sanitize.fragment("<noscript>hello! <script>alert(0)</script></noscript>"))
218
+ .must_equal ""
218
219
  end
219
220
 
220
- it 'should not preserve the content of removed `plaintext` elements' do
221
- _(Sanitize.fragment('<plaintext>hello! <script>alert(0)</script>'))
222
- .must_equal ''
221
+ it "should not preserve the content of removed `plaintext` elements" do
222
+ _(Sanitize.fragment("<plaintext>hello! <script>alert(0)</script>"))
223
+ .must_equal ""
223
224
  end
224
225
 
225
- it 'should not preserve the content of removed `script` elements' do
226
- _(Sanitize.fragment('<script>hello! <script>alert(0)</script></script>'))
227
- .must_equal ''
226
+ it "should not preserve the content of removed `script` elements" do
227
+ _(Sanitize.fragment("<script>hello! <script>alert(0)</script></script>"))
228
+ .must_equal ""
228
229
  end
229
230
 
230
- it 'should not preserve the content of removed `style` elements' do
231
- _(Sanitize.fragment('<style>hello! <script>alert(0)</script></style>'))
232
- .must_equal ''
231
+ it "should not preserve the content of removed `style` elements" do
232
+ _(Sanitize.fragment("<style>hello! <script>alert(0)</script></style>"))
233
+ .must_equal ""
233
234
  end
234
235
 
235
- it 'should not preserve the content of removed `svg` elements' do
236
- _(Sanitize.fragment('<svg>hello! <script>alert(0)</script></svg>'))
237
- .must_equal ''
236
+ it "should not preserve the content of removed `svg` elements" do
237
+ _(Sanitize.fragment("<svg>hello! <script>alert(0)</script></svg>"))
238
+ .must_equal ""
238
239
  end
239
240
 
240
- it 'should not preserve the content of removed `xmp` elements' do
241
- _(Sanitize.fragment('<xmp>hello! <script>alert(0)</script></xmp>'))
242
- .must_equal ''
241
+ it "should not preserve the content of removed `xmp` elements" do
242
+ _(Sanitize.fragment("<xmp>hello! <script>alert(0)</script></xmp>"))
243
+ .must_equal ""
243
244
  end
244
245
 
245
246
  strings.each do |name, data|
@@ -255,7 +256,7 @@ describe 'Sanitize::Transformers::CleanElement' do
255
256
  end
256
257
  end
257
258
 
258
- describe 'Restricted config' do
259
+ describe "Restricted config" do
259
260
  before do
260
261
  @s = Sanitize.new(Sanitize::Config::RESTRICTED)
261
262
  end
@@ -273,17 +274,17 @@ describe 'Sanitize::Transformers::CleanElement' do
273
274
  end
274
275
  end
275
276
 
276
- describe 'Basic config' do
277
+ describe "Basic config" do
277
278
  before do
278
279
  @s = Sanitize.new(Sanitize::Config::BASIC)
279
280
  end
280
281
 
281
- it 'should not choke on valueless attributes' do
282
- _(@s.fragment('foo <a href>foo</a> bar'))
282
+ it "should not choke on valueless attributes" do
283
+ _(@s.fragment("foo <a href>foo</a> bar"))
283
284
  .must_equal 'foo <a href="" rel="nofollow">foo</a> bar'
284
285
  end
285
286
 
286
- it 'should downcase attribute names' do
287
+ it "should downcase attribute names" do
287
288
  _(@s.fragment('<a HREF="javascript:alert(\'foo\')">bar</a>'))
288
289
  .must_equal '<a rel="nofollow">bar</a>'
289
290
  end
@@ -301,12 +302,12 @@ describe 'Sanitize::Transformers::CleanElement' do
301
302
  end
302
303
  end
303
304
 
304
- describe 'Relaxed config' do
305
+ describe "Relaxed config" do
305
306
  before do
306
307
  @s = Sanitize.new(Sanitize::Config::RELAXED)
307
308
  end
308
309
 
309
- it 'should encode special chars in attribute values' do
310
+ it "should encode special chars in attribute values" do
310
311
  _(@s.fragment('<a href="http://example.com" title="<b>&eacute;xamples</b> & things">foo</a>'))
311
312
  .must_equal '<a href="http://example.com" title="<b>éxamples</b> &amp; things">foo</a>'
312
313
  end
@@ -324,25 +325,25 @@ describe 'Sanitize::Transformers::CleanElement' do
324
325
  end
325
326
  end
326
327
 
327
- describe 'Custom configs' do
328
- it 'should allow attributes on all elements if allowlisted under :all' do
328
+ describe "Custom configs" do
329
+ it "should allow attributes on all elements if allowlisted under :all" do
329
330
  input = '<p class="foo">bar</p>'
330
331
 
331
- _(Sanitize.fragment(input)).must_equal ' bar '
332
+ _(Sanitize.fragment(input)).must_equal " bar "
332
333
 
333
334
  _(Sanitize.fragment(input, {
334
- :elements => ['p'],
335
- :attributes => {:all => ['class']}
335
+ elements: ["p"],
336
+ attributes: {all: ["class"]}
336
337
  })).must_equal input
337
338
 
338
339
  _(Sanitize.fragment(input, {
339
- :elements => ['p'],
340
- :attributes => {'div' => ['class']}
341
- })).must_equal '<p>bar</p>'
340
+ elements: ["p"],
341
+ attributes: {"div" => ["class"]}
342
+ })).must_equal "<p>bar</p>"
342
343
 
343
344
  _(Sanitize.fragment(input, {
344
- :elements => ['p'],
345
- :attributes => {'p' => ['title'], :all => ['class']}
345
+ elements: ["p"],
346
+ attributes: {"p" => ["title"], :all => ["class"]}
346
347
  })).must_equal input
347
348
  end
348
349
 
@@ -350,203 +351,187 @@ describe 'Sanitize::Transformers::CleanElement' do
350
351
  input = '<a href="/foo/bar">Link</a>'
351
352
 
352
353
  _(Sanitize.fragment(input,
353
- :elements => ['a'],
354
- :attributes => {'a' => ['href']},
355
- :protocols => {'a' => {'href' => ['http']}}
356
- )).must_equal '<a>Link</a>'
354
+ elements: ["a"],
355
+ attributes: {"a" => ["href"]},
356
+ protocols: {"a" => {"href" => ["http"]}})).must_equal "<a>Link</a>"
357
357
  end
358
358
 
359
- it 'should allow relative URLs containing colons when the colon is not in the first path segment' do
359
+ it "should allow relative URLs containing colons when the colon is not in the first path segment" do
360
360
  input = '<a href="/wiki/Special:Random">Random Page</a>'
361
361
 
362
362
  _(Sanitize.fragment(input, {
363
- :elements => ['a'],
364
- :attributes => {'a' => ['href']},
365
- :protocols => {'a' => {'href' => [:relative]}}
363
+ elements: ["a"],
364
+ attributes: {"a" => ["href"]},
365
+ protocols: {"a" => {"href" => [:relative]}}
366
366
  })).must_equal input
367
367
  end
368
368
 
369
- it 'should allow relative URLs containing colons when the colon is part of an anchor' do
369
+ it "should allow relative URLs containing colons when the colon is part of an anchor" do
370
370
  input = '<a href="#fn:1">Footnote 1</a>'
371
371
 
372
372
  _(Sanitize.fragment(input, {
373
- :elements => ['a'],
374
- :attributes => {'a' => ['href']},
375
- :protocols => {'a' => {'href' => [:relative]}}
373
+ elements: ["a"],
374
+ attributes: {"a" => ["href"]},
375
+ protocols: {"a" => {"href" => [:relative]}}
376
376
  })).must_equal input
377
377
 
378
378
  input = '<a href="somepage#fn:1">Footnote 1</a>'
379
379
 
380
380
  _(Sanitize.fragment(input, {
381
- :elements => ['a'],
382
- :attributes => {'a' => ['href']},
383
- :protocols => {'a' => {'href' => [:relative]}}
381
+ elements: ["a"],
382
+ attributes: {"a" => ["href"]},
383
+ protocols: {"a" => {"href" => [:relative]}}
384
384
  })).must_equal input
385
385
  end
386
386
 
387
- it 'should remove the contents of filtered nodes when :remove_contents is true' do
388
- _(Sanitize.fragment('foo bar <div>baz<span>quux</span></div>',
389
- :remove_contents => true
390
- )).must_equal 'foo bar '
387
+ it "should remove the contents of filtered nodes when :remove_contents is true" do
388
+ _(Sanitize.fragment("foo bar <div>baz<span>quux</span></div>",
389
+ remove_contents: true)).must_equal "foo bar "
391
390
  end
392
391
 
393
- it 'should remove the contents of specified nodes when :remove_contents is an Array or Set of element names as strings' do
392
+ it "should remove the contents of specified nodes when :remove_contents is an Array or Set of element names as strings" do
394
393
  _(Sanitize.fragment('foo bar <div>baz<span>quux</span> <b>hi</b><script>alert("hello!");</script></div>',
395
- :remove_contents => ['script', 'span']
396
- )).must_equal 'foo bar baz hi '
394
+ remove_contents: ["script", "span"])).must_equal "foo bar baz hi "
397
395
 
398
396
  _(Sanitize.fragment('foo bar <div>baz<span>quux</span> <b>hi</b><script>alert("hello!");</script></div>',
399
- :remove_contents => Set.new(['script', 'span'])
400
- )).must_equal 'foo bar baz hi '
397
+ remove_contents: Set.new(["script", "span"]))).must_equal "foo bar baz hi "
401
398
  end
402
399
 
403
- it 'should remove the contents of specified nodes when :remove_contents is an Array or Set of element names as symbols' do
400
+ it "should remove the contents of specified nodes when :remove_contents is an Array or Set of element names as symbols" do
404
401
  _(Sanitize.fragment('foo bar <div>baz<span>quux</span> <b>hi</b><script>alert("hello!");</script></div>',
405
- :remove_contents => [:script, :span]
406
- )).must_equal 'foo bar baz hi '
402
+ remove_contents: [:script, :span])).must_equal "foo bar baz hi "
407
403
 
408
404
  _(Sanitize.fragment('foo bar <div>baz<span>quux</span> <b>hi</b><script>alert("hello!");</script></div>',
409
- :remove_contents => Set.new([:script, :span])
410
- )).must_equal 'foo bar baz hi '
405
+ remove_contents: Set.new([:script, :span]))).must_equal "foo bar baz hi "
411
406
  end
412
407
 
413
- it 'should remove the contents of allowlisted iframes' do
414
- _(Sanitize.fragment('<iframe>hi <script>hello</script></iframe>',
415
- :elements => ['iframe']
416
- )).must_equal '<iframe></iframe>'
408
+ it "should remove the contents of allowlisted iframes" do
409
+ _(Sanitize.fragment("<iframe>hi <script>hello</script></iframe>",
410
+ elements: ["iframe"])).must_equal "<iframe></iframe>"
417
411
  end
418
412
 
419
- it 'should not allow arbitrary HTML5 data attributes by default' do
413
+ it "should not allow arbitrary HTML5 data attributes by default" do
420
414
  _(Sanitize.fragment('<b data-foo="bar"></b>',
421
- :elements => ['b']
422
- )).must_equal '<b></b>'
415
+ elements: ["b"])).must_equal "<b></b>"
423
416
 
424
417
  _(Sanitize.fragment('<b class="foo" data-foo="bar"></b>',
425
- :attributes => {'b' => ['class']},
426
- :elements => ['b']
427
- )).must_equal '<b class="foo"></b>'
418
+ attributes: {"b" => ["class"]},
419
+ elements: ["b"])).must_equal '<b class="foo"></b>'
428
420
  end
429
421
 
430
- it 'should allow arbitrary HTML5 data attributes when the :attributes config includes :data' do
422
+ it "should allow arbitrary HTML5 data attributes when the :attributes config includes :data" do
431
423
  s = Sanitize.new(
432
- :attributes => {'b' => [:data]},
433
- :elements => ['b']
424
+ attributes: {"b" => [:data]},
425
+ elements: ["b"]
434
426
  )
435
427
 
436
428
  _(s.fragment('<b data-foo="valid" data-bar="valid"></b>'))
437
429
  .must_equal '<b data-foo="valid" data-bar="valid"></b>'
438
430
 
439
431
  _(s.fragment('<b data-="invalid"></b>'))
440
- .must_equal '<b></b>'
432
+ .must_equal "<b></b>"
441
433
 
442
434
  _(s.fragment('<b data-="invalid"></b>'))
443
- .must_equal '<b></b>'
435
+ .must_equal "<b></b>"
444
436
 
445
437
  _(s.fragment('<b data-xml="invalid"></b>'))
446
- .must_equal '<b></b>'
438
+ .must_equal "<b></b>"
447
439
 
448
440
  _(s.fragment('<b data-xmlfoo="invalid"></b>'))
449
- .must_equal '<b></b>'
441
+ .must_equal "<b></b>"
450
442
 
451
443
  _(s.fragment('<b data-f:oo="valid"></b>'))
452
- .must_equal '<b></b>'
444
+ .must_equal "<b></b>"
453
445
 
454
446
  _(s.fragment('<b data-f/oo="partial"></b>'))
455
447
  .must_equal '<b data-f=""></b>' # Nokogiri quirk; not ideal, but harmless
456
448
 
457
449
  _(s.fragment('<b data-éfoo="valid"></b>'))
458
- .must_equal '<b></b>' # Another annoying Nokogiri quirk.
450
+ .must_equal "<b></b>" # Another annoying Nokogiri quirk.
459
451
  end
460
452
 
461
- it 'should replace whitespace_elements with configured :before and :after values' do
453
+ it "should replace whitespace_elements with configured :before and :after values" do
462
454
  s = Sanitize.new(
463
- :whitespace_elements => {
464
- 'p' => { :before => "\n", :after => "\n" },
465
- 'div' => { :before => "\n", :after => "\n" },
466
- 'br' => { :before => "\n", :after => "\n" },
455
+ whitespace_elements: {
456
+ "p" => {before: "\n", after: "\n"},
457
+ "div" => {before: "\n", after: "\n"},
458
+ "br" => {before: "\n", after: "\n"}
467
459
  }
468
460
  )
469
461
 
470
- _(s.fragment('<p>foo</p>')).must_equal "\nfoo\n"
471
- _(s.fragment('<p>foo</p><p>bar</p>')).must_equal "\nfoo\n\nbar\n"
472
- _(s.fragment('foo<div>bar</div>baz')).must_equal "foo\nbar\nbaz"
473
- _(s.fragment('foo<br>bar<br>baz')).must_equal "foo\nbar\nbaz"
462
+ _(s.fragment("<p>foo</p>")).must_equal "\nfoo\n"
463
+ _(s.fragment("<p>foo</p><p>bar</p>")).must_equal "\nfoo\n\nbar\n"
464
+ _(s.fragment("foo<div>bar</div>baz")).must_equal "foo\nbar\nbaz"
465
+ _(s.fragment("foo<br>bar<br>baz")).must_equal "foo\nbar\nbaz"
474
466
  end
475
467
 
476
- it 'should handle protocols correctly regardless of case' do
468
+ it "should handle protocols correctly regardless of case" do
477
469
  input = '<a href="hTTpS://foo.com/">Text</a>'
478
470
 
479
471
  _(Sanitize.fragment(input, {
480
- :elements => ['a'],
481
- :attributes => {'a' => ['href']},
482
- :protocols => {'a' => {'href' => ['https']}}
472
+ elements: ["a"],
473
+ attributes: {"a" => ["href"]},
474
+ protocols: {"a" => {"href" => ["https"]}}
483
475
  })).must_equal input
484
476
 
485
477
  input = '<a href="mailto:someone@example.com?Subject=Hello">Text</a>'
486
478
 
487
479
  _(Sanitize.fragment(input, {
488
- :elements => ['a'],
489
- :attributes => {'a' => ['href']},
490
- :protocols => {'a' => {'href' => ['https']}}
480
+ elements: ["a"],
481
+ attributes: {"a" => ["href"]},
482
+ protocols: {"a" => {"href" => ["https"]}}
491
483
  })).must_equal "<a>Text</a>"
492
484
  end
493
485
 
494
- it 'should sanitize protocols in data attributes even if data attributes are generically allowed' do
486
+ it "should sanitize protocols in data attributes even if data attributes are generically allowed" do
495
487
  input = '<a data-url="mailto:someone@example.com">Text</a>'
496
488
 
497
489
  _(Sanitize.fragment(input, {
498
- :elements => ['a'],
499
- :attributes => {'a' => [:data]},
500
- :protocols => {'a' => {'data-url' => ['https']}}
490
+ elements: ["a"],
491
+ attributes: {"a" => [:data]},
492
+ protocols: {"a" => {"data-url" => ["https"]}}
501
493
  })).must_equal "<a>Text</a>"
502
494
 
503
495
  _(Sanitize.fragment(input, {
504
- :elements => ['a'],
505
- :attributes => {'a' => [:data]},
506
- :protocols => {'a' => {'data-url' => ['mailto']}}
496
+ elements: ["a"],
497
+ attributes: {"a" => [:data]},
498
+ protocols: {"a" => {"data-url" => ["mailto"]}}
507
499
  })).must_equal input
508
500
  end
509
501
 
510
- it 'should prevent `<meta>` tags from being used to set a non-UTF-8 charset' do
502
+ it "should prevent `<meta>` tags from being used to set a non-UTF-8 charset" do
511
503
  _(Sanitize.document('<html><head><meta charset="utf-8"></head><body>Howdy!</body></html>',
512
- :elements => %w[html head meta body],
513
- :attributes => {'meta' => ['charset']}
514
- )).must_equal "<html><head><meta charset=\"utf-8\"></head><body>Howdy!</body></html>"
504
+ elements: %w[html head meta body],
505
+ attributes: {"meta" => ["charset"]})).must_equal "<html><head><meta charset=\"utf-8\"></head><body>Howdy!</body></html>"
515
506
 
516
507
  _(Sanitize.document('<html><meta charset="utf-8">Howdy!</html>',
517
- :elements => %w[html meta],
518
- :attributes => {'meta' => ['charset']}
519
- )).must_equal "<html><meta charset=\"utf-8\">Howdy!</html>"
508
+ elements: %w[html meta],
509
+ attributes: {"meta" => ["charset"]})).must_equal "<html><meta charset=\"utf-8\">Howdy!</html>"
520
510
 
521
511
  _(Sanitize.document('<html><meta charset="us-ascii">Howdy!</html>',
522
- :elements => %w[html meta],
523
- :attributes => {'meta' => ['charset']}
524
- )).must_equal "<html><meta charset=\"utf-8\">Howdy!</html>"
512
+ elements: %w[html meta],
513
+ attributes: {"meta" => ["charset"]})).must_equal "<html><meta charset=\"utf-8\">Howdy!</html>"
525
514
 
526
515
  _(Sanitize.document('<html><meta http-equiv="content-type" content=" text/html; charset=us-ascii">Howdy!</html>',
527
- :elements => %w[html meta],
528
- :attributes => {'meta' => %w[content http-equiv]}
529
- )).must_equal "<html><meta http-equiv=\"content-type\" content=\" text/html;charset=utf-8\">Howdy!</html>"
516
+ elements: %w[html meta],
517
+ attributes: {"meta" => %w[content http-equiv]})).must_equal "<html><meta http-equiv=\"content-type\" content=\" text/html;charset=utf-8\">Howdy!</html>"
530
518
 
531
519
  _(Sanitize.document('<html><meta http-equiv="Content-Type" content="text/plain;charset = us-ascii">Howdy!</html>',
532
- :elements => %w[html meta],
533
- :attributes => {'meta' => %w[content http-equiv]}
534
- )).must_equal "<html><meta http-equiv=\"Content-Type\" content=\"text/plain;charset=utf-8\">Howdy!</html>"
520
+ elements: %w[html meta],
521
+ attributes: {"meta" => %w[content http-equiv]})).must_equal "<html><meta http-equiv=\"Content-Type\" content=\"text/plain;charset=utf-8\">Howdy!</html>"
535
522
  end
536
523
 
537
- it 'should not modify `<meta>` tags that already set a UTF-8 charset' do
524
+ it "should not modify `<meta>` tags that already set a UTF-8 charset" do
538
525
  _(Sanitize.document('<html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"></head><body>Howdy!</body></html>',
539
- :elements => %w[html head meta body],
540
- :attributes => {'meta' => %w[content http-equiv]}
541
- )).must_equal "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\"></head><body>Howdy!</body></html>"
526
+ elements: %w[html head meta body],
527
+ attributes: {"meta" => %w[content http-equiv]})).must_equal "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\"></head><body>Howdy!</body></html>"
542
528
  end
543
529
 
544
- it 'always removes `<noscript>` elements even if `noscript` is in the allowlist' do
530
+ it "always removes `<noscript>` elements even if `noscript` is in the allowlist" do
545
531
  assert_equal(
546
- '',
547
- Sanitize.fragment('<noscript>foo</noscript>', elements: ['noscript'])
532
+ "",
533
+ Sanitize.fragment("<noscript>foo</noscript>", elements: ["noscript"])
548
534
  )
549
535
  end
550
-
551
536
  end
552
537
  end