sanitize 4.6.6 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sanitize might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/HISTORY.md +176 -16
- data/LICENSE +1 -1
- data/README.md +65 -67
- data/lib/sanitize/config/default.rb +10 -4
- data/lib/sanitize/config/relaxed.rb +1 -1
- data/lib/sanitize/css.rb +2 -2
- data/lib/sanitize/transformers/clean_comment.rb +1 -1
- data/lib/sanitize/transformers/clean_css.rb +3 -3
- data/lib/sanitize/transformers/clean_doctype.rb +1 -1
- data/lib/sanitize/transformers/clean_element.rb +60 -22
- data/lib/sanitize/version.rb +1 -1
- data/lib/sanitize.rb +39 -63
- data/test/common.rb +0 -31
- data/test/test_clean_comment.rb +1 -5
- data/test/test_clean_css.rb +1 -1
- data/test/test_clean_doctype.rb +8 -8
- data/test/test_clean_element.rb +137 -26
- data/test/test_malicious_html.rb +50 -7
- data/test/test_parser.rb +3 -32
- data/test/test_sanitize.rb +103 -18
- data/test/test_sanitize_css.rb +43 -16
- data/test/test_transformers.rb +29 -23
- metadata +17 -33
- data/test/test_unicode.rb +0 -95
data/test/test_sanitize_css.rb
CHANGED
@@ -21,7 +21,7 @@ describe 'Sanitize::CSS' do
|
|
21
21
|
@custom.properties(css).must_equal 'background: #fff; '
|
22
22
|
end
|
23
23
|
|
24
|
-
it 'should allow
|
24
|
+
it 'should allow allowlisted URL protocols' do
|
25
25
|
[
|
26
26
|
"background: url(relative.jpg)",
|
27
27
|
"background: url('relative.jpg')",
|
@@ -36,7 +36,7 @@ describe 'Sanitize::CSS' do
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
-
it 'should not allow non-
|
39
|
+
it 'should not allow non-allowlisted URL protocols' do
|
40
40
|
[
|
41
41
|
"background: url(javascript:alert(0))",
|
42
42
|
"background: url(ja\\56 ascript:alert(0))",
|
@@ -196,26 +196,53 @@ describe 'Sanitize::CSS' do
|
|
196
196
|
|
197
197
|
describe 'class methods' do
|
198
198
|
describe '.properties' do
|
199
|
-
it 'should
|
200
|
-
|
201
|
-
|
202
|
-
|
199
|
+
it 'should sanitize CSS properties with the given config' do
|
200
|
+
css = 'background: #fff; width: expression(alert("hi"));'
|
201
|
+
|
202
|
+
Sanitize::CSS.properties(css).must_equal ' '
|
203
|
+
Sanitize::CSS.properties(css, Sanitize::Config::RELAXED[:css]).must_equal 'background: #fff; '
|
204
|
+
Sanitize::CSS.properties(css, :properties => %w[background color width]).must_equal 'background: #fff; '
|
203
205
|
end
|
204
206
|
end
|
205
207
|
|
206
208
|
describe '.stylesheet' do
|
207
|
-
it 'should
|
208
|
-
|
209
|
-
|
210
|
-
|
209
|
+
it 'should sanitize a CSS stylesheet with the given config' do
|
210
|
+
css = %[
|
211
|
+
/* Yay CSS! */
|
212
|
+
.foo { color: #fff; }
|
213
|
+
#bar { background: url(yay.jpg); }
|
214
|
+
|
215
|
+
@media screen (max-width:480px) {
|
216
|
+
.foo { width: 400px; }
|
217
|
+
#bar:not(.baz) { height: 100px; }
|
218
|
+
}
|
219
|
+
].strip
|
220
|
+
|
221
|
+
Sanitize::CSS.stylesheet(css).strip.must_equal %[
|
222
|
+
.foo { }
|
223
|
+
#bar { }
|
224
|
+
].strip
|
225
|
+
|
226
|
+
Sanitize::CSS.stylesheet(css, Sanitize::Config::RELAXED[:css]).must_equal css
|
227
|
+
|
228
|
+
Sanitize::CSS.stylesheet(css, :properties => %w[background color width]).strip.must_equal %[
|
229
|
+
.foo { color: #fff; }
|
230
|
+
#bar { }
|
231
|
+
].strip
|
211
232
|
end
|
212
233
|
end
|
213
234
|
|
214
235
|
describe '.tree!' do
|
215
|
-
it 'should
|
216
|
-
|
217
|
-
|
218
|
-
|
236
|
+
it 'should sanitize a Crass CSS parse tree with the given config' do
|
237
|
+
tree = Crass.parse(String.new("@import url(foo.css);\n") <<
|
238
|
+
".foo { background: #fff; font: 16pt 'Comic Sans MS'; }\n" <<
|
239
|
+
"#bar { top: 125px; background: green; }")
|
240
|
+
|
241
|
+
Sanitize::CSS.tree!(tree, :properties => %w[background color width]).must_be_same_as tree
|
242
|
+
|
243
|
+
Crass::Parser.stringify(tree).must_equal String.new("\n") <<
|
244
|
+
".foo { background: #fff; }\n" <<
|
245
|
+
"#bar { background: green; }"
|
219
246
|
end
|
220
247
|
end
|
221
248
|
end
|
@@ -280,7 +307,7 @@ describe 'Sanitize::CSS' do
|
|
280
307
|
end
|
281
308
|
|
282
309
|
describe ":at_rules" do
|
283
|
-
it "should remove blockless at-rules that aren't
|
310
|
+
it "should remove blockless at-rules that aren't allowlisted" do
|
284
311
|
css = %[
|
285
312
|
@charset 'utf-8';
|
286
313
|
@import url('foo.css');
|
@@ -292,7 +319,7 @@ describe 'Sanitize::CSS' do
|
|
292
319
|
].strip
|
293
320
|
end
|
294
321
|
|
295
|
-
describe "when blockless at-rules are
|
322
|
+
describe "when blockless at-rules are allowlisted" do
|
296
323
|
before do
|
297
324
|
@scss = Sanitize::CSS.new(Sanitize::Config.merge(Sanitize::Config::RELAXED[:css], {
|
298
325
|
:at_rules => ['charset', 'import']
|
data/test/test_transformers.rb
CHANGED
@@ -12,11 +12,13 @@ describe 'Transformers' do
|
|
12
12
|
return unless env[:node].element?
|
13
13
|
|
14
14
|
env[:config][:foo].must_equal :bar
|
15
|
-
env[:
|
15
|
+
env[:is_allowlisted].must_equal false
|
16
|
+
env[:is_whitelisted].must_equal env[:is_allowlisted]
|
16
17
|
env[:node].must_be_kind_of Nokogiri::XML::Node
|
17
18
|
env[:node_name].must_equal 'span'
|
18
|
-
env[:
|
19
|
-
env[:
|
19
|
+
env[:node_allowlist].must_be_kind_of Set
|
20
|
+
env[:node_allowlist].must_be_empty
|
21
|
+
env[:node_whitelist].must_equal env[:node_allowlist]
|
20
22
|
}
|
21
23
|
)
|
22
24
|
end
|
@@ -43,34 +45,38 @@ describe 'Transformers' do
|
|
43
45
|
nodes.must_equal %w[div span strong b p]
|
44
46
|
end
|
45
47
|
|
46
|
-
it 'should
|
48
|
+
it 'should allowlist nodes in the node allowlist' do
|
47
49
|
Sanitize.fragment('<div class="foo">foo</div><span>bar</span>',
|
48
50
|
:transformers => [
|
49
51
|
proc {|env|
|
50
|
-
{:
|
52
|
+
{:node_allowlist => [env[:node]]} if env[:node_name] == 'div'
|
51
53
|
},
|
52
54
|
|
53
55
|
proc {|env|
|
54
|
-
env[:
|
55
|
-
env[:
|
56
|
-
env[:
|
56
|
+
env[:is_allowlisted].must_equal false unless env[:node_name] == 'div'
|
57
|
+
env[:is_allowlisted].must_equal true if env[:node_name] == 'div'
|
58
|
+
env[:node_allowlist].must_include env[:node] if env[:node_name] == 'div'
|
59
|
+
env[:is_whitelisted].must_equal env[:is_allowlisted]
|
60
|
+
env[:node_whitelist].must_equal env[:node_allowlist]
|
57
61
|
}
|
58
62
|
]
|
59
63
|
).must_equal '<div class="foo">foo</div>bar'
|
60
64
|
end
|
61
65
|
|
62
|
-
it 'should clear the node
|
66
|
+
it 'should clear the node allowlist after each fragment' do
|
63
67
|
called = false
|
64
68
|
|
65
69
|
Sanitize.fragment('<div>foo</div>',
|
66
|
-
:transformers => proc {|env| {:
|
70
|
+
:transformers => proc {|env| {:node_allowlist => [env[:node]]}}
|
67
71
|
)
|
68
72
|
|
69
73
|
Sanitize.fragment('<div>foo</div>',
|
70
74
|
:transformers => proc {|env|
|
71
75
|
called = true
|
72
|
-
env[:
|
73
|
-
env[:
|
76
|
+
env[:is_allowlisted].must_equal false
|
77
|
+
env[:is_whitelisted].must_equal env[:is_allowlisted]
|
78
|
+
env[:node_allowlist].must_be_empty
|
79
|
+
env[:node_whitelist].must_equal env[:node_allowlist]
|
74
80
|
}
|
75
81
|
)
|
76
82
|
|
@@ -83,10 +89,10 @@ describe 'Transformers' do
|
|
83
89
|
.must_equal(' foo ')
|
84
90
|
end
|
85
91
|
|
86
|
-
describe 'Image
|
92
|
+
describe 'Image allowlist transformer' do
|
87
93
|
require 'uri'
|
88
94
|
|
89
|
-
|
95
|
+
image_allowlist_transformer = lambda do |env|
|
90
96
|
# Ignore everything except <img> elements.
|
91
97
|
return unless env[:node_name] == 'img'
|
92
98
|
|
@@ -103,7 +109,7 @@ describe 'Transformers' do
|
|
103
109
|
|
104
110
|
before do
|
105
111
|
@s = Sanitize.new(Sanitize::Config.merge(Sanitize::Config::RELAXED,
|
106
|
-
:transformers =>
|
112
|
+
:transformers => image_allowlist_transformer))
|
107
113
|
end
|
108
114
|
|
109
115
|
it 'should allow images with relative URLs' do
|
@@ -142,8 +148,8 @@ describe 'Transformers' do
|
|
142
148
|
node = env[:node]
|
143
149
|
node_name = env[:node_name]
|
144
150
|
|
145
|
-
# Don't continue if this node is already
|
146
|
-
return if env[:
|
151
|
+
# Don't continue if this node is already allowlisted or is not an element.
|
152
|
+
return if env[:is_allowlisted] || !node.element?
|
147
153
|
|
148
154
|
# Don't continue unless the node is an iframe.
|
149
155
|
return unless node_name == 'iframe'
|
@@ -164,36 +170,36 @@ describe 'Transformers' do
|
|
164
170
|
|
165
171
|
# Now that we're sure that this is a valid YouTube embed and that there are
|
166
172
|
# no unwanted elements or attributes hidden inside it, we can tell Sanitize
|
167
|
-
# to
|
168
|
-
{:
|
173
|
+
# to allowlist the current node.
|
174
|
+
{:node_allowlist => [node]}
|
169
175
|
end
|
170
176
|
|
171
177
|
it 'should allow HTTP YouTube video embeds' do
|
172
178
|
input = '<iframe width="420" height="315" src="http://www.youtube.com/embed/QH2-TGUlwu4" frameborder="0" allowfullscreen bogus="bogus"><script>alert()</script></iframe>'
|
173
179
|
|
174
180
|
Sanitize.fragment(input, :transformers => youtube_transformer)
|
175
|
-
.must_equal '<iframe width="420" height="315" src="http://www.youtube.com/embed/QH2-TGUlwu4" frameborder="0" allowfullscreen=""
|
181
|
+
.must_equal '<iframe width="420" height="315" src="http://www.youtube.com/embed/QH2-TGUlwu4" frameborder="0" allowfullscreen=""></iframe>'
|
176
182
|
end
|
177
183
|
|
178
184
|
it 'should allow HTTPS YouTube video embeds' do
|
179
185
|
input = '<iframe width="420" height="315" src="https://www.youtube.com/embed/QH2-TGUlwu4" frameborder="0" allowfullscreen bogus="bogus"><script>alert()</script></iframe>'
|
180
186
|
|
181
187
|
Sanitize.fragment(input, :transformers => youtube_transformer)
|
182
|
-
.must_equal '<iframe width="420" height="315" src="https://www.youtube.com/embed/QH2-TGUlwu4" frameborder="0" allowfullscreen=""
|
188
|
+
.must_equal '<iframe width="420" height="315" src="https://www.youtube.com/embed/QH2-TGUlwu4" frameborder="0" allowfullscreen=""></iframe>'
|
183
189
|
end
|
184
190
|
|
185
191
|
it 'should allow protocol-relative YouTube video embeds' do
|
186
192
|
input = '<iframe width="420" height="315" src="//www.youtube.com/embed/QH2-TGUlwu4" frameborder="0" allowfullscreen bogus="bogus"><script>alert()</script></iframe>'
|
187
193
|
|
188
194
|
Sanitize.fragment(input, :transformers => youtube_transformer)
|
189
|
-
.must_equal '<iframe width="420" height="315" src="//www.youtube.com/embed/QH2-TGUlwu4" frameborder="0" allowfullscreen=""
|
195
|
+
.must_equal '<iframe width="420" height="315" src="//www.youtube.com/embed/QH2-TGUlwu4" frameborder="0" allowfullscreen=""></iframe>'
|
190
196
|
end
|
191
197
|
|
192
198
|
it 'should allow privacy-enhanced YouTube video embeds' do
|
193
199
|
input = '<iframe width="420" height="315" src="https://www.youtube-nocookie.com/embed/QH2-TGUlwu4" frameborder="0" allowfullscreen bogus="bogus"><script>alert()</script></iframe>'
|
194
200
|
|
195
201
|
Sanitize.fragment(input, :transformers => youtube_transformer)
|
196
|
-
.must_equal '<iframe width="420" height="315" src="https://www.youtube-nocookie.com/embed/QH2-TGUlwu4" frameborder="0" allowfullscreen=""
|
202
|
+
.must_equal '<iframe width="420" height="315" src="https://www.youtube-nocookie.com/embed/QH2-TGUlwu4" frameborder="0" allowfullscreen=""></iframe>'
|
197
203
|
end
|
198
204
|
|
199
205
|
it 'should not allow non-YouTube video embeds' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sanitize
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 6.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Grove
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-08-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: crass
|
@@ -30,59 +30,45 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 1.
|
33
|
+
version: 1.12.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 1.
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: nokogumbo
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '1.4'
|
48
|
-
type: :runtime
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '1.4'
|
40
|
+
version: 1.12.0
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
42
|
name: minitest
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
58
44
|
requirements:
|
59
45
|
- - "~>"
|
60
46
|
- !ruby/object:Gem::Version
|
61
|
-
version: 5.
|
47
|
+
version: 5.14.4
|
62
48
|
type: :development
|
63
49
|
prerelease: false
|
64
50
|
version_requirements: !ruby/object:Gem::Requirement
|
65
51
|
requirements:
|
66
52
|
- - "~>"
|
67
53
|
- !ruby/object:Gem::Version
|
68
|
-
version: 5.
|
54
|
+
version: 5.14.4
|
69
55
|
- !ruby/object:Gem::Dependency
|
70
56
|
name: rake
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
72
58
|
requirements:
|
73
59
|
- - "~>"
|
74
60
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
61
|
+
version: 13.0.6
|
76
62
|
type: :development
|
77
63
|
prerelease: false
|
78
64
|
version_requirements: !ruby/object:Gem::Requirement
|
79
65
|
requirements:
|
80
66
|
- - "~>"
|
81
67
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
83
|
-
description: Sanitize is
|
84
|
-
|
85
|
-
|
68
|
+
version: 13.0.6
|
69
|
+
description: Sanitize is an allowlist-based HTML and CSS sanitizer. It removes all
|
70
|
+
HTML and/or CSS from a string except the elements, attributes, and properties you
|
71
|
+
choose to allow.
|
86
72
|
email: ryan@wonko.com
|
87
73
|
executables: []
|
88
74
|
extensions: []
|
@@ -116,12 +102,11 @@ files:
|
|
116
102
|
- test/test_sanitize.rb
|
117
103
|
- test/test_sanitize_css.rb
|
118
104
|
- test/test_transformers.rb
|
119
|
-
- test/test_unicode.rb
|
120
105
|
homepage: https://github.com/rgrove/sanitize/
|
121
106
|
licenses:
|
122
107
|
- MIT
|
123
108
|
metadata: {}
|
124
|
-
post_install_message:
|
109
|
+
post_install_message:
|
125
110
|
rdoc_options: []
|
126
111
|
require_paths:
|
127
112
|
- lib
|
@@ -129,16 +114,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
129
114
|
requirements:
|
130
115
|
- - ">="
|
131
116
|
- !ruby/object:Gem::Version
|
132
|
-
version:
|
117
|
+
version: 2.5.0
|
133
118
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
134
119
|
requirements:
|
135
120
|
- - ">="
|
136
121
|
- !ruby/object:Gem::Version
|
137
122
|
version: 1.2.0
|
138
123
|
requirements: []
|
139
|
-
|
140
|
-
|
141
|
-
signing_key:
|
124
|
+
rubygems_version: 3.2.22
|
125
|
+
signing_key:
|
142
126
|
specification_version: 4
|
143
|
-
summary:
|
127
|
+
summary: Allowlist-based HTML and CSS sanitizer.
|
144
128
|
test_files: []
|
data/test/test_unicode.rb
DELETED
@@ -1,95 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require_relative 'common'
|
3
|
-
|
4
|
-
describe 'Unicode' do
|
5
|
-
make_my_diffs_pretty!
|
6
|
-
parallelize_me!
|
7
|
-
|
8
|
-
# http://www.w3.org/TR/unicode-xml/#Charlist
|
9
|
-
describe 'Unsuitable characters' do
|
10
|
-
before do
|
11
|
-
@s = Sanitize.new(Sanitize::Config::RELAXED)
|
12
|
-
end
|
13
|
-
|
14
|
-
it 'should not modify the input string' do
|
15
|
-
fragment = "a\u0340b\u0341c"
|
16
|
-
document = "a\u0340b\u0341c"
|
17
|
-
|
18
|
-
@s.document(document)
|
19
|
-
@s.fragment(fragment)
|
20
|
-
|
21
|
-
fragment.must_equal "a\u0340b\u0341c"
|
22
|
-
document.must_equal "a\u0340b\u0341c"
|
23
|
-
end
|
24
|
-
|
25
|
-
it 'should strip deprecated grave and acute clones' do
|
26
|
-
@s.document("a\u0340b\u0341c").must_equal "<html><head></head><body>abc</body></html>\n"
|
27
|
-
@s.fragment("a\u0340b\u0341c").must_equal 'abc'
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'should strip deprecated Khmer characters' do
|
31
|
-
@s.document("a\u17a3b\u17d3c").must_equal "<html><head></head><body>abc</body></html>\n"
|
32
|
-
@s.fragment("a\u17a3b\u17d3c").must_equal 'abc'
|
33
|
-
end
|
34
|
-
|
35
|
-
it 'should strip line and paragraph separator punctuation' do
|
36
|
-
@s.document("a\u2028b\u2029c").must_equal "<html><head></head><body>abc</body></html>\n"
|
37
|
-
@s.fragment("a\u2028b\u2029c").must_equal 'abc'
|
38
|
-
end
|
39
|
-
|
40
|
-
it 'should strip bidi embedding control characters' do
|
41
|
-
@s.document("a\u202ab\u202bc\u202cd\u202de\u202e")
|
42
|
-
.must_equal "<html><head></head><body>abcde</body></html>\n"
|
43
|
-
|
44
|
-
@s.fragment("a\u202ab\u202bc\u202cd\u202de\u202e")
|
45
|
-
.must_equal 'abcde'
|
46
|
-
end
|
47
|
-
|
48
|
-
it 'should strip deprecated symmetric swapping characters' do
|
49
|
-
@s.document("a\u206ab\u206bc").must_equal "<html><head></head><body>abc</body></html>\n"
|
50
|
-
@s.fragment("a\u206ab\u206bc").must_equal 'abc'
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'should strip deprecated Arabic form shaping characters' do
|
54
|
-
@s.document("a\u206cb\u206dc").must_equal "<html><head></head><body>abc</body></html>\n"
|
55
|
-
@s.fragment("a\u206cb\u206dc").must_equal 'abc'
|
56
|
-
end
|
57
|
-
|
58
|
-
it 'should strip deprecated National digit shape characters' do
|
59
|
-
@s.document("a\u206eb\u206fc").must_equal "<html><head></head><body>abc</body></html>\n"
|
60
|
-
@s.fragment("a\u206eb\u206fc").must_equal 'abc'
|
61
|
-
end
|
62
|
-
|
63
|
-
it 'should strip interlinear annotation characters' do
|
64
|
-
@s.document("a\ufff9b\ufffac\ufffb").must_equal "<html><head></head><body>abc</body></html>\n"
|
65
|
-
@s.fragment("a\ufff9b\ufffac\ufffb").must_equal 'abc'
|
66
|
-
end
|
67
|
-
|
68
|
-
it 'should strip BOM/zero-width non-breaking space characters' do
|
69
|
-
@s.document("a\ufeffbc").must_equal "<html><head></head><body>abc</body></html>\n"
|
70
|
-
@s.fragment("a\ufeffbc").must_equal 'abc'
|
71
|
-
end
|
72
|
-
|
73
|
-
it 'should strip object replacement characters' do
|
74
|
-
@s.document("a\ufffcbc").must_equal "<html><head></head><body>abc</body></html>\n"
|
75
|
-
@s.fragment("a\ufffcbc").must_equal 'abc'
|
76
|
-
end
|
77
|
-
|
78
|
-
it 'should strip musical notation scoping characters' do
|
79
|
-
@s.document("a\u{1d173}b\u{1d174}c\u{1d175}d\u{1d176}e\u{1d177}f\u{1d178}g\u{1d179}h\u{1d17a}")
|
80
|
-
.must_equal "<html><head></head><body>abcdefgh</body></html>\n"
|
81
|
-
|
82
|
-
@s.fragment("a\u{1d173}b\u{1d174}c\u{1d175}d\u{1d176}e\u{1d177}f\u{1d178}g\u{1d179}h\u{1d17a}")
|
83
|
-
.must_equal 'abcdefgh'
|
84
|
-
end
|
85
|
-
|
86
|
-
it 'should strip language tag code point characters' do
|
87
|
-
str = String.new 'a'
|
88
|
-
(0xE0000..0xE007F).each {|n| str << [n].pack('U') }
|
89
|
-
str << 'b'
|
90
|
-
|
91
|
-
@s.document(str).must_equal "<html><head></head><body>ab</body></html>\n"
|
92
|
-
@s.fragment(str).must_equal 'ab'
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|