html-pipeline-linuxfr 0.14.23 → 0.14.24
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 +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
|