html-pipeline-linuxfr 0.14.23 → 0.14.24
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -18
- data/html-pipeline-linuxfr.gemspec +7 -5
- data/lib/html/pipeline/sanitization_filter.rb +1 -2
- data/lib/html/pipeline/version.rb +1 -1
- data/test/html/pipeline/markdown_filter_test.rb +10 -28
- data/test/html/pipeline/sanitization_filter_test.rb +0 -11
- data/test/html/pipeline/toc_filter_test.rb +20 -21
- metadata +27 -25
- data/.travis.yml +0 -13
- data/bin/html-pipeline +0 -80
- data/test/html/pipeline/absolute_source_filter_test.rb +0 -56
- data/test/html/pipeline/camo_filter_test.rb +0 -47
- data/test/html/pipeline/image_max_width_filter_test.rb +0 -50
- data/test/html/pipeline/mention_filter_test.rb +0 -156
- data/test/html/pipeline/plain_text_input_filter_test.rb +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bb682966ec238f8fab36cad469d5ce4150e4d7ca
|
4
|
+
data.tar.gz: 20244031571553790cc97cd5d633c702419188b2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e3e46ea4cb7bcf90f9d6af31f7442ab6417f56bea353580f119de09f21931bf8b14506da95ccb08435fdb2c95f107c811f494bd7fbf3dc94c75a876d15993080
|
7
|
+
data.tar.gz: 91cbc215b6699a01893180f018d0604d0f5fd3958fa6fa9d45dc0e094ed054a181b74760b572cda2639af2119c78ecab91b87fa1f5186b48c0708bc701a4cb2f
|
data/.gitignore
CHANGED
@@ -15,11 +15,13 @@ Gem::Specification.new do |gem|
|
|
15
15
|
gem.test_files = gem.files.grep(%r{^test})
|
16
16
|
gem.require_paths = ["lib"]
|
17
17
|
|
18
|
-
gem.add_dependency "nokogiri", "~> 1.
|
19
|
-
gem.add_dependency "redcarpet", "~> 3.
|
18
|
+
gem.add_dependency "nokogiri", "~> 1.6"
|
19
|
+
gem.add_dependency "redcarpet", "~> 3.2"
|
20
20
|
gem.add_dependency "pygments.rb", "~> 0.5"
|
21
|
-
gem.add_dependency "sanitize", "~>
|
22
|
-
gem.add_dependency "escape_utils", "~> 1.
|
23
|
-
gem.add_dependency "activesupport", "~> 4.
|
21
|
+
gem.add_dependency "sanitize", "~> 3.1"
|
22
|
+
gem.add_dependency "escape_utils", "~> 1.1"
|
23
|
+
gem.add_dependency "activesupport", "~> 4.2"
|
24
24
|
gem.add_dependency "patron", "~> 0.4"
|
25
|
+
|
26
|
+
gem.add_development_dependency "test-unit"
|
25
27
|
end
|
@@ -23,7 +23,6 @@ module HTML
|
|
23
23
|
# The main sanitization whitelist. Only these elements and attributes are
|
24
24
|
# allowed through by default.
|
25
25
|
WHITELIST = {
|
26
|
-
:output => :xhtml,
|
27
26
|
:elements => %w(a abbr b blockquote br cite code dd del dfn div dl dt em
|
28
27
|
h1 h2 h3 h4 h5 h6 hr i img ins kbd li mark meter ol p pre
|
29
28
|
q s samp small source span strong sub sup table tbody td
|
@@ -70,7 +69,7 @@ module HTML
|
|
70
69
|
|
71
70
|
# Sanitize markup using the Sanitize library.
|
72
71
|
def call
|
73
|
-
encode_mb4 Sanitize.
|
72
|
+
encode_mb4 Sanitize.node!(doc, whitelist)
|
74
73
|
end
|
75
74
|
|
76
75
|
# The whitelist to use when sanitizing. This can be passed in the context
|
@@ -30,24 +30,11 @@ class HTML::Pipeline::MarkdownFilterTest < Test::Unit::TestCase
|
|
30
30
|
assert_equal 2, doc.search('br').size
|
31
31
|
end
|
32
32
|
|
33
|
-
def test_disabling_gfm
|
34
|
-
doc = MarkdownFilter.to_document(@haiku, :gfm => false)
|
35
|
-
assert doc.kind_of?(HTML::Pipeline::DocumentFragment)
|
36
|
-
assert_equal 0, doc.search('br').size
|
37
|
-
end
|
38
|
-
|
39
33
|
def test_fenced_code_blocks
|
40
34
|
doc = MarkdownFilter.to_document(@code)
|
41
35
|
assert doc.kind_of?(HTML::Pipeline::DocumentFragment)
|
42
36
|
assert_equal 1, doc.search('pre').size
|
43
37
|
end
|
44
|
-
|
45
|
-
def test_fenced_code_blocks_with_language
|
46
|
-
doc = MarkdownFilter.to_document(@code.sub("```", "``` ruby"))
|
47
|
-
assert doc.kind_of?(HTML::Pipeline::DocumentFragment)
|
48
|
-
assert_equal 1, doc.search('pre').size
|
49
|
-
assert_equal 'ruby', doc.search('pre').first['lang']
|
50
|
-
end
|
51
38
|
end
|
52
39
|
|
53
40
|
class GFMTest < Test::Unit::TestCase
|
@@ -56,46 +43,41 @@ class GFMTest < Test::Unit::TestCase
|
|
56
43
|
end
|
57
44
|
|
58
45
|
def test_not_touch_single_underscores_inside_words
|
59
|
-
assert_equal "<p>foo_bar</p
|
46
|
+
assert_equal "<p>foo_bar</p>\n",
|
60
47
|
gfm("foo_bar")
|
61
48
|
end
|
62
49
|
|
63
50
|
def test_not_touch_underscores_in_code_blocks
|
64
|
-
assert_equal "<pre><code>foo_bar_baz\n</code></pre
|
51
|
+
assert_equal "<pre><code>foo_bar_baz\n</code></pre>\n",
|
65
52
|
gfm(" foo_bar_baz")
|
66
53
|
end
|
67
54
|
|
68
|
-
def test_not_touch_underscores_in_pre_blocks
|
69
|
-
assert_equal "<pre>\nfoo_bar_baz\n</pre>",
|
70
|
-
gfm("<pre>\nfoo_bar_baz\n</pre>")
|
71
|
-
end
|
72
|
-
|
73
55
|
def test_not_touch_two_or_more_underscores_inside_words
|
74
|
-
assert_equal "<p>foo_bar_baz</p
|
56
|
+
assert_equal "<p>foo_bar_baz</p>\n",
|
75
57
|
gfm("foo_bar_baz")
|
76
58
|
end
|
77
59
|
|
78
60
|
def test_turn_newlines_into_br_tags_in_simple_cases
|
79
|
-
assert_equal "<p>foo<br
|
61
|
+
assert_equal "<p>foo<br/>\nbar</p>\n",
|
80
62
|
gfm("foo\nbar")
|
81
63
|
end
|
82
64
|
|
83
65
|
def test_convert_newlines_in_all_groups
|
84
|
-
assert_equal "<p>apple<br
|
85
|
-
"<p>ruby<br
|
66
|
+
assert_equal "<p>apple<br/>\npear<br/>\norange</p>\n\n" +
|
67
|
+
"<p>ruby<br/>\npython<br/>\nerlang</p>\n",
|
86
68
|
gfm("apple\npear\norange\n\nruby\npython\nerlang")
|
87
69
|
end
|
88
70
|
|
89
71
|
def test_convert_newlines_in_even_long_groups
|
90
|
-
assert_equal "<p>apple<br
|
91
|
-
"<p>ruby<br
|
72
|
+
assert_equal "<p>apple<br/>\npear<br/>\norange<br/>\nbanana</p>\n\n" +
|
73
|
+
"<p>ruby<br/>\npython<br/>\nerlang</p>\n",
|
92
74
|
gfm("apple\npear\norange\nbanana\n\nruby\npython\nerlang")
|
93
75
|
end
|
94
76
|
|
95
77
|
def test_not_convert_newlines_in_lists
|
96
|
-
assert_equal "<
|
78
|
+
assert_equal "<h2>foo</h2>\n<h2>bar</h2>\n",
|
97
79
|
gfm("# foo\n# bar")
|
98
|
-
assert_equal "<ul>\n<li>foo</li>\n<li>bar</li>\n</ul
|
80
|
+
assert_equal "<ul>\n<li>foo</li>\n<li>bar</li>\n</ul>\n",
|
99
81
|
gfm("* foo\n* bar")
|
100
82
|
end
|
101
83
|
end
|
@@ -29,22 +29,11 @@ class HTML::Pipeline::SanitizationFilterTest < Test::Unit::TestCase
|
|
29
29
|
assert_no_match /onclick/, html
|
30
30
|
end
|
31
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
32
|
def test_does_not_sanitize_li_elements_contained_in_ul_or_ol
|
39
33
|
stuff = "a\n<ul><li>b</li></ul>\nc"
|
40
34
|
assert_equal stuff, SanitizationFilter.call(stuff).to_s
|
41
35
|
end
|
42
36
|
|
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
37
|
def test_script_contents_are_removed
|
49
38
|
orig = '<script>JavaScript!</script>'
|
50
39
|
assert_equal "", SanitizationFilter.call(orig).to_s
|
@@ -2,15 +2,16 @@ require "test_helper"
|
|
2
2
|
|
3
3
|
class HTML::Pipeline::TableOfContentsFilterTest < Test::Unit::TestCase
|
4
4
|
TocFilter = HTML::Pipeline::TableOfContentsFilter
|
5
|
+
CONTEXT = { toc_minimal_length: 1, toc_header: 'Table of contents' }
|
5
6
|
|
6
7
|
def test_anchors_are_added_properly
|
7
|
-
orig = %(<
|
8
|
-
assert_includes '<
|
8
|
+
orig = %(<h2>Ice cube</h2><p>Will swarm on any motherfucker in a blue uniform</p>)
|
9
|
+
assert_includes '<h2 id=', TocFilter.call(orig, CONTEXT).to_s
|
9
10
|
end
|
10
11
|
|
11
12
|
def test_anchors_have_sane_names
|
12
|
-
orig = %(<
|
13
|
-
result = TocFilter.call(orig).to_s
|
13
|
+
orig = %(<h2>Dr Dre</h2><h2>Ice Cube</h2><h2>Eazy-E</h2><h2>MC Ren</h2>)
|
14
|
+
result = TocFilter.call(orig, CONTEXT).to_s
|
14
15
|
|
15
16
|
assert_includes '"dr-dre"', result
|
16
17
|
assert_includes '"ice-cube"', result
|
@@ -19,29 +20,27 @@ class HTML::Pipeline::TableOfContentsFilterTest < Test::Unit::TestCase
|
|
19
20
|
end
|
20
21
|
|
21
22
|
def test_dupe_headers_have_unique_trailing_identifiers
|
22
|
-
orig = %(<
|
23
|
-
<
|
24
|
-
<
|
25
|
-
<
|
23
|
+
orig = %(<h2>Straight Outta Compton</h2>
|
24
|
+
<h3>Dopeman</h3>
|
25
|
+
<h4>Express Yourself</h4>
|
26
|
+
<h2>Dopeman</h2>)
|
26
27
|
|
27
|
-
result = TocFilter.call(orig).to_s
|
28
|
+
result = TocFilter.call(orig, CONTEXT).to_s
|
28
29
|
|
29
30
|
assert_includes '"dopeman"', result
|
30
31
|
assert_includes '"dopeman-1"', result
|
31
32
|
end
|
32
33
|
|
33
34
|
def test_all_header_tags_are_found_when_adding_anchors
|
34
|
-
orig = %(<
|
35
|
-
<
|
36
|
-
<
|
37
|
-
<
|
38
|
-
<
|
39
|
-
<
|
40
|
-
<
|
41
|
-
|
42
|
-
doc = TocFilter.call(orig)
|
43
|
-
assert_equal
|
35
|
+
orig = %(<h2>"Funky President" by James Brown</h2>
|
36
|
+
<h3>"It's My Thing" by Marva Whitney</h3>
|
37
|
+
<h4>"Boogie Back" by Roy Ayers</h4>
|
38
|
+
<h5>"Feel Good" by Fancy</h5>
|
39
|
+
<h6>"Funky Drummer" by James Brown</h6>
|
40
|
+
<h7>"Ruthless Villain" by Eazy-E</h7>
|
41
|
+
<h8>"Be Thankful for What You Got" by William DeVaughn</h8>)
|
42
|
+
|
43
|
+
doc = TocFilter.call(orig, CONTEXT)
|
44
|
+
assert_equal 5, doc.search('a').size
|
44
45
|
end
|
45
46
|
end
|
46
|
-
|
47
|
-
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: html-pipeline-linuxfr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.14.
|
4
|
+
version: 0.14.24
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Tomayko
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2015-04-08 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: nokogiri
|
@@ -18,28 +18,28 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - "~>"
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: '1.
|
21
|
+
version: '1.6'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
requirements:
|
26
26
|
- - "~>"
|
27
27
|
- !ruby/object:Gem::Version
|
28
|
-
version: '1.
|
28
|
+
version: '1.6'
|
29
29
|
- !ruby/object:Gem::Dependency
|
30
30
|
name: redcarpet
|
31
31
|
requirement: !ruby/object:Gem::Requirement
|
32
32
|
requirements:
|
33
33
|
- - "~>"
|
34
34
|
- !ruby/object:Gem::Version
|
35
|
-
version: '3.
|
35
|
+
version: '3.2'
|
36
36
|
type: :runtime
|
37
37
|
prerelease: false
|
38
38
|
version_requirements: !ruby/object:Gem::Requirement
|
39
39
|
requirements:
|
40
40
|
- - "~>"
|
41
41
|
- !ruby/object:Gem::Version
|
42
|
-
version: '3.
|
42
|
+
version: '3.2'
|
43
43
|
- !ruby/object:Gem::Dependency
|
44
44
|
name: pygments.rb
|
45
45
|
requirement: !ruby/object:Gem::Requirement
|
@@ -60,42 +60,42 @@ dependencies:
|
|
60
60
|
requirements:
|
61
61
|
- - "~>"
|
62
62
|
- !ruby/object:Gem::Version
|
63
|
-
version: '
|
63
|
+
version: '3.1'
|
64
64
|
type: :runtime
|
65
65
|
prerelease: false
|
66
66
|
version_requirements: !ruby/object:Gem::Requirement
|
67
67
|
requirements:
|
68
68
|
- - "~>"
|
69
69
|
- !ruby/object:Gem::Version
|
70
|
-
version: '
|
70
|
+
version: '3.1'
|
71
71
|
- !ruby/object:Gem::Dependency
|
72
72
|
name: escape_utils
|
73
73
|
requirement: !ruby/object:Gem::Requirement
|
74
74
|
requirements:
|
75
75
|
- - "~>"
|
76
76
|
- !ruby/object:Gem::Version
|
77
|
-
version: '1.
|
77
|
+
version: '1.1'
|
78
78
|
type: :runtime
|
79
79
|
prerelease: false
|
80
80
|
version_requirements: !ruby/object:Gem::Requirement
|
81
81
|
requirements:
|
82
82
|
- - "~>"
|
83
83
|
- !ruby/object:Gem::Version
|
84
|
-
version: '1.
|
84
|
+
version: '1.1'
|
85
85
|
- !ruby/object:Gem::Dependency
|
86
86
|
name: activesupport
|
87
87
|
requirement: !ruby/object:Gem::Requirement
|
88
88
|
requirements:
|
89
89
|
- - "~>"
|
90
90
|
- !ruby/object:Gem::Version
|
91
|
-
version: '4.
|
91
|
+
version: '4.2'
|
92
92
|
type: :runtime
|
93
93
|
prerelease: false
|
94
94
|
version_requirements: !ruby/object:Gem::Requirement
|
95
95
|
requirements:
|
96
96
|
- - "~>"
|
97
97
|
- !ruby/object:Gem::Version
|
98
|
-
version: '4.
|
98
|
+
version: '4.2'
|
99
99
|
- !ruby/object:Gem::Dependency
|
100
100
|
name: patron
|
101
101
|
requirement: !ruby/object:Gem::Requirement
|
@@ -110,6 +110,20 @@ dependencies:
|
|
110
110
|
- - "~>"
|
111
111
|
- !ruby/object:Gem::Version
|
112
112
|
version: '0.4'
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: test-unit
|
115
|
+
requirement: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
120
|
+
type: :development
|
121
|
+
prerelease: false
|
122
|
+
version_requirements: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - ">="
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
113
127
|
description: LinuxFr.org HTML processing filters and utilities, adapted from those
|
114
128
|
of GitHub
|
115
129
|
email:
|
@@ -121,13 +135,11 @@ extensions: []
|
|
121
135
|
extra_rdoc_files: []
|
122
136
|
files:
|
123
137
|
- ".gitignore"
|
124
|
-
- ".travis.yml"
|
125
138
|
- CHANGELOG.md
|
126
139
|
- Gemfile
|
127
140
|
- LICENSE
|
128
141
|
- README.md
|
129
142
|
- Rakefile
|
130
|
-
- bin/html-pipeline
|
131
143
|
- html-pipeline-linuxfr.gemspec
|
132
144
|
- lib/html/pipeline.rb
|
133
145
|
- lib/html/pipeline/custom_links_filter.rb
|
@@ -142,12 +154,7 @@ files:
|
|
142
154
|
- lib/html/pipeline/toc_filter.rb
|
143
155
|
- lib/html/pipeline/version.rb
|
144
156
|
- test/helpers/mocked_instrumentation_service.rb
|
145
|
-
- test/html/pipeline/absolute_source_filter_test.rb
|
146
|
-
- test/html/pipeline/camo_filter_test.rb
|
147
|
-
- test/html/pipeline/image_max_width_filter_test.rb
|
148
157
|
- test/html/pipeline/markdown_filter_test.rb
|
149
|
-
- test/html/pipeline/mention_filter_test.rb
|
150
|
-
- test/html/pipeline/plain_text_input_filter_test.rb
|
151
158
|
- test/html/pipeline/sanitization_filter_test.rb
|
152
159
|
- test/html/pipeline/toc_filter_test.rb
|
153
160
|
- test/html/pipeline_test.rb
|
@@ -172,18 +179,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
172
179
|
version: '0'
|
173
180
|
requirements: []
|
174
181
|
rubyforge_project:
|
175
|
-
rubygems_version: 2.
|
182
|
+
rubygems_version: 2.4.5
|
176
183
|
signing_key:
|
177
184
|
specification_version: 4
|
178
185
|
summary: Helpers for processing content through a chain of filters
|
179
186
|
test_files:
|
180
187
|
- test/helpers/mocked_instrumentation_service.rb
|
181
|
-
- test/html/pipeline/absolute_source_filter_test.rb
|
182
|
-
- test/html/pipeline/camo_filter_test.rb
|
183
|
-
- test/html/pipeline/image_max_width_filter_test.rb
|
184
188
|
- test/html/pipeline/markdown_filter_test.rb
|
185
|
-
- test/html/pipeline/mention_filter_test.rb
|
186
|
-
- test/html/pipeline/plain_text_input_filter_test.rb
|
187
189
|
- test/html/pipeline/sanitization_filter_test.rb
|
188
190
|
- test/html/pipeline/toc_filter_test.rb
|
189
191
|
- test/html/pipeline_test.rb
|
data/.travis.yml
DELETED
data/bin/html-pipeline
DELETED
@@ -1,80 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require 'html/pipeline'
|
3
|
-
|
4
|
-
require 'optparse'
|
5
|
-
|
6
|
-
# Accept "help", too
|
7
|
-
ARGV.map!{|a| a == "help" ? "--help" : a }
|
8
|
-
|
9
|
-
OptionParser.new do |opts|
|
10
|
-
opts.banner = <<-HELP.gsub(/^ /, '')
|
11
|
-
Usage: html-pipeline [-h] [-f]
|
12
|
-
html-pipeline [FILTER [FILTER [...]]] < file.md
|
13
|
-
cat file.md | html-pipeline [FILTER [FILTER [...]]]
|
14
|
-
HELP
|
15
|
-
|
16
|
-
opts.separator "Options:"
|
17
|
-
|
18
|
-
opts.on("-f", "--filters", "List the available filters") do
|
19
|
-
filters = HTML::Pipeline.constants.grep(/\w+Filter$/).
|
20
|
-
map{|f| f.to_s.gsub(/Filter$/,'') }
|
21
|
-
|
22
|
-
# Text filter doesn't work, no call method
|
23
|
-
filters -= ["Text"]
|
24
|
-
|
25
|
-
abort <<-HELP.gsub(/^ /, '')
|
26
|
-
Available filters:
|
27
|
-
#{filters.join("\n ")}
|
28
|
-
HELP
|
29
|
-
end
|
30
|
-
end.parse!
|
31
|
-
|
32
|
-
# Default to a GitHub-ish pipeline
|
33
|
-
if ARGV.empty?
|
34
|
-
|
35
|
-
filters = [
|
36
|
-
HTML::Pipeline::MarkdownFilter,
|
37
|
-
HTML::Pipeline::SanitizationFilter,
|
38
|
-
HTML::Pipeline::ImageMaxWidthFilter,
|
39
|
-
HTML::Pipeline::EmojiFilter,
|
40
|
-
HTML::Pipeline::AutolinkFilter,
|
41
|
-
HTML::Pipeline::TableOfContentsFilter,
|
42
|
-
]
|
43
|
-
|
44
|
-
# Add syntax highlighting if linguist is present
|
45
|
-
begin
|
46
|
-
require 'linguist'
|
47
|
-
filters << HTML::Pipeline::SyntaxHighlightFilter
|
48
|
-
rescue LoadError
|
49
|
-
end
|
50
|
-
|
51
|
-
else
|
52
|
-
|
53
|
-
def filter_named(name)
|
54
|
-
case name
|
55
|
-
when "Text"
|
56
|
-
raise NameError # Text filter doesn't work, no call method
|
57
|
-
when "Textile"
|
58
|
-
require "RedCloth" # Textile filter doesn't require RedCloth
|
59
|
-
end
|
60
|
-
|
61
|
-
HTML::Pipeline.const_get("#{name}Filter")
|
62
|
-
rescue NameError => e
|
63
|
-
abort "Unknown filter '#{name}'. List filters with the -f option."
|
64
|
-
end
|
65
|
-
|
66
|
-
filters = []
|
67
|
-
until ARGV.empty?
|
68
|
-
name = ARGV.shift
|
69
|
-
filters << filter_named(name)
|
70
|
-
end
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
|
-
context = {
|
75
|
-
:asset_root => "/assets",
|
76
|
-
:base_url => "/",
|
77
|
-
:gfm => true
|
78
|
-
}
|
79
|
-
|
80
|
-
puts HTML::Pipeline.new(filters, context).call(ARGF.read)[:output]
|
@@ -1,56 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class HTML::Pipeline::AbsoluteSourceFilterTest < Test::Unit::TestCase
|
4
|
-
AbsoluteSourceFilter = HTML::Pipeline::AbsoluteSourceFilter
|
5
|
-
|
6
|
-
def setup
|
7
|
-
@image_base_url = 'http://assets.example.com'
|
8
|
-
@image_subpage_url = 'http://blog.example.com/a/post'
|
9
|
-
@options = {
|
10
|
-
:image_base_url => @image_base_url,
|
11
|
-
:image_subpage_url => @image_subpage_url
|
12
|
-
}
|
13
|
-
end
|
14
|
-
|
15
|
-
def test_rewrites_root_relative_urls
|
16
|
-
orig = %(<p><img src="/img.png"></p>)
|
17
|
-
puts AbsoluteSourceFilter.call(orig, @options).to_s
|
18
|
-
assert_equal "<p><img src=\"#{@image_base_url}/img.png\"></p>",
|
19
|
-
AbsoluteSourceFilter.call(orig, @options).to_s
|
20
|
-
end
|
21
|
-
|
22
|
-
def test_rewrites_root_relative_urls
|
23
|
-
orig = %(<p><img src="post/img.png"></p>)
|
24
|
-
assert_equal "<p><img src=\"#{@image_subpage_url}/img.png\"></p>",
|
25
|
-
AbsoluteSourceFilter.call(orig, @options).to_s
|
26
|
-
end
|
27
|
-
|
28
|
-
def test_does_not_rewrite_absolute_urls
|
29
|
-
orig = %(<p><img src="http://other.example.com/img.png"></p>)
|
30
|
-
result = AbsoluteSourceFilter.call(orig, @options).to_s
|
31
|
-
assert_no_match /@image_base_url/, result
|
32
|
-
assert_no_match /@image_subpage_url/, result
|
33
|
-
end
|
34
|
-
|
35
|
-
def test_fails_when_context_is_missing
|
36
|
-
assert_raise RuntimeError do
|
37
|
-
AbsoluteSourceFilter.call("<img src=\"img.png\">", {})
|
38
|
-
end
|
39
|
-
assert_raise RuntimeError do
|
40
|
-
AbsoluteSourceFilter.call("<img src=\"/img.png\">", {})
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def test_tells_you_where_context_is_required
|
45
|
-
exception = assert_raise(RuntimeError) {
|
46
|
-
AbsoluteSourceFilter.call("<img src=\"img.png\">", {})
|
47
|
-
}
|
48
|
-
assert_match 'HTML::Pipeline::AbsoluteSourceFilter', exception.message
|
49
|
-
|
50
|
-
exception = assert_raise(RuntimeError) {
|
51
|
-
AbsoluteSourceFilter.call("<img src=\"/img.png\">", {})
|
52
|
-
}
|
53
|
-
assert_match 'HTML::Pipeline::AbsoluteSourceFilter', exception.message
|
54
|
-
end
|
55
|
-
|
56
|
-
end
|
@@ -1,47 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class HTML::Pipeline::CamoFilterTest < Test::Unit::TestCase
|
4
|
-
CamoFilter = HTML::Pipeline::CamoFilter
|
5
|
-
|
6
|
-
def setup
|
7
|
-
@asset_proxy_url = 'https//assets.example.org'
|
8
|
-
@asset_proxy_secret_key = 'ssssh-secret'
|
9
|
-
@options = {
|
10
|
-
:asset_proxy => @asset_proxy_url,
|
11
|
-
:asset_proxy_secret_key => @asset_proxy_secret_key
|
12
|
-
}
|
13
|
-
end
|
14
|
-
|
15
|
-
def test_camouflaging_http_image_urls
|
16
|
-
orig = %(<p><img src="http://twitter.com/img.png"></p>)
|
17
|
-
assert_includes 'img src="' + @asset_proxy_url,
|
18
|
-
CamoFilter.call(orig, @options).to_s
|
19
|
-
end
|
20
|
-
|
21
|
-
def test_rewrites_dotcom_image_urls
|
22
|
-
orig = %(<p><img src="http://github.com/img.png"></p>)
|
23
|
-
assert_equal "<p><img src=\"https://github.com/img.png\"></p>",
|
24
|
-
CamoFilter.call(orig, @options).to_s
|
25
|
-
end
|
26
|
-
|
27
|
-
def test_not_camouflaging_https_image_urls
|
28
|
-
orig = %(<p><img src="https://foo.com/img.png"></p>)
|
29
|
-
assert_doesnt_include 'img src="' + @asset_proxy_url,
|
30
|
-
CamoFilter.call(orig, @options).to_s
|
31
|
-
end
|
32
|
-
|
33
|
-
def test_handling_images_with_no_src_attribute
|
34
|
-
orig = %(<p><img></p>)
|
35
|
-
assert_nothing_raised do
|
36
|
-
CamoFilter.call(orig, @options).to_s
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def test_required_context_validation
|
41
|
-
exception = assert_raise(ArgumentError) {
|
42
|
-
CamoFilter.call("", {})
|
43
|
-
}
|
44
|
-
assert_match /:asset_proxy[^_]/, exception.message
|
45
|
-
assert_match /:asset_proxy_secret_key/, exception.message
|
46
|
-
end
|
47
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class HTML::Pipeline::ImageMaxWidthFilterTest < Test::Unit::TestCase
|
4
|
-
def filter(html)
|
5
|
-
HTML::Pipeline::ImageMaxWidthFilter.call(html)
|
6
|
-
end
|
7
|
-
|
8
|
-
def test_rewrites_image_style_tags
|
9
|
-
body = "<p>Screenshot: <img src='screenshot.png'></p>"
|
10
|
-
doc = Nokogiri::HTML::DocumentFragment.parse(body)
|
11
|
-
|
12
|
-
res = filter(doc)
|
13
|
-
assert_equal_html %q(<p>Screenshot: <a target="_blank" href="screenshot.png"><img src="screenshot.png" style="max-width:100%;"></a></p>),
|
14
|
-
res.to_html
|
15
|
-
end
|
16
|
-
|
17
|
-
def test_leaves_existing_image_style_tags_alone
|
18
|
-
body = "<p><img src='screenshot.png' style='width:100px;'></p>"
|
19
|
-
doc = Nokogiri::HTML::DocumentFragment.parse(body)
|
20
|
-
|
21
|
-
res = filter(doc)
|
22
|
-
assert_equal_html '<p><img src="screenshot.png" style="width:100px;"></p>',
|
23
|
-
res.to_html
|
24
|
-
end
|
25
|
-
|
26
|
-
def test_links_to_image
|
27
|
-
body = "<p>Screenshot: <img src='screenshot.png'></p>"
|
28
|
-
doc = Nokogiri::HTML::DocumentFragment.parse(body)
|
29
|
-
|
30
|
-
res = filter(doc)
|
31
|
-
assert_equal_html '<p>Screenshot: <a target="_blank" href="screenshot.png"><img src="screenshot.png" style="max-width:100%;"></a></p>',
|
32
|
-
res.to_html
|
33
|
-
end
|
34
|
-
|
35
|
-
def test_doesnt_link_to_image_when_already_linked
|
36
|
-
body = "<p>Screenshot: <a href='blah.png'><img src='screenshot.png'></a></p>"
|
37
|
-
doc = Nokogiri::HTML::DocumentFragment.parse(body)
|
38
|
-
|
39
|
-
res = filter(doc)
|
40
|
-
assert_equal_html %q(<p>Screenshot: <a href="blah.png"><img src="screenshot.png" style="max-width:100%;"></a></p>),
|
41
|
-
res.to_html
|
42
|
-
end
|
43
|
-
|
44
|
-
def test_doesnt_screw_up_inlined_images
|
45
|
-
body = "<p>Screenshot <img src='screenshot.png'>, yes, this is a <b>screenshot</b> indeed.</p>"
|
46
|
-
doc = Nokogiri::HTML::DocumentFragment.parse(body)
|
47
|
-
|
48
|
-
assert_equal_html %q(<p>Screenshot <a target="_blank" href="screenshot.png"><img src="screenshot.png" style="max-width:100%;"></a>, yes, this is a <b>screenshot</b> indeed.</p>), filter(doc).to_html
|
49
|
-
end
|
50
|
-
end
|
@@ -1,156 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class HTML::Pipeline::MentionFilterTest < Test::Unit::TestCase
|
4
|
-
def filter(html, base_url='/', info_url=nil)
|
5
|
-
HTML::Pipeline::MentionFilter.call(html, :base_url => base_url, :info_url => info_url)
|
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_links
|
40
|
-
body = "<p><a>@kneath</a> okay</p>"
|
41
|
-
assert_equal body, filter(body).to_html
|
42
|
-
end
|
43
|
-
|
44
|
-
def test_entity_encoding_and_whatnot
|
45
|
-
body = "<p>@kneath what's up</p>"
|
46
|
-
link = "<a href=\"/kneath\" class=\"user-mention\">@kneath</a>"
|
47
|
-
assert_equal "<p>#{link} what's up</p>", filter(body, '/').to_html
|
48
|
-
end
|
49
|
-
|
50
|
-
def test_html_injection
|
51
|
-
body = "<p>@kneath <script>alert(0)</script></p>"
|
52
|
-
link = "<a href=\"/kneath\" class=\"user-mention\">@kneath</a>"
|
53
|
-
assert_equal "<p>#{link} <script>alert(0)</script></p>",
|
54
|
-
filter(body, '/').to_html
|
55
|
-
end
|
56
|
-
|
57
|
-
def test_links_to_nothing_when_no_info_url_given
|
58
|
-
body = "<p>How do I @mention someone?</p>"
|
59
|
-
assert_equal "<p>How do I @mention someone?</p>",
|
60
|
-
filter(body, '/').to_html
|
61
|
-
end
|
62
|
-
|
63
|
-
def test_links_to_more_info_when_info_url_given
|
64
|
-
body = "<p>How do I @mention someone?</p>"
|
65
|
-
link = "<a href=\"https://github.com/blog/821\" class=\"user-mention\">@mention</a>"
|
66
|
-
assert_equal "<p>How do I #{link} someone?</p>",
|
67
|
-
filter(body, '/', 'https://github.com/blog/821').to_html
|
68
|
-
end
|
69
|
-
|
70
|
-
MarkdownPipeline =
|
71
|
-
HTML::Pipeline.new [
|
72
|
-
HTML::Pipeline::MarkdownFilter,
|
73
|
-
HTML::Pipeline::MentionFilter
|
74
|
-
]
|
75
|
-
|
76
|
-
def mentioned_usernames
|
77
|
-
result = {}
|
78
|
-
MarkdownPipeline.call(@body, {}, result)
|
79
|
-
result[:mentioned_usernames]
|
80
|
-
end
|
81
|
-
|
82
|
-
def test_matches_usernames_in_body
|
83
|
-
@body = "@test how are you?"
|
84
|
-
assert_equal %w[test], mentioned_usernames
|
85
|
-
end
|
86
|
-
|
87
|
-
def test_matches_usernames_with_dashes
|
88
|
-
@body = "hi @some-user"
|
89
|
-
assert_equal %w[some-user], mentioned_usernames
|
90
|
-
end
|
91
|
-
|
92
|
-
def test_matches_usernames_followed_by_a_single_dot
|
93
|
-
@body = "okay @some-user."
|
94
|
-
assert_equal %w[some-user], mentioned_usernames
|
95
|
-
end
|
96
|
-
|
97
|
-
def test_matches_usernames_followed_by_multiple_dots
|
98
|
-
@body = "okay @some-user..."
|
99
|
-
assert_equal %w[some-user], mentioned_usernames
|
100
|
-
end
|
101
|
-
|
102
|
-
def test_does_not_match_email_addresses
|
103
|
-
@body = "aman@tmm1.net"
|
104
|
-
assert_equal [], mentioned_usernames
|
105
|
-
end
|
106
|
-
|
107
|
-
def test_does_not_match_domain_name_looking_things
|
108
|
-
@body = "we need a @github.com email"
|
109
|
-
assert_equal [], mentioned_usernames
|
110
|
-
end
|
111
|
-
|
112
|
-
def test_does_not_match_organization_team_mentions
|
113
|
-
@body = "we need to @github/enterprise know"
|
114
|
-
assert_equal [], mentioned_usernames
|
115
|
-
end
|
116
|
-
|
117
|
-
def test_matches_colon_suffixed_names
|
118
|
-
@body = "@tmm1: what do you think?"
|
119
|
-
assert_equal %w[tmm1], mentioned_usernames
|
120
|
-
end
|
121
|
-
|
122
|
-
def test_matches_list_of_names
|
123
|
-
@body = "@defunkt @atmos @kneath"
|
124
|
-
assert_equal %w[defunkt atmos kneath], mentioned_usernames
|
125
|
-
end
|
126
|
-
|
127
|
-
def test_matches_list_of_names_with_commas
|
128
|
-
@body = "/cc @defunkt, @atmos, @kneath"
|
129
|
-
assert_equal %w[defunkt atmos kneath], mentioned_usernames
|
130
|
-
end
|
131
|
-
|
132
|
-
def test_matches_inside_brackets
|
133
|
-
@body = "(@mislav) and [@rtomayko]"
|
134
|
-
assert_equal %w[mislav rtomayko], mentioned_usernames
|
135
|
-
end
|
136
|
-
|
137
|
-
def test_doesnt_ignore_invalid_users
|
138
|
-
@body = "@defunkt @mojombo and @somedude"
|
139
|
-
assert_equal ['defunkt', 'mojombo', 'somedude'], mentioned_usernames
|
140
|
-
end
|
141
|
-
|
142
|
-
def test_returns_distinct_set
|
143
|
-
@body = "/cc @defunkt, @atmos, @kneath, @defunkt, @defunkt"
|
144
|
-
assert_equal %w[defunkt atmos kneath], mentioned_usernames
|
145
|
-
end
|
146
|
-
|
147
|
-
def test_does_not_match_inline_code_block_with_multiple_code_blocks
|
148
|
-
@body = "something\n\n`/cc @defunkt @atmos @kneath` `/cc @atmos/atmos`"
|
149
|
-
assert_equal %w[], mentioned_usernames
|
150
|
-
end
|
151
|
-
|
152
|
-
def test_mention_at_end_of_parenthetical_sentence
|
153
|
-
@body = "(We're talking 'bout @ymendel.)"
|
154
|
-
assert_equal %w[ymendel], mentioned_usernames
|
155
|
-
end
|
156
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class HTML::Pipeline::PlainTextInputFilterTest < Test::Unit::TestCase
|
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_raise(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
|