html-pipeline 2.4.1 → 2.4.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +15 -4
- data/Appraisals +13 -0
- data/CHANGELOG.md +4 -0
- data/Gemfile +2 -1
- data/Rakefile +4 -1
- data/html-pipeline.gemspec +2 -3
- data/lib/html/pipeline/emoji_filter.rb +22 -1
- data/lib/html/pipeline/version.rb +1 -1
- metadata +4 -46
- data/script/changelog +0 -47
- data/script/package +0 -7
- data/script/release +0 -16
- data/test/helpers/mocked_instrumentation_service.rb +0 -17
- data/test/html/pipeline/absolute_source_filter_test.rb +0 -55
- data/test/html/pipeline/autolink_filter_test.rb +0 -35
- data/test/html/pipeline/camo_filter_test.rb +0 -77
- data/test/html/pipeline/email_reply_filter_test.rb +0 -66
- data/test/html/pipeline/emoji_filter_test.rb +0 -65
- data/test/html/pipeline/https_filter_test.rb +0 -53
- data/test/html/pipeline/image_filter_test.rb +0 -39
- data/test/html/pipeline/image_max_width_filter_test.rb +0 -50
- data/test/html/pipeline/markdown_filter_test.rb +0 -101
- data/test/html/pipeline/mention_filter_test.rb +0 -212
- data/test/html/pipeline/plain_text_input_filter_test.rb +0 -22
- data/test/html/pipeline/sanitization_filter_test.rb +0 -166
- data/test/html/pipeline/syntax_highlight_filter_test.rb +0 -22
- data/test/html/pipeline/toc_filter_test.rb +0 -134
- data/test/html/pipeline_test.rb +0 -74
- data/test/test_helper.rb +0 -16
@@ -1,212 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class HTML::Pipeline::MentionFilterTest < Minitest::Test
|
4
|
-
def filter(html, base_url='/', info_url=nil, username_pattern=nil)
|
5
|
-
HTML::Pipeline::MentionFilter.call(html, :base_url => base_url, :info_url => info_url, :username_pattern => username_pattern)
|
6
|
-
end
|
7
|
-
|
8
|
-
def test_filtering_a_documentfragment
|
9
|
-
body = "<p>@kneath: check it out.</p>"
|
10
|
-
doc = Nokogiri::HTML::DocumentFragment.parse(body)
|
11
|
-
|
12
|
-
res = filter(doc, '/')
|
13
|
-
assert_same doc, res
|
14
|
-
|
15
|
-
link = "<a href=\"/kneath\" class=\"user-mention\">@kneath</a>"
|
16
|
-
assert_equal "<p>#{link}: check it out.</p>",
|
17
|
-
res.to_html
|
18
|
-
end
|
19
|
-
|
20
|
-
def test_filtering_plain_text
|
21
|
-
body = "<p>@kneath: check it out.</p>"
|
22
|
-
res = filter(body, '/')
|
23
|
-
|
24
|
-
link = "<a href=\"/kneath\" class=\"user-mention\">@kneath</a>"
|
25
|
-
assert_equal "<p>#{link}: check it out.</p>",
|
26
|
-
res.to_html
|
27
|
-
end
|
28
|
-
|
29
|
-
def test_not_replacing_mentions_in_pre_tags
|
30
|
-
body = "<pre>@kneath: okay</pre>"
|
31
|
-
assert_equal body, filter(body).to_html
|
32
|
-
end
|
33
|
-
|
34
|
-
def test_not_replacing_mentions_in_code_tags
|
35
|
-
body = "<p><code>@kneath:</code> okay</p>"
|
36
|
-
assert_equal body, filter(body).to_html
|
37
|
-
end
|
38
|
-
|
39
|
-
def test_not_replacing_mentions_in_style_tags
|
40
|
-
body = "<style>@media (min-width: 768px) { color: red; }</style>"
|
41
|
-
assert_equal body, filter(body).to_html
|
42
|
-
end
|
43
|
-
|
44
|
-
def test_not_replacing_mentions_in_links
|
45
|
-
body = "<p><a>@kneath</a> okay</p>"
|
46
|
-
assert_equal body, filter(body).to_html
|
47
|
-
end
|
48
|
-
|
49
|
-
def test_entity_encoding_and_whatnot
|
50
|
-
body = "<p>@kneath what's up</p>"
|
51
|
-
link = "<a href=\"/kneath\" class=\"user-mention\">@kneath</a>"
|
52
|
-
assert_equal "<p>#{link} what's up</p>", filter(body, '/').to_html
|
53
|
-
end
|
54
|
-
|
55
|
-
def test_html_injection
|
56
|
-
body = "<p>@kneath <script>alert(0)</script></p>"
|
57
|
-
link = "<a href=\"/kneath\" class=\"user-mention\">@kneath</a>"
|
58
|
-
assert_equal "<p>#{link} <script>alert(0)</script></p>",
|
59
|
-
filter(body, '/').to_html
|
60
|
-
end
|
61
|
-
|
62
|
-
def test_links_to_nothing_when_no_info_url_given
|
63
|
-
body = "<p>How do I @mention someone?</p>"
|
64
|
-
assert_equal "<p>How do I @mention someone?</p>",
|
65
|
-
filter(body, '/').to_html
|
66
|
-
end
|
67
|
-
|
68
|
-
def test_links_to_more_info_when_info_url_given
|
69
|
-
body = "<p>How do I @mention someone?</p>"
|
70
|
-
link = "<a href=\"https://github.com/blog/821\" class=\"user-mention\">@mention</a>"
|
71
|
-
assert_equal "<p>How do I #{link} someone?</p>",
|
72
|
-
filter(body, '/', 'https://github.com/blog/821').to_html
|
73
|
-
end
|
74
|
-
|
75
|
-
def test_base_url_slash
|
76
|
-
body = "<p>Hi, @jch!</p>"
|
77
|
-
link = "<a href=\"/jch\" class=\"user-mention\">@jch</a>"
|
78
|
-
assert_equal "<p>Hi, #{link}!</p>",
|
79
|
-
filter(body, '/').to_html
|
80
|
-
end
|
81
|
-
|
82
|
-
def test_base_url_under_custom_route
|
83
|
-
body = "<p>Hi, @jch!</p>"
|
84
|
-
link = "<a href=\"/userprofile/jch\" class=\"user-mention\">@jch</a>"
|
85
|
-
assert_equal "<p>Hi, #{link}!</p>",
|
86
|
-
filter(body, '/userprofile').to_html
|
87
|
-
end
|
88
|
-
|
89
|
-
def test_base_url_slash_with_tilde
|
90
|
-
body = "<p>Hi, @jch!</p>"
|
91
|
-
link = "<a href=\"/~jch\" class=\"user-mention\">@jch</a>"
|
92
|
-
assert_equal "<p>Hi, #{link}!</p>",
|
93
|
-
filter(body, '/~').to_html
|
94
|
-
end
|
95
|
-
|
96
|
-
MarkdownPipeline =
|
97
|
-
HTML::Pipeline.new [
|
98
|
-
HTML::Pipeline::MarkdownFilter,
|
99
|
-
HTML::Pipeline::MentionFilter
|
100
|
-
]
|
101
|
-
|
102
|
-
def mentioned_usernames
|
103
|
-
result = {}
|
104
|
-
MarkdownPipeline.call(@body, {}, result)
|
105
|
-
result[:mentioned_usernames]
|
106
|
-
end
|
107
|
-
|
108
|
-
def test_matches_usernames_in_body
|
109
|
-
@body = "@test how are you?"
|
110
|
-
assert_equal %w[test], mentioned_usernames
|
111
|
-
end
|
112
|
-
|
113
|
-
def test_matches_usernames_with_dashes
|
114
|
-
@body = "hi @some-user"
|
115
|
-
assert_equal %w[some-user], mentioned_usernames
|
116
|
-
end
|
117
|
-
|
118
|
-
def test_matches_usernames_followed_by_a_single_dot
|
119
|
-
@body = "okay @some-user."
|
120
|
-
assert_equal %w[some-user], mentioned_usernames
|
121
|
-
end
|
122
|
-
|
123
|
-
def test_matches_usernames_followed_by_multiple_dots
|
124
|
-
@body = "okay @some-user..."
|
125
|
-
assert_equal %w[some-user], mentioned_usernames
|
126
|
-
end
|
127
|
-
|
128
|
-
def test_does_not_match_email_addresses
|
129
|
-
@body = "aman@tmm1.net"
|
130
|
-
assert_equal [], mentioned_usernames
|
131
|
-
end
|
132
|
-
|
133
|
-
def test_does_not_match_domain_name_looking_things
|
134
|
-
@body = "we need a @github.com email"
|
135
|
-
assert_equal [], mentioned_usernames
|
136
|
-
end
|
137
|
-
|
138
|
-
def test_does_not_match_organization_team_mentions
|
139
|
-
@body = "we need to @github/enterprise know"
|
140
|
-
assert_equal [], mentioned_usernames
|
141
|
-
end
|
142
|
-
|
143
|
-
def test_matches_colon_suffixed_names
|
144
|
-
@body = "@tmm1: what do you think?"
|
145
|
-
assert_equal %w[tmm1], mentioned_usernames
|
146
|
-
end
|
147
|
-
|
148
|
-
def test_matches_list_of_names
|
149
|
-
@body = "@defunkt @atmos @kneath"
|
150
|
-
assert_equal %w[defunkt atmos kneath], mentioned_usernames
|
151
|
-
end
|
152
|
-
|
153
|
-
def test_matches_list_of_names_with_commas
|
154
|
-
@body = "/cc @defunkt, @atmos, @kneath"
|
155
|
-
assert_equal %w[defunkt atmos kneath], mentioned_usernames
|
156
|
-
end
|
157
|
-
|
158
|
-
def test_matches_inside_brackets
|
159
|
-
@body = "(@mislav) and [@rtomayko]"
|
160
|
-
assert_equal %w[mislav rtomayko], mentioned_usernames
|
161
|
-
end
|
162
|
-
|
163
|
-
def test_doesnt_ignore_invalid_users
|
164
|
-
@body = "@defunkt @mojombo and @somedude"
|
165
|
-
assert_equal ['defunkt', 'mojombo', 'somedude'], mentioned_usernames
|
166
|
-
end
|
167
|
-
|
168
|
-
def test_returns_distinct_set
|
169
|
-
@body = "/cc @defunkt, @atmos, @kneath, @defunkt, @defunkt"
|
170
|
-
assert_equal %w[defunkt atmos kneath], mentioned_usernames
|
171
|
-
end
|
172
|
-
|
173
|
-
def test_does_not_match_inline_code_block_with_multiple_code_blocks
|
174
|
-
@body = "something\n\n`/cc @defunkt @atmos @kneath` `/cc @atmos/atmos`"
|
175
|
-
assert_equal %w[], mentioned_usernames
|
176
|
-
end
|
177
|
-
|
178
|
-
def test_mention_at_end_of_parenthetical_sentence
|
179
|
-
@body = "(We're talking 'bout @ymendel.)"
|
180
|
-
assert_equal %w[ymendel], mentioned_usernames
|
181
|
-
end
|
182
|
-
|
183
|
-
def test_username_pattern_can_be_customized
|
184
|
-
body = "<p>@_abc: test.</p>"
|
185
|
-
doc = Nokogiri::HTML::DocumentFragment.parse(body)
|
186
|
-
|
187
|
-
res = filter(doc, '/', nil, /(_[a-z]{3})/)
|
188
|
-
|
189
|
-
link = "<a href=\"/_abc\" class=\"user-mention\">@_abc</a>"
|
190
|
-
assert_equal "<p>#{link}: test.</p>",
|
191
|
-
res.to_html
|
192
|
-
end
|
193
|
-
|
194
|
-
def test_filter_does_not_create_a_new_object_for_default_username_pattern
|
195
|
-
body = "<div>@test</div>"
|
196
|
-
doc = Nokogiri::HTML::DocumentFragment.parse(body)
|
197
|
-
|
198
|
-
filter(doc.clone, '/', nil)
|
199
|
-
pattern_count = HTML::Pipeline::MentionFilter::MentionPatterns.length
|
200
|
-
filter(doc.clone, '/', nil)
|
201
|
-
|
202
|
-
assert_equal pattern_count, HTML::Pipeline::MentionFilter::MentionPatterns.length
|
203
|
-
filter(doc.clone, '/', nil, /test/)
|
204
|
-
assert_equal pattern_count + 1, HTML::Pipeline::MentionFilter::MentionPatterns.length
|
205
|
-
end
|
206
|
-
|
207
|
-
def test_mention_link_filter
|
208
|
-
filter = HTML::Pipeline::MentionFilter.new nil
|
209
|
-
expected = "<a href='/hubot' class='user-mention'>@hubot</a>"
|
210
|
-
assert_equal expected, filter.mention_link_filter("@hubot")
|
211
|
-
end
|
212
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class HTML::Pipeline::PlainTextInputFilterTest < Minitest::Test
|
4
|
-
PlainTextInputFilter = HTML::Pipeline::PlainTextInputFilter
|
5
|
-
|
6
|
-
def test_fails_when_given_a_documentfragment
|
7
|
-
body = "<p>heyo</p>"
|
8
|
-
doc = Nokogiri::HTML::DocumentFragment.parse(body)
|
9
|
-
assert_raises(TypeError) { PlainTextInputFilter.call(doc, {}) }
|
10
|
-
end
|
11
|
-
|
12
|
-
def test_wraps_input_in_a_div_element
|
13
|
-
doc = PlainTextInputFilter.call("howdy pahtner", {})
|
14
|
-
assert_equal "<div>howdy pahtner</div>", doc.to_s
|
15
|
-
end
|
16
|
-
|
17
|
-
def test_html_escapes_plain_text_input
|
18
|
-
doc = PlainTextInputFilter.call("See: <http://example.org>", {})
|
19
|
-
assert_equal "<div>See: <http://example.org></div>",
|
20
|
-
doc.to_s
|
21
|
-
end
|
22
|
-
end
|
@@ -1,166 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class HTML::Pipeline::SanitizationFilterTest < Minitest::Test
|
4
|
-
SanitizationFilter = HTML::Pipeline::SanitizationFilter
|
5
|
-
|
6
|
-
def test_removing_script_tags
|
7
|
-
orig = %(<p><img src="http://github.com/img.png" /><script></script></p>)
|
8
|
-
html = SanitizationFilter.call(orig).to_s
|
9
|
-
refute_match /script/, html
|
10
|
-
end
|
11
|
-
|
12
|
-
def test_removing_style_tags
|
13
|
-
orig = %(<p><style>hey now</style></p>)
|
14
|
-
html = SanitizationFilter.call(orig).to_s
|
15
|
-
refute_match /style/, html
|
16
|
-
end
|
17
|
-
|
18
|
-
def test_removing_style_attributes
|
19
|
-
orig = %(<p style='font-size:1000%'>YO DAWG</p>)
|
20
|
-
html = SanitizationFilter.call(orig).to_s
|
21
|
-
refute_match /font-size/, html
|
22
|
-
refute_match /style/, html
|
23
|
-
end
|
24
|
-
|
25
|
-
def test_removing_script_event_handler_attributes
|
26
|
-
orig = %(<a onclick='javascript:alert(0)'>YO DAWG</a>)
|
27
|
-
html = SanitizationFilter.call(orig).to_s
|
28
|
-
refute_match /javscript/, html
|
29
|
-
refute_match /onclick/, html
|
30
|
-
end
|
31
|
-
|
32
|
-
def test_sanitizes_li_elements_not_contained_in_ul_or_ol
|
33
|
-
stuff = "a\n<li>b</li>\nc"
|
34
|
-
html = SanitizationFilter.call(stuff).to_s
|
35
|
-
assert_equal "a\nb\nc", html
|
36
|
-
end
|
37
|
-
|
38
|
-
def test_does_not_sanitize_li_elements_contained_in_ul_or_ol
|
39
|
-
stuff = "a\n<ul><li>b</li></ul>\nc"
|
40
|
-
assert_equal stuff, SanitizationFilter.call(stuff).to_s
|
41
|
-
end
|
42
|
-
|
43
|
-
def test_github_specific_protocols_are_not_removed
|
44
|
-
stuff = '<a href="github-windows://spillthelog">Spill this yo</a> and so on'
|
45
|
-
assert_equal stuff, SanitizationFilter.call(stuff).to_s
|
46
|
-
end
|
47
|
-
|
48
|
-
def test_unknown_schemes_are_removed
|
49
|
-
stuff = '<a href="something-weird://heyyy">Wat</a> is this'
|
50
|
-
html = SanitizationFilter.call(stuff).to_s
|
51
|
-
assert_equal '<a>Wat</a> is this', html
|
52
|
-
end
|
53
|
-
|
54
|
-
def test_whitelisted_longdesc_schemes_are_allowed
|
55
|
-
stuff = '<img src="./foo.jpg" longdesc="http://longdesc.com">'
|
56
|
-
html = SanitizationFilter.call(stuff).to_s
|
57
|
-
assert_equal '<img src="./foo.jpg" longdesc="http://longdesc.com">', html
|
58
|
-
end
|
59
|
-
|
60
|
-
def test_weird_longdesc_schemes_are_removed
|
61
|
-
stuff = '<img src="./foo.jpg" longdesc="javascript:alert(1)">'
|
62
|
-
html = SanitizationFilter.call(stuff).to_s
|
63
|
-
assert_equal '<img src="./foo.jpg">', html
|
64
|
-
end
|
65
|
-
|
66
|
-
def test_standard_schemes_are_removed_if_not_specified_in_anchor_schemes
|
67
|
-
stuff = '<a href="http://www.example.com/">No href for you</a>'
|
68
|
-
filter = SanitizationFilter.new(stuff, {:anchor_schemes => []})
|
69
|
-
html = filter.call.to_s
|
70
|
-
assert_equal '<a>No href for you</a>', html
|
71
|
-
end
|
72
|
-
|
73
|
-
def test_custom_anchor_schemes_are_not_removed
|
74
|
-
stuff = '<a href="something-weird://heyyy">Wat</a> is this'
|
75
|
-
filter = SanitizationFilter.new(stuff, {:anchor_schemes => ['something-weird']})
|
76
|
-
html = filter.call.to_s
|
77
|
-
assert_equal stuff, html
|
78
|
-
end
|
79
|
-
|
80
|
-
def test_anchor_schemes_are_merged_with_other_anchor_restrictions
|
81
|
-
stuff = '<a href="something-weird://heyyy" ping="more-weird://hiii">Wat</a> is this'
|
82
|
-
whitelist = {
|
83
|
-
:elements => ['a'],
|
84
|
-
:attributes => {'a' => ['href', 'ping']},
|
85
|
-
:protocols => {'a' => {'ping' => ['http']}}
|
86
|
-
}
|
87
|
-
filter = SanitizationFilter.new(stuff, {:whitelist => whitelist, :anchor_schemes => ['something-weird']})
|
88
|
-
html = filter.call.to_s
|
89
|
-
assert_equal '<a href="something-weird://heyyy">Wat</a> is this', html
|
90
|
-
end
|
91
|
-
|
92
|
-
def test_uses_anchor_schemes_from_whitelist_when_not_separately_specified
|
93
|
-
stuff = '<a href="something-weird://heyyy">Wat</a> is this'
|
94
|
-
whitelist = {
|
95
|
-
:elements => ['a'],
|
96
|
-
:attributes => {'a' => ['href']},
|
97
|
-
:protocols => {'a' => {'href' => ['something-weird']}}
|
98
|
-
}
|
99
|
-
filter = SanitizationFilter.new(stuff, {:whitelist => whitelist})
|
100
|
-
html = filter.call.to_s
|
101
|
-
assert_equal stuff, html
|
102
|
-
end
|
103
|
-
|
104
|
-
def test_whitelist_contains_default_anchor_schemes
|
105
|
-
assert_equal SanitizationFilter::WHITELIST[:protocols]['a']['href'], ['http', 'https', 'mailto', :relative, 'github-windows', 'github-mac']
|
106
|
-
end
|
107
|
-
|
108
|
-
def test_whitelist_from_full_constant
|
109
|
-
stuff = '<a href="something-weird://heyyy" ping="more-weird://hiii">Wat</a> is this'
|
110
|
-
filter = SanitizationFilter.new(stuff, :whitelist => SanitizationFilter::FULL)
|
111
|
-
html = filter.call.to_s
|
112
|
-
assert_equal 'Wat is this', html
|
113
|
-
end
|
114
|
-
|
115
|
-
def test_exports_default_anchor_schemes
|
116
|
-
assert_equal SanitizationFilter::ANCHOR_SCHEMES, ['http', 'https', 'mailto', :relative, 'github-windows', 'github-mac']
|
117
|
-
end
|
118
|
-
|
119
|
-
def test_script_contents_are_removed
|
120
|
-
orig = '<script>JavaScript!</script>'
|
121
|
-
assert_equal "", SanitizationFilter.call(orig).to_s
|
122
|
-
end
|
123
|
-
|
124
|
-
def test_table_rows_and_cells_removed_if_not_in_table
|
125
|
-
orig = %(<tr><td>Foo</td></tr><td>Bar</td>)
|
126
|
-
assert_equal 'FooBar', SanitizationFilter.call(orig).to_s
|
127
|
-
end
|
128
|
-
|
129
|
-
def test_table_sections_removed_if_not_in_table
|
130
|
-
orig = %(<thead><tr><td>Foo</td></tr></thead>)
|
131
|
-
assert_equal 'Foo', SanitizationFilter.call(orig).to_s
|
132
|
-
end
|
133
|
-
|
134
|
-
def test_table_sections_are_not_removed
|
135
|
-
orig = %(<table>
|
136
|
-
<thead><tr><th>Column 1</th></tr></thead>
|
137
|
-
<tfoot><tr><td>Sum</td></tr></tfoot>
|
138
|
-
<tbody><tr><td>1</td></tr></tbody>
|
139
|
-
</table>)
|
140
|
-
assert_equal orig, SanitizationFilter.call(orig).to_s
|
141
|
-
end
|
142
|
-
|
143
|
-
def test_summary_tag_are_not_removed
|
144
|
-
orig = %(<summary>Foo</summary>)
|
145
|
-
assert_equal orig, SanitizationFilter.call(orig).to_s
|
146
|
-
end
|
147
|
-
|
148
|
-
def test_details_tag_and_open_attribute_are_not_removed
|
149
|
-
orig = %(<details open>Foo</details>)
|
150
|
-
assert_equal orig, SanitizationFilter.call(orig).to_s
|
151
|
-
end
|
152
|
-
|
153
|
-
def test_nested_details_tag_are_not_removed
|
154
|
-
orig = <<-NESTED
|
155
|
-
<details>
|
156
|
-
<summary>Foo</summary>
|
157
|
-
<details>
|
158
|
-
Bar
|
159
|
-
<summary>Baz</summary>
|
160
|
-
</details>
|
161
|
-
Qux
|
162
|
-
</details>
|
163
|
-
NESTED
|
164
|
-
assert_equal orig, SanitizationFilter.call(orig).to_s
|
165
|
-
end
|
166
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
SyntaxHighlightFilter = HTML::Pipeline::SyntaxHighlightFilter
|
4
|
-
|
5
|
-
class HTML::Pipeline::SyntaxHighlightFilterTest < Minitest::Test
|
6
|
-
def test_highlight_default
|
7
|
-
filter = SyntaxHighlightFilter.new \
|
8
|
-
"<pre>hello</pre>", :highlight => "coffeescript"
|
9
|
-
|
10
|
-
doc = filter.call
|
11
|
-
assert !doc.css(".highlight-coffeescript").empty?
|
12
|
-
end
|
13
|
-
|
14
|
-
def test_highlight_default_will_not_override
|
15
|
-
filter = SyntaxHighlightFilter.new \
|
16
|
-
"<pre lang='c'>hello</pre>", :highlight => "coffeescript"
|
17
|
-
|
18
|
-
doc = filter.call
|
19
|
-
assert doc.css(".highlight-coffeescript").empty?
|
20
|
-
assert !doc.css(".highlight-c").empty?
|
21
|
-
end
|
22
|
-
end
|
@@ -1,134 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require "test_helper"
|
3
|
-
|
4
|
-
class HTML::Pipeline::TableOfContentsFilterTest < Minitest::Test
|
5
|
-
TocFilter = HTML::Pipeline::TableOfContentsFilter
|
6
|
-
|
7
|
-
TocPipeline =
|
8
|
-
HTML::Pipeline.new [
|
9
|
-
HTML::Pipeline::TableOfContentsFilter
|
10
|
-
]
|
11
|
-
|
12
|
-
def toc
|
13
|
-
result = {}
|
14
|
-
TocPipeline.call(@orig, {}, result)
|
15
|
-
result[:toc]
|
16
|
-
end
|
17
|
-
|
18
|
-
def test_anchors_are_added_properly
|
19
|
-
orig = %(<h1>Ice cube</h1><p>Will swarm on any motherfucker in a blue uniform</p>)
|
20
|
-
assert_includes TocFilter.call(orig).to_s, '<a id='
|
21
|
-
end
|
22
|
-
|
23
|
-
def test_custom_anchor_icons_added_properly
|
24
|
-
orig = %(<h1>Ice cube</h1>)
|
25
|
-
expected = %Q{<h1>\n<a id="ice-cube" class="anchor" href="#ice-cube" aria-hidden="true">#</a>Ice cube</h1>}
|
26
|
-
|
27
|
-
assert_equal expected, TocFilter.call(orig, {:anchor_icon => "#"}).to_s
|
28
|
-
end
|
29
|
-
|
30
|
-
def test_toc_list_added_properly
|
31
|
-
@orig = %(<h1>Ice cube</h1><p>Will swarm on any motherfucker in a blue uniform</p>)
|
32
|
-
assert_includes toc, %Q{<ul class="section-nav">\n<li><a href="}
|
33
|
-
end
|
34
|
-
|
35
|
-
def test_anchors_have_sane_names
|
36
|
-
orig = %(<h1>Dr Dre</h1><h1>Ice Cube</h1><h1>Eazy-E</h1><h1>MC Ren</h1>)
|
37
|
-
result = TocFilter.call(orig).to_s
|
38
|
-
|
39
|
-
assert_includes result, '"dr-dre"'
|
40
|
-
assert_includes result, '"ice-cube"'
|
41
|
-
assert_includes result, '"eazy-e"'
|
42
|
-
assert_includes result, '"mc-ren"'
|
43
|
-
end
|
44
|
-
|
45
|
-
def test_anchors_have_aria_hidden
|
46
|
-
orig = "<h1>Straight Outta Compton</h1>"
|
47
|
-
result = TocFilter.call(orig).to_s
|
48
|
-
assert_includes result, 'aria-hidden="true"'
|
49
|
-
end
|
50
|
-
|
51
|
-
def test_toc_hrefs_have_sane_values
|
52
|
-
@orig = %(<h1>Dr Dre</h1><h1>Ice Cube</h1><h1>Eazy-E</h1><h1>MC Ren</h1>)
|
53
|
-
assert_includes toc, '"#dr-dre"'
|
54
|
-
assert_includes toc, '"#ice-cube"'
|
55
|
-
assert_includes toc, '"#eazy-e"'
|
56
|
-
assert_includes toc, '"#mc-ren"'
|
57
|
-
end
|
58
|
-
|
59
|
-
def test_dupe_headers_have_unique_trailing_identifiers
|
60
|
-
orig = %(<h1>Straight Outta Compton</h1>
|
61
|
-
<h2>Dopeman</h2>
|
62
|
-
<h3>Express Yourself</h3>
|
63
|
-
<h1>Dopeman</h1>)
|
64
|
-
|
65
|
-
result = TocFilter.call(orig).to_s
|
66
|
-
|
67
|
-
assert_includes result, '"dopeman"'
|
68
|
-
assert_includes result, '"dopeman-1"'
|
69
|
-
end
|
70
|
-
|
71
|
-
def test_dupe_headers_have_unique_toc_anchors
|
72
|
-
@orig = %(<h1>Straight Outta Compton</h1>
|
73
|
-
<h2>Dopeman</h2>
|
74
|
-
<h3>Express Yourself</h3>
|
75
|
-
<h1>Dopeman</h1>)
|
76
|
-
|
77
|
-
assert_includes toc, '"#dopeman"'
|
78
|
-
assert_includes toc, '"#dopeman-1"'
|
79
|
-
end
|
80
|
-
|
81
|
-
def test_all_header_tags_are_found_when_adding_anchors
|
82
|
-
orig = %(<h1>"Funky President" by James Brown</h1>
|
83
|
-
<h2>"It's My Thing" by Marva Whitney</h2>
|
84
|
-
<h3>"Boogie Back" by Roy Ayers</h3>
|
85
|
-
<h4>"Feel Good" by Fancy</h4>
|
86
|
-
<h5>"Funky Drummer" by James Brown</h5>
|
87
|
-
<h6>"Ruthless Villain" by Eazy-E</h6>
|
88
|
-
<h7>"Be Thankful for What You Got" by William DeVaughn</h7>)
|
89
|
-
|
90
|
-
doc = TocFilter.call(orig)
|
91
|
-
|
92
|
-
assert_equal 6, doc.search('a').size
|
93
|
-
end
|
94
|
-
|
95
|
-
def test_toc_is_complete
|
96
|
-
@orig = %(<h1>"Funky President" by James Brown</h1>
|
97
|
-
<h2>"It's My Thing" by Marva Whitney</h2>
|
98
|
-
<h3>"Boogie Back" by Roy Ayers</h3>
|
99
|
-
<h4>"Feel Good" by Fancy</h4>
|
100
|
-
<h5>"Funky Drummer" by James Brown</h5>
|
101
|
-
<h6>"Ruthless Villain" by Eazy-E</h6>
|
102
|
-
<h7>"Be Thankful for What You Got" by William DeVaughn</h7>)
|
103
|
-
|
104
|
-
expected = %Q{<ul class="section-nav">\n<li><a href="#funky-president-by-james-brown">"Funky President" by James Brown</a></li>\n<li><a href="#its-my-thing-by-marva-whitney">"It's My Thing" by Marva Whitney</a></li>\n<li><a href="#boogie-back-by-roy-ayers">"Boogie Back" by Roy Ayers</a></li>\n<li><a href="#feel-good-by-fancy">"Feel Good" by Fancy</a></li>\n<li><a href="#funky-drummer-by-james-brown">"Funky Drummer" by James Brown</a></li>\n<li><a href="#ruthless-villain-by-eazy-e">"Ruthless Villain" by Eazy-E</a></li>\n</ul>}
|
105
|
-
|
106
|
-
assert_equal expected, toc
|
107
|
-
end
|
108
|
-
|
109
|
-
if RUBY_VERSION > "1.9" # not sure how to make this work on 1.8.7
|
110
|
-
|
111
|
-
def test_anchors_with_utf8_characters
|
112
|
-
orig = %(<h1>日本語</h1>
|
113
|
-
<h1>Русский</h1)
|
114
|
-
|
115
|
-
rendered_h1s = TocFilter.call(orig).search('h1').map(&:to_s)
|
116
|
-
|
117
|
-
assert_equal "<h1>\n<a id=\"日本語\" class=\"anchor\" href=\"#%E6%97%A5%E6%9C%AC%E8%AA%9E\" aria-hidden=\"true\"><span aria-hidden=\"true\" class=\"octicon octicon-link\"></span></a>日本語</h1>",
|
118
|
-
rendered_h1s[0]
|
119
|
-
assert_equal "<h1>\n<a id=\"Русский\" class=\"anchor\" href=\"#%D0%A0%D1%83%D1%81%D1%81%D0%BA%D0%B8%D0%B9\" aria-hidden=\"true\"><span aria-hidden=\"true\" class=\"octicon octicon-link\"></span></a>Русский</h1>",
|
120
|
-
rendered_h1s[1]
|
121
|
-
end
|
122
|
-
|
123
|
-
def test_toc_with_utf8_characters
|
124
|
-
@orig = %(<h1>日本語</h1>
|
125
|
-
<h1>Русский</h1)
|
126
|
-
|
127
|
-
rendered_toc = Nokogiri::HTML::DocumentFragment.parse(toc).to_s
|
128
|
-
|
129
|
-
expected = %Q{<ul class="section-nav">\n<li><a href="#%E6%97%A5%E6%9C%AC%E8%AA%9E">日本語</a></li>\n<li><a href="#%D0%A0%D1%83%D1%81%D1%81%D0%BA%D0%B8%D0%B9">Русский</a></li>\n</ul>}
|
130
|
-
|
131
|
-
assert_equal expected, rendered_toc
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|