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.
- 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
|