motion-html-pipeline 0.1

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.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +379 -0
  3. data/lib/motion-html-pipeline.rb +14 -0
  4. data/lib/motion-html-pipeline/document_fragment.rb +27 -0
  5. data/lib/motion-html-pipeline/pipeline.rb +153 -0
  6. data/lib/motion-html-pipeline/pipeline/absolute_source_filter.rb +45 -0
  7. data/lib/motion-html-pipeline/pipeline/body_content.rb +42 -0
  8. data/lib/motion-html-pipeline/pipeline/disabled/@mention_filter.rb +140 -0
  9. data/lib/motion-html-pipeline/pipeline/disabled/autolink_filter.rb +27 -0
  10. data/lib/motion-html-pipeline/pipeline/disabled/camo_filter.rb +93 -0
  11. data/lib/motion-html-pipeline/pipeline/disabled/email_reply_filter.rb +66 -0
  12. data/lib/motion-html-pipeline/pipeline/disabled/emoji_filter.rb +125 -0
  13. data/lib/motion-html-pipeline/pipeline/disabled/markdown_filter.rb +37 -0
  14. data/lib/motion-html-pipeline/pipeline/disabled/plain_text_input_filter.rb +13 -0
  15. data/lib/motion-html-pipeline/pipeline/disabled/sanitization_filter.rb +137 -0
  16. data/lib/motion-html-pipeline/pipeline/disabled/syntax_highlight_filter.rb +44 -0
  17. data/lib/motion-html-pipeline/pipeline/disabled/toc_filter.rb +67 -0
  18. data/lib/motion-html-pipeline/pipeline/filter.rb +163 -0
  19. data/lib/motion-html-pipeline/pipeline/https_filter.rb +27 -0
  20. data/lib/motion-html-pipeline/pipeline/image_filter.rb +17 -0
  21. data/lib/motion-html-pipeline/pipeline/image_max_width_filter.rb +37 -0
  22. data/lib/motion-html-pipeline/pipeline/text_filter.rb +14 -0
  23. data/lib/motion-html-pipeline/pipeline/version.rb +5 -0
  24. data/spec/motion-html-pipeline/_helpers/mock_instumentation_service.rb +19 -0
  25. data/spec/motion-html-pipeline/pipeline/absolute_source_filter_spec.rb +47 -0
  26. data/spec/motion-html-pipeline/pipeline/disabled/auto_link_filter_spec.rb +33 -0
  27. data/spec/motion-html-pipeline/pipeline/disabled/camo_filter_spec.rb +75 -0
  28. data/spec/motion-html-pipeline/pipeline/disabled/email_reply_filter_spec.rb +64 -0
  29. data/spec/motion-html-pipeline/pipeline/disabled/emoji_filter_spec.rb +92 -0
  30. data/spec/motion-html-pipeline/pipeline/disabled/markdown_filter_spec.rb +112 -0
  31. data/spec/motion-html-pipeline/pipeline/disabled/plain_text_input_filter_spec.rb +20 -0
  32. data/spec/motion-html-pipeline/pipeline/disabled/sanitization_filter_spec.rb +164 -0
  33. data/spec/motion-html-pipeline/pipeline/disabled/syntax_highlighting_filter_spec.rb +59 -0
  34. data/spec/motion-html-pipeline/pipeline/disabled/toc_filter_spec.rb +137 -0
  35. data/spec/motion-html-pipeline/pipeline/https_filter_spec.rb +52 -0
  36. data/spec/motion-html-pipeline/pipeline/image_filter_spec.rb +37 -0
  37. data/spec/motion-html-pipeline/pipeline/image_max_width_filter_spec.rb +57 -0
  38. data/spec/motion-html-pipeline/pipeline_spec.rb +80 -0
  39. data/spec/spec_helper.rb +48 -0
  40. 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 = "&lt;iframe src='http://www.google.com'>&lt;/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: &lt;http://example.org&gt;</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>&lt;img src="x" onerror="alert(42)"&gt;</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">&quot;Funky President&quot; by James Brown</a></li>\n<li><a href="#its-my-thing-by-marva-whitney">&quot;It&#39;s My Thing&quot; by Marva Whitney</a></li>\n<li><a href="#boogie-back-by-roy-ayers">&quot;Boogie Back&quot; by Roy Ayers</a></li>\n<li><a href="#feel-good-by-fancy">&quot;Feel Good&quot; by Fancy</a></li>\n<li><a href="#funky-drummer-by-james-brown">&quot;Funky Drummer&quot; by James Brown</a></li>\n<li><a href="#ruthless-villain-by-eazy-e">&quot;Ruthless Villain&quot; 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