motion-html-pipeline 0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +379 -0
- data/lib/motion-html-pipeline.rb +14 -0
- data/lib/motion-html-pipeline/document_fragment.rb +27 -0
- data/lib/motion-html-pipeline/pipeline.rb +153 -0
- data/lib/motion-html-pipeline/pipeline/absolute_source_filter.rb +45 -0
- data/lib/motion-html-pipeline/pipeline/body_content.rb +42 -0
- data/lib/motion-html-pipeline/pipeline/disabled/@mention_filter.rb +140 -0
- data/lib/motion-html-pipeline/pipeline/disabled/autolink_filter.rb +27 -0
- data/lib/motion-html-pipeline/pipeline/disabled/camo_filter.rb +93 -0
- data/lib/motion-html-pipeline/pipeline/disabled/email_reply_filter.rb +66 -0
- data/lib/motion-html-pipeline/pipeline/disabled/emoji_filter.rb +125 -0
- data/lib/motion-html-pipeline/pipeline/disabled/markdown_filter.rb +37 -0
- data/lib/motion-html-pipeline/pipeline/disabled/plain_text_input_filter.rb +13 -0
- data/lib/motion-html-pipeline/pipeline/disabled/sanitization_filter.rb +137 -0
- data/lib/motion-html-pipeline/pipeline/disabled/syntax_highlight_filter.rb +44 -0
- data/lib/motion-html-pipeline/pipeline/disabled/toc_filter.rb +67 -0
- data/lib/motion-html-pipeline/pipeline/filter.rb +163 -0
- data/lib/motion-html-pipeline/pipeline/https_filter.rb +27 -0
- data/lib/motion-html-pipeline/pipeline/image_filter.rb +17 -0
- data/lib/motion-html-pipeline/pipeline/image_max_width_filter.rb +37 -0
- data/lib/motion-html-pipeline/pipeline/text_filter.rb +14 -0
- data/lib/motion-html-pipeline/pipeline/version.rb +5 -0
- data/spec/motion-html-pipeline/_helpers/mock_instumentation_service.rb +19 -0
- data/spec/motion-html-pipeline/pipeline/absolute_source_filter_spec.rb +47 -0
- data/spec/motion-html-pipeline/pipeline/disabled/auto_link_filter_spec.rb +33 -0
- data/spec/motion-html-pipeline/pipeline/disabled/camo_filter_spec.rb +75 -0
- data/spec/motion-html-pipeline/pipeline/disabled/email_reply_filter_spec.rb +64 -0
- data/spec/motion-html-pipeline/pipeline/disabled/emoji_filter_spec.rb +92 -0
- data/spec/motion-html-pipeline/pipeline/disabled/markdown_filter_spec.rb +112 -0
- data/spec/motion-html-pipeline/pipeline/disabled/plain_text_input_filter_spec.rb +20 -0
- data/spec/motion-html-pipeline/pipeline/disabled/sanitization_filter_spec.rb +164 -0
- data/spec/motion-html-pipeline/pipeline/disabled/syntax_highlighting_filter_spec.rb +59 -0
- data/spec/motion-html-pipeline/pipeline/disabled/toc_filter_spec.rb +137 -0
- data/spec/motion-html-pipeline/pipeline/https_filter_spec.rb +52 -0
- data/spec/motion-html-pipeline/pipeline/image_filter_spec.rb +37 -0
- data/spec/motion-html-pipeline/pipeline/image_max_width_filter_spec.rb +57 -0
- data/spec/motion-html-pipeline/pipeline_spec.rb +80 -0
- data/spec/spec_helper.rb +48 -0
- metadata +147 -0
@@ -0,0 +1,112 @@
|
|
1
|
+
# describe 'MotionHTMLPipeline::Pipeline::MarkdownFilterTest' do
|
2
|
+
# MarkdownFilter = MotionHTMLPipeline::Pipeline::MarkdownFilter
|
3
|
+
#
|
4
|
+
# def setup
|
5
|
+
# @haiku =
|
6
|
+
# "Pointing at the moon\n" \
|
7
|
+
# "Reminded of simple things\n" \
|
8
|
+
# 'Moments matter most'
|
9
|
+
# @links =
|
10
|
+
# 'See http://example.org/ for more info'
|
11
|
+
# @code =
|
12
|
+
# "```\n" \
|
13
|
+
# 'def hello()' \
|
14
|
+
# " 'world'" \
|
15
|
+
# 'end' \
|
16
|
+
# '```'
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# def test_fails_when_given_a_documentfragment
|
20
|
+
# body = '<p>heyo</p>'
|
21
|
+
# doc = HTML::Pipeline.parse(body)
|
22
|
+
# assert_raises(TypeError) { MarkdownFilter.call(doc, {}) }
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# def test_gfm_enabled_by_default
|
26
|
+
# doc = MarkdownFilter.to_document(@haiku, {})
|
27
|
+
# assert doc.is_a?(HTML::Pipeline::DocumentFragment)
|
28
|
+
# assert_equal 2, doc.search('br').size
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# def test_disabling_gfm
|
32
|
+
# doc = MarkdownFilter.to_document(@haiku, gfm: false)
|
33
|
+
# assert doc.is_a?(HTML::Pipeline::DocumentFragment)
|
34
|
+
# assert_equal 0, doc.search('br').size
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# def test_fenced_code_blocks
|
38
|
+
# doc = MarkdownFilter.to_document(@code)
|
39
|
+
# assert doc.is_a?(HTML::Pipeline::DocumentFragment)
|
40
|
+
# assert_equal 1, doc.search('pre').size
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# def test_fenced_code_blocks_with_language
|
44
|
+
# doc = MarkdownFilter.to_document(@code.sub('```', '``` ruby'))
|
45
|
+
# assert doc.is_a?(HTML::Pipeline::DocumentFragment)
|
46
|
+
# assert_equal 1, doc.search('pre').size
|
47
|
+
# assert_equal 'ruby', doc.search('pre').first['lang']
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# def test_standard_extensions
|
51
|
+
# iframe = "<iframe src='http://www.google.com'></iframe>"
|
52
|
+
# iframe_escaped = "<iframe src='http://www.google.com'></iframe>"
|
53
|
+
# doc = MarkdownFilter.new(iframe, unsafe: true).call
|
54
|
+
# assert_equal(doc, iframe_escaped)
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# def test_changing_extensions
|
58
|
+
# iframe = "<iframe src='http://www.google.com'></iframe>"
|
59
|
+
# doc = MarkdownFilter.new(iframe, commonmarker_extensions: [], unsafe: true).call
|
60
|
+
# assert_equal(doc, iframe)
|
61
|
+
# end
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
# class GFMTest < Minitest::Test
|
65
|
+
# def gfm(text)
|
66
|
+
# MarkdownFilter.call(text, gfm: true, unsafe: true)
|
67
|
+
# end
|
68
|
+
#
|
69
|
+
# def test_not_touch_single_underscores_inside_words
|
70
|
+
# assert_equal '<p>foo_bar</p>',
|
71
|
+
# gfm('foo_bar')
|
72
|
+
# end
|
73
|
+
#
|
74
|
+
# def test_not_touch_underscores_in_code_blocks
|
75
|
+
# assert_equal "<pre><code>foo_bar_baz\n</code></pre>",
|
76
|
+
# gfm(' foo_bar_baz')
|
77
|
+
# end
|
78
|
+
#
|
79
|
+
# def test_not_touch_underscores_in_pre_blocks
|
80
|
+
# assert_equal "<pre>\nfoo_bar_baz\n</pre>",
|
81
|
+
# gfm("<pre>\nfoo_bar_baz\n</pre>")
|
82
|
+
# end
|
83
|
+
#
|
84
|
+
# def test_not_touch_two_or_more_underscores_inside_words
|
85
|
+
# assert_equal '<p>foo_bar_baz</p>',
|
86
|
+
# gfm('foo_bar_baz')
|
87
|
+
# end
|
88
|
+
#
|
89
|
+
# def test_turn_newlines_into_br_tags_in_simple_cases
|
90
|
+
# assert_equal "<p>foo<br />\nbar</p>",
|
91
|
+
# gfm("foo\nbar")
|
92
|
+
# end
|
93
|
+
#
|
94
|
+
# def test_convert_newlines_in_all_groups
|
95
|
+
# assert_equal "<p>apple<br />\npear<br />\norange</p>\n" \
|
96
|
+
# "<p>ruby<br />\npython<br />\nerlang</p>",
|
97
|
+
# gfm("apple\npear\norange\n\nruby\npython\nerlang")
|
98
|
+
# end
|
99
|
+
#
|
100
|
+
# def test_convert_newlines_in_even_long_groups
|
101
|
+
# assert_equal "<p>apple<br />\npear<br />\norange<br />\nbanana</p>\n" \
|
102
|
+
# "<p>ruby<br />\npython<br />\nerlang</p>",
|
103
|
+
# gfm("apple\npear\norange\nbanana\n\nruby\npython\nerlang")
|
104
|
+
# end
|
105
|
+
#
|
106
|
+
# def test_not_convert_newlines_in_lists
|
107
|
+
# assert_equal "<h1>foo</h1>\n<h1>bar</h1>",
|
108
|
+
# gfm("# foo\n# bar")
|
109
|
+
# assert_equal "<ul>\n<li>foo</li>\n<li>bar</li>\n</ul>",
|
110
|
+
# gfm("* foo\n* bar")
|
111
|
+
# end
|
112
|
+
# end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# describe 'MotionHTMLPipeline::Pipeline::PlainTextInputFilterTest' do
|
2
|
+
# PlainTextInputFilter = MotionHTMLPipeline::Pipeline::PlainTextInputFilter
|
3
|
+
#
|
4
|
+
# def test_fails_when_given_a_documentfragment
|
5
|
+
# body = '<p>heyo</p>'
|
6
|
+
# doc = Nokogiri::HTML::DocumentFragment.parse(body)
|
7
|
+
# assert_raises(TypeError) { PlainTextInputFilter.call(doc, {}) }
|
8
|
+
# end
|
9
|
+
#
|
10
|
+
# def test_wraps_input_in_a_div_element
|
11
|
+
# doc = PlainTextInputFilter.call('howdy pahtner', {})
|
12
|
+
# assert_equal '<div>howdy pahtner</div>', doc.to_s
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# def test_html_escapes_plain_text_input
|
16
|
+
# doc = PlainTextInputFilter.call('See: <http://example.org>', {})
|
17
|
+
# assert_equal '<div>See: <http://example.org></div>',
|
18
|
+
# doc.to_s
|
19
|
+
# end
|
20
|
+
# end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
# describe 'MotionHTMLPipeline::Pipeline::SanitizationFilterTest' do
|
2
|
+
# SanitizationFilter = MotionHTMLPipeline::Pipeline::SanitizationFilter
|
3
|
+
#
|
4
|
+
# def test_removing_script_tags
|
5
|
+
# orig = %(<p><img src="http://github.com/img.png" /><script></script></p>)
|
6
|
+
# html = SanitizationFilter.call(orig).to_s
|
7
|
+
# refute_match /script/, html
|
8
|
+
# end
|
9
|
+
#
|
10
|
+
# def test_removing_style_tags
|
11
|
+
# orig = %(<p><style>hey now</style></p>)
|
12
|
+
# html = SanitizationFilter.call(orig).to_s
|
13
|
+
# refute_match /style/, html
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# def test_removing_style_attributes
|
17
|
+
# orig = %(<p style='font-size:1000%'>YO DAWG</p>)
|
18
|
+
# html = SanitizationFilter.call(orig).to_s
|
19
|
+
# refute_match /font-size/, html
|
20
|
+
# refute_match /style/, html
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# def test_removing_script_event_handler_attributes
|
24
|
+
# orig = %(<a onclick='javascript:alert(0)'>YO DAWG</a>)
|
25
|
+
# html = SanitizationFilter.call(orig).to_s
|
26
|
+
# refute_match /javscript/, html
|
27
|
+
# refute_match /onclick/, html
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# def test_sanitizes_li_elements_not_contained_in_ul_or_ol
|
31
|
+
# stuff = "a\n<li>b</li>\nc"
|
32
|
+
# html = SanitizationFilter.call(stuff).to_s
|
33
|
+
# assert_equal "a\nb\nc", html
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# def test_does_not_sanitize_li_elements_contained_in_ul_or_ol
|
37
|
+
# stuff = "a\n<ul><li>b</li></ul>\nc"
|
38
|
+
# assert_equal stuff, SanitizationFilter.call(stuff).to_s
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# def test_github_specific_protocols_are_not_removed
|
42
|
+
# stuff = '<a href="github-windows://spillthelog">Spill this yo</a> and so on'
|
43
|
+
# assert_equal stuff, SanitizationFilter.call(stuff).to_s
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# def test_unknown_schemes_are_removed
|
47
|
+
# stuff = '<a href="something-weird://heyyy">Wat</a> is this'
|
48
|
+
# html = SanitizationFilter.call(stuff).to_s
|
49
|
+
# assert_equal '<a>Wat</a> is this', html
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# def test_whitelisted_longdesc_schemes_are_allowed
|
53
|
+
# stuff = '<img src="./foo.jpg" longdesc="http://longdesc.com">'
|
54
|
+
# html = SanitizationFilter.call(stuff).to_s
|
55
|
+
# assert_equal '<img src="./foo.jpg" longdesc="http://longdesc.com">', html
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# def test_weird_longdesc_schemes_are_removed
|
59
|
+
# stuff = '<img src="./foo.jpg" longdesc="javascript:alert(1)">'
|
60
|
+
# html = SanitizationFilter.call(stuff).to_s
|
61
|
+
# assert_equal '<img src="./foo.jpg">', html
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
# def test_standard_schemes_are_removed_if_not_specified_in_anchor_schemes
|
65
|
+
# stuff = '<a href="http://www.example.com/">No href for you</a>'
|
66
|
+
# filter = SanitizationFilter.new(stuff, anchor_schemes: [])
|
67
|
+
# html = filter.call.to_s
|
68
|
+
# assert_equal '<a>No href for you</a>', html
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# def test_custom_anchor_schemes_are_not_removed
|
72
|
+
# stuff = '<a href="something-weird://heyyy">Wat</a> is this'
|
73
|
+
# filter = SanitizationFilter.new(stuff, anchor_schemes: ['something-weird'])
|
74
|
+
# html = filter.call.to_s
|
75
|
+
# assert_equal stuff, html
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
# def test_anchor_schemes_are_merged_with_other_anchor_restrictions
|
79
|
+
# stuff = '<a href="something-weird://heyyy" ping="more-weird://hiii">Wat</a> is this'
|
80
|
+
# whitelist = {
|
81
|
+
# elements: ['a'],
|
82
|
+
# attributes: { 'a' => %w[href ping] },
|
83
|
+
# protocols: { 'a' => { 'ping' => ['http'] } }
|
84
|
+
# }
|
85
|
+
# filter = SanitizationFilter.new(stuff, whitelist: whitelist, anchor_schemes: ['something-weird'])
|
86
|
+
# html = filter.call.to_s
|
87
|
+
# assert_equal '<a href="something-weird://heyyy">Wat</a> is this', html
|
88
|
+
# end
|
89
|
+
#
|
90
|
+
# def test_uses_anchor_schemes_from_whitelist_when_not_separately_specified
|
91
|
+
# stuff = '<a href="something-weird://heyyy">Wat</a> is this'
|
92
|
+
# whitelist = {
|
93
|
+
# elements: ['a'],
|
94
|
+
# attributes: { 'a' => ['href'] },
|
95
|
+
# protocols: { 'a' => { 'href' => ['something-weird'] } }
|
96
|
+
# }
|
97
|
+
# filter = SanitizationFilter.new(stuff, whitelist: whitelist)
|
98
|
+
# html = filter.call.to_s
|
99
|
+
# assert_equal stuff, html
|
100
|
+
# end
|
101
|
+
#
|
102
|
+
# def test_whitelist_contains_default_anchor_schemes
|
103
|
+
# assert_equal SanitizationFilter::WHITELIST[:protocols]['a']['href'], ['http', 'https', 'mailto', 'xmpp', :relative, 'github-windows', 'github-mac', 'irc', 'ircs']
|
104
|
+
# end
|
105
|
+
#
|
106
|
+
# def test_whitelist_from_full_constant
|
107
|
+
# stuff = '<a href="something-weird://heyyy" ping="more-weird://hiii">Wat</a> is this'
|
108
|
+
# filter = SanitizationFilter.new(stuff, whitelist: SanitizationFilter::FULL)
|
109
|
+
# html = filter.call.to_s
|
110
|
+
# assert_equal 'Wat is this', html
|
111
|
+
# end
|
112
|
+
#
|
113
|
+
# def test_exports_default_anchor_schemes
|
114
|
+
# assert_equal SanitizationFilter::ANCHOR_SCHEMES, ['http', 'https', 'mailto', 'xmpp', :relative, 'github-windows', 'github-mac', 'irc', 'ircs']
|
115
|
+
# end
|
116
|
+
#
|
117
|
+
# def test_script_contents_are_removed
|
118
|
+
# orig = '<script>JavaScript!</script>'
|
119
|
+
# assert_equal '', SanitizationFilter.call(orig).to_s
|
120
|
+
# end
|
121
|
+
#
|
122
|
+
# def test_table_rows_and_cells_removed_if_not_in_table
|
123
|
+
# orig = %(<tr><td>Foo</td></tr><td>Bar</td>)
|
124
|
+
# assert_equal 'FooBar', SanitizationFilter.call(orig).to_s
|
125
|
+
# end
|
126
|
+
#
|
127
|
+
# def test_table_sections_removed_if_not_in_table
|
128
|
+
# orig = %(<thead><tr><td>Foo</td></tr></thead>)
|
129
|
+
# assert_equal 'Foo', SanitizationFilter.call(orig).to_s
|
130
|
+
# end
|
131
|
+
#
|
132
|
+
# def test_table_sections_are_not_removed
|
133
|
+
# orig = %(<table>
|
134
|
+
# <thead><tr><th>Column 1</th></tr></thead>
|
135
|
+
# <tfoot><tr><td>Sum</td></tr></tfoot>
|
136
|
+
# <tbody><tr><td>1</td></tr></tbody>
|
137
|
+
# </table>)
|
138
|
+
# assert_equal orig, SanitizationFilter.call(orig).to_s
|
139
|
+
# end
|
140
|
+
#
|
141
|
+
# def test_summary_tag_are_not_removed
|
142
|
+
# orig = %(<summary>Foo</summary>)
|
143
|
+
# assert_equal orig, SanitizationFilter.call(orig).to_s
|
144
|
+
# end
|
145
|
+
#
|
146
|
+
# def test_details_tag_and_open_attribute_are_not_removed
|
147
|
+
# orig = %(<details open>Foo</details>)
|
148
|
+
# assert_equal orig, SanitizationFilter.call(orig).to_s
|
149
|
+
# end
|
150
|
+
#
|
151
|
+
# def test_nested_details_tag_are_not_removed
|
152
|
+
# orig = <<-NESTED
|
153
|
+
# <details>
|
154
|
+
# <summary>Foo</summary>
|
155
|
+
# <details>
|
156
|
+
# Bar
|
157
|
+
# <summary>Baz</summary>
|
158
|
+
# </details>
|
159
|
+
# Qux
|
160
|
+
# </details>
|
161
|
+
# NESTED
|
162
|
+
# assert_equal orig, SanitizationFilter.call(orig).to_s
|
163
|
+
# end
|
164
|
+
# end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# describe 'MotionHTMLPipeline::Pipeline::SyntaxHighlightFilterTest' do
|
2
|
+
# SyntaxHighlightFilter = MotionHTMLPipeline::Pipeline::SyntaxHighlightFilter
|
3
|
+
#
|
4
|
+
# def test_highlight_default
|
5
|
+
# filter = SyntaxHighlightFilter.new \
|
6
|
+
# '<pre>hello</pre>', highlight: 'coffeescript'
|
7
|
+
#
|
8
|
+
# doc = filter.call
|
9
|
+
# assert !doc.css('.highlight-coffeescript').empty?
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# def test_highlight_default_will_not_override
|
13
|
+
# filter = SyntaxHighlightFilter.new \
|
14
|
+
# "<pre lang='c'>hello</pre>", highlight: 'coffeescript'
|
15
|
+
#
|
16
|
+
# doc = filter.call
|
17
|
+
# assert doc.css('.highlight-coffeescript').empty?
|
18
|
+
# assert !doc.css('.highlight-c').empty?
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# def test_highlight_does_not_remove_pre_tag
|
22
|
+
# filter = SyntaxHighlightFilter.new \
|
23
|
+
# "<pre lang='c'>hello</pre>", highlight: 'coffeescript'
|
24
|
+
#
|
25
|
+
# doc = filter.call
|
26
|
+
#
|
27
|
+
# assert !doc.css('pre').empty?
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# def test_highlight_allows_optional_scope
|
31
|
+
# filter = SyntaxHighlightFilter.new \
|
32
|
+
# "<pre lang='c'>hello</pre>", highlight: 'coffeescript', scope: 'test-scope'
|
33
|
+
#
|
34
|
+
# doc = filter.call
|
35
|
+
#
|
36
|
+
# assert !doc.css('pre.test-scope').empty?
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# def test_highlight_keeps_the_pre_tags_lang
|
40
|
+
# filter = SyntaxHighlightFilter.new \
|
41
|
+
# "<pre lang='c'>hello</pre>", highlight: 'coffeescript'
|
42
|
+
#
|
43
|
+
# doc = filter.call
|
44
|
+
#
|
45
|
+
# assert !doc.css('pre[lang=c]').empty?
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# def test_highlight_handles_nested_pre_tags
|
49
|
+
# inner_code = "<pre>console.log('i am nested!')</pre>"
|
50
|
+
# escaped = EscapeUtils.escape_html(inner_code)
|
51
|
+
# html = "<pre lang='html'>#{escaped}</pre>"
|
52
|
+
# filter = SyntaxHighlightFilter.new html, highlight: 'html'
|
53
|
+
#
|
54
|
+
# doc = filter.call
|
55
|
+
#
|
56
|
+
# assert_equal 2, doc.css('span[class=nt]').length
|
57
|
+
# assert_equal EscapeUtils.unescape_html(escaped), doc.inner_text
|
58
|
+
# end
|
59
|
+
# end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
# describe 'MotionHTMLPipeline::Pipeline::TableOfContentsFilterTest' do
|
2
|
+
# TocFilter = MotionHTMLPipeline::Pipeline::TableOfContentsFilter
|
3
|
+
#
|
4
|
+
# TocPipeline =
|
5
|
+
# HTML::Pipeline.new [
|
6
|
+
# HTML::Pipeline::TableOfContentsFilter
|
7
|
+
# ]
|
8
|
+
#
|
9
|
+
# def toc
|
10
|
+
# result = {}
|
11
|
+
# TocPipeline.call(@orig, {}, result)
|
12
|
+
# result[:toc]
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# def test_anchors_are_added_properly
|
16
|
+
# orig = %(<h1>Ice cube</h1><p>Will swarm on any motherfucker in a blue uniform</p>)
|
17
|
+
# assert_includes TocFilter.call(orig).to_s, '<a id='
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# def test_custom_anchor_icons_added_properly
|
21
|
+
# orig = %(<h1>Ice cube</h1>)
|
22
|
+
# expected = %(<h1>\n<a id="ice-cube" class="anchor" href="#ice-cube" aria-hidden="true">#</a>Ice cube</h1>)
|
23
|
+
#
|
24
|
+
# assert_equal expected, TocFilter.call(orig, anchor_icon: '#').to_s
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# def test_toc_list_added_properly
|
28
|
+
# @orig = %(<h1>Ice cube</h1><p>Will swarm on any motherfucker in a blue uniform</p>)
|
29
|
+
# assert_includes toc, %(<ul class="section-nav">\n<li><a href=")
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# def test_anchors_have_sane_names
|
33
|
+
# orig = %(<h1>Dr Dre</h1><h1>Ice Cube</h1><h1>Eazy-E</h1><h1>MC Ren</h1>)
|
34
|
+
# result = TocFilter.call(orig).to_s
|
35
|
+
#
|
36
|
+
# assert_includes result, '"dr-dre"'
|
37
|
+
# assert_includes result, '"ice-cube"'
|
38
|
+
# assert_includes result, '"eazy-e"'
|
39
|
+
# assert_includes result, '"mc-ren"'
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# def test_anchors_have_aria_hidden
|
43
|
+
# orig = '<h1>Straight Outta Compton</h1>'
|
44
|
+
# result = TocFilter.call(orig).to_s
|
45
|
+
# assert_includes result, 'aria-hidden="true"'
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# def test_toc_hrefs_have_sane_values
|
49
|
+
# @orig = %(<h1>Dr Dre</h1><h1>Ice Cube</h1><h1>Eazy-E</h1><h1>MC Ren</h1>)
|
50
|
+
# assert_includes toc, '"#dr-dre"'
|
51
|
+
# assert_includes toc, '"#ice-cube"'
|
52
|
+
# assert_includes toc, '"#eazy-e"'
|
53
|
+
# assert_includes toc, '"#mc-ren"'
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# def test_dupe_headers_have_unique_trailing_identifiers
|
57
|
+
# orig = %(<h1>Straight Outta Compton</h1>
|
58
|
+
# <h2>Dopeman</h2>
|
59
|
+
# <h3>Express Yourself</h3>
|
60
|
+
# <h1>Dopeman</h1>)
|
61
|
+
#
|
62
|
+
# result = TocFilter.call(orig).to_s
|
63
|
+
#
|
64
|
+
# assert_includes result, '"dopeman"'
|
65
|
+
# assert_includes result, '"dopeman-1"'
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
# def test_dupe_headers_have_unique_toc_anchors
|
69
|
+
# @orig = %(<h1>Straight Outta Compton</h1>
|
70
|
+
# <h2>Dopeman</h2>
|
71
|
+
# <h3>Express Yourself</h3>
|
72
|
+
# <h1>Dopeman</h1>)
|
73
|
+
#
|
74
|
+
# assert_includes toc, '"#dopeman"'
|
75
|
+
# assert_includes toc, '"#dopeman-1"'
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
# def test_all_header_tags_are_found_when_adding_anchors
|
79
|
+
# orig = %(<h1>"Funky President" by James Brown</h1>
|
80
|
+
# <h2>"It's My Thing" by Marva Whitney</h2>
|
81
|
+
# <h3>"Boogie Back" by Roy Ayers</h3>
|
82
|
+
# <h4>"Feel Good" by Fancy</h4>
|
83
|
+
# <h5>"Funky Drummer" by James Brown</h5>
|
84
|
+
# <h6>"Ruthless Villain" by Eazy-E</h6>
|
85
|
+
# <h7>"Be Thankful for What You Got" by William DeVaughn</h7>)
|
86
|
+
#
|
87
|
+
# doc = TocFilter.call(orig)
|
88
|
+
#
|
89
|
+
# assert_equal 6, doc.search('a').size
|
90
|
+
# end
|
91
|
+
#
|
92
|
+
# def test_toc_outputs_escaped_html
|
93
|
+
# @orig = %(<h1><img src="x" onerror="alert(42)"></h1>)
|
94
|
+
#
|
95
|
+
# refute_includes toc, %(<img src="x" onerror="alert(42)">)
|
96
|
+
# end
|
97
|
+
#
|
98
|
+
# def test_toc_is_complete
|
99
|
+
# @orig = %(<h1>"Funky President" by James Brown</h1>
|
100
|
+
# <h2>"It's My Thing" by Marva Whitney</h2>
|
101
|
+
# <h3>"Boogie Back" by Roy Ayers</h3>
|
102
|
+
# <h4>"Feel Good" by Fancy</h4>
|
103
|
+
# <h5>"Funky Drummer" by James Brown</h5>
|
104
|
+
# <h6>"Ruthless Villain" by Eazy-E</h6>
|
105
|
+
# <h7>"Be Thankful for What You Got" by William DeVaughn</h7>)
|
106
|
+
#
|
107
|
+
# expected = %(<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>)
|
108
|
+
#
|
109
|
+
# assert_equal expected, toc
|
110
|
+
# end
|
111
|
+
#
|
112
|
+
# if RUBY_VERSION > '1.9' # not sure how to make this work on 1.8.7
|
113
|
+
#
|
114
|
+
# def test_anchors_with_utf8_characters
|
115
|
+
# orig = %(<h1>日本語</h1>
|
116
|
+
# <h1>Русский</h1)
|
117
|
+
#
|
118
|
+
# rendered_h1s = TocFilter.call(orig).search('h1').map(&:to_s)
|
119
|
+
#
|
120
|
+
# 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>",
|
121
|
+
# rendered_h1s[0]
|
122
|
+
# 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>",
|
123
|
+
# rendered_h1s[1]
|
124
|
+
# end
|
125
|
+
#
|
126
|
+
# def test_toc_with_utf8_characters
|
127
|
+
# @orig = %(<h1>日本語</h1>
|
128
|
+
# <h1>Русский</h1)
|
129
|
+
#
|
130
|
+
# rendered_toc = Nokogiri::HTML::DocumentFragment.parse(toc).to_s
|
131
|
+
#
|
132
|
+
# expected = %(<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>)
|
133
|
+
#
|
134
|
+
# assert_equal expected, rendered_toc
|
135
|
+
# end
|
136
|
+
# end
|
137
|
+
# end
|