html-pipeline 2.7.1 → 2.7.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 51be736324dd52bf97242e77f261fbbd77f14922
4
- data.tar.gz: d3e7b8b65e9c6856e86ea9d287d450b2ddce66ca
3
+ metadata.gz: 947ea1f82d3c13232378bac704544208961431a4
4
+ data.tar.gz: f72d0af2a8072741e8e2f993b1aa7c12b99c2faa
5
5
  SHA512:
6
- metadata.gz: 9a4a67b0002cf54ef1b4983af83682f2cbfb6ec65a7c95bcef5fe4e644798a61f10c61191fb9ae9dd09863c5e3a5a30e9bd65f3b1a7f5232cd777d9eedd7a1bd
7
- data.tar.gz: 7ddab3f6d8b59870c12ca8a5cbc449fd9b58cec104897563375da29d43ed6e9301eba92fde400a54eded048ece4659ab093e3c9d50525cc1ea3ae8e50616a770
6
+ metadata.gz: 566aaf8bf2f3a012e79e1fcd3028a85f4d26c087b63ba48f03ffea3e626a93150d8ab5b642ecdb3f425df9108eb8963b7bdbc0e6fdb067f7b0987347a019a785
7
+ data.tar.gz: 9fb3b6c03a92fc82649704700a20af03487200bc2096ece6725920c9c54903215aecc153c61a75732f61da839dfe0a6834b00b4de491ee5b8a584ccc2752bb61
data/.travis.yml CHANGED
@@ -22,8 +22,6 @@ rvm:
22
22
  - 2.4.0
23
23
  - 2.3.1
24
24
  - 2.2.5
25
- - 2.1
26
- - 2.0
27
25
  - ruby-head
28
26
 
29
27
  matrix:
@@ -31,10 +29,6 @@ matrix:
31
29
  allow_failures:
32
30
  - rvm: ruby-head
33
31
  exclude:
34
- - gemfile: gemfiles/rails_5.gemfile
35
- rvm: 2.1
36
- - gemfile: gemfiles/rails_5.gemfile
37
- rvm: 2.0
38
32
  - gemfile: gemfiles/rails_4.gemfile
39
33
  rvm: 2.4.0
40
34
  - gemfile: gemfiles/rails_3.gemfile
data/Appraisals CHANGED
@@ -1,13 +1,13 @@
1
- appraise "rails-3" do
2
- gem "rack", "< 2"
3
- gem "rails", "3.2.22.2"
1
+ appraise 'rails-3' do
2
+ gem 'rack', '< 2'
3
+ gem 'rails', '3.2.22.2'
4
4
  end
5
5
 
6
- appraise "rails-4" do
7
- gem "rack", "< 2"
8
- gem "rails", "~> 4.2.6"
6
+ appraise 'rails-4' do
7
+ gem 'rack', '< 2'
8
+ gem 'rails', '~> 4.2.6'
9
9
  end
10
10
 
11
- appraise "rails-5" do
12
- gem "rails", "~> 5.0.0"
11
+ appraise 'rails-5' do
12
+ gem 'rails', '~> 5.0.0'
13
13
  end
data/Gemfile CHANGED
@@ -1,32 +1,23 @@
1
- source "https://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in html-pipeline.gemspec
4
4
  gemspec
5
5
 
6
6
  group :development do
7
- gem "bundler"
8
- gem "rake"
9
- gem "appraisal"
7
+ gem 'appraisal'
8
+ gem 'bundler'
9
+ gem 'rake'
10
10
  end
11
11
 
12
12
  group :test do
13
- gem "minitest"
14
- gem "rinku", "~> 1.7", :require => false
15
- gem "gemoji", "~> 2.0", :require => false
16
- gem "RedCloth", "~> 4.2.9", :require => false
17
- gem "commonmarker", "~> 0.14", :require => false
18
- gem "email_reply_parser", "~> 0.5", :require => false
19
- gem "sanitize", "~> 2.0", :require => false
13
+ gem 'commonmarker', '~> 0.14', require: false
14
+ gem 'email_reply_parser', '~> 0.5', require: false
15
+ gem 'gemoji', '~> 2.0', require: false
16
+ gem 'minitest'
17
+ gem 'RedCloth', '~> 4.2.9', require: false
18
+ gem 'rinku', '~> 1.7', require: false
19
+ gem 'sanitize', '~> 2.0', require: false
20
20
 
21
- if RUBY_VERSION < "2.1.0"
22
- gem "escape_utils", "~> 0.3", :require => false
23
- gem "github-linguist", "~> 2.6.2", :require => false
24
- else
25
- gem "escape_utils", "~> 1.0", :require => false
26
- gem "github-linguist", "~> 2.10", :require => false
27
- end
28
-
29
- if RUBY_VERSION < "1.9.3"
30
- gem "activesupport", ">= 2", "< 4"
31
- end
21
+ gem 'escape_utils', '~> 1.0', require: false
22
+ gem 'rouge', '~> 3.1', require: false
32
23
  end
data/README.md CHANGED
@@ -82,7 +82,7 @@ Prints:
82
82
  </code></pre>
83
83
  ```
84
84
 
85
- To generate CSS for HTML formatted code, use the [pygments.rb](https://github.com/tmm1/pygments.rb#usage) `#css` method. `pygments.rb` is a dependency of the `SyntaxHighlightFilter`.
85
+ To generate CSS for HTML formatted code, use the [Rouge CSS Theme](https://github.com/jneen/rouge#css-theme-options) `#css` method. `rouge` is a dependency of the `SyntaxHighlightFilter`.
86
86
 
87
87
  Some filters take an optional **context** and/or **result** hash. These are
88
88
  used to pass around arguments and metadata between filters in a pipeline. For
@@ -163,7 +163,7 @@ EmojiPipeline = Pipeline.new [
163
163
  * `MarkdownFilter` - convert markdown to html
164
164
  * `PlainTextInputFilter` - html escape text and wrap the result in a div
165
165
  * `SanitizationFilter` - whitelist sanitize user markup
166
- * `SyntaxHighlightFilter` - [code syntax highlighter](#syntax-highlighting)
166
+ * `SyntaxHighlightFilter` - code syntax highlighter
167
167
  * `TextileFilter` - convert textile to html
168
168
  * `TableOfContentsFilter` - anchor headings with name attributes and generate Table of Contents html unordered list linking headings
169
169
 
@@ -171,12 +171,12 @@ EmojiPipeline = Pipeline.new [
171
171
 
172
172
  Filter gem dependencies are not bundled; you must bundle the filter's gem
173
173
  dependencies. The below list details filters with dependencies. For example,
174
- `SyntaxHighlightFilter` uses [github-linguist](https://github.com/github/linguist)
174
+ `SyntaxHighlightFilter` uses [rouge](https://github.com/jneen/rouge)
175
175
  to detect and highlight languages. For example, to use the `SyntaxHighlightFilter`,
176
176
  add the following to your Gemfile:
177
177
 
178
178
  ```ruby
179
- gem 'github-linguist'
179
+ gem 'rouge'
180
180
  ```
181
181
 
182
182
  * `AutolinkFilter` - `rinku`
@@ -185,7 +185,7 @@ gem 'github-linguist'
185
185
  * `MarkdownFilter` - `commonmarker`
186
186
  * `PlainTextInputFilter` - `escape_utils`
187
187
  * `SanitizationFilter` - `sanitize`
188
- * `SyntaxHighlightFilter` - `github-linguist`
188
+ * `SyntaxHighlightFilter` - `rouge`
189
189
  * `TextileFilter` - `RedCloth`
190
190
 
191
191
  _Note:_ See [Gemfile](/Gemfile) `:test` block for version requirements.
@@ -242,7 +242,6 @@ Here are some extensions people have built:
242
242
  * [tilt-html-pipeline](https://github.com/bradgessler/tilt-html-pipeline)
243
243
  * [html-pipeline-wiki-link'](https://github.com/lifted-studios/html-pipeline-wiki-link) - WikiMedia-style wiki links
244
244
  * [task_list](https://github.com/github/task_list) - GitHub flavor Markdown Task List
245
- * [html-pipeline-rouge_filter](https://github.com/JuanitoFatas/html-pipeline-rouge_filter) - Syntax highlight with [Rouge](https://github.com/jneen/rouge/)
246
245
  * [html-pipeline-nico_link](https://github.com/rutan/html-pipeline-nico_link) - An HTML::Pipeline filter for [niconico](http://www.nicovideo.jp) description links
247
246
  * [html-pipeline-gitlab](https://gitlab.com/gitlab-org/html-pipeline-gitlab) - This gem implements various filters for html-pipeline used by GitLab
248
247
  * [html-pipeline-youtube](https://github.com/st0012/html-pipeline-youtube) - An HTML::Pipeline filter for YouTube links
data/Rakefile CHANGED
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env rake
2
- require "rubygems"
3
- require "bundler/setup"
2
+ require 'rubygems'
3
+ require 'bundler/setup'
4
4
 
5
- require "bundler/gem_tasks"
5
+ require 'bundler/gem_tasks'
6
6
  require 'rake/testtask'
7
7
 
8
8
  Rake::TestTask.new do |t|
9
- t.libs << "test"
9
+ t.libs << 'test'
10
10
  t.test_files = FileList['test/**/*_test.rb']
11
11
  t.verbose = true
12
12
  end
13
13
 
14
- task :default => :test
14
+ task default: :test
data/bin/html-pipeline CHANGED
@@ -4,23 +4,23 @@ require 'html/pipeline'
4
4
  require 'optparse'
5
5
 
6
6
  # Accept "help", too
7
- ARGV.map!{|a| a == "help" ? "--help" : a }
7
+ .map! { |a| a == 'help' ? '--help' : a }
8
8
 
9
- OptionParser.new do |opts|
9
+ onParser.new do |opts|
10
10
  opts.banner = <<-HELP.gsub(/^ /, '')
11
11
  Usage: html-pipeline [-h] [-f]
12
12
  html-pipeline [FILTER [FILTER [...]]] < file.md
13
- cat file.md | html-pipeline [FILTER [FILTER [...]]]
13
+ cat file.md | html-pipeline [FILTER [FILTER [...]]]
14
14
  HELP
15
15
 
16
- opts.separator "Options:"
16
+ opts.separator 'Options:'
17
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$/,'') }
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
21
 
22
22
  # Text filter doesn't work, no call method
23
- filters -= ["Text"]
23
+ filters -= ['Text']
24
24
 
25
25
  abort <<-HELP.gsub(/^ /, '')
26
26
  Available filters:
@@ -38,12 +38,12 @@ if ARGV.empty?
38
38
  HTML::Pipeline::ImageMaxWidthFilter,
39
39
  HTML::Pipeline::EmojiFilter,
40
40
  HTML::Pipeline::AutolinkFilter,
41
- HTML::Pipeline::TableOfContentsFilter,
41
+ HTML::Pipeline::TableOfContentsFilter
42
42
  ]
43
43
 
44
- # Add syntax highlighting if linguist is present
44
+ # Add syntax highlighting if rouge is present
45
45
  begin
46
- require 'linguist'
46
+ require 'rouge'
47
47
  filters << HTML::Pipeline::SyntaxHighlightFilter
48
48
  rescue LoadError
49
49
  end
@@ -52,7 +52,7 @@ else
52
52
 
53
53
  def filter_named(name)
54
54
  case name
55
- when "Text"
55
+ when 'Text'
56
56
  raise NameError # Text filter doesn't work, no call method
57
57
  end
58
58
 
@@ -70,9 +70,9 @@ else
70
70
  end
71
71
 
72
72
  context = {
73
- :asset_root => "/assets",
74
- :base_url => "/",
75
- :gfm => true
73
+ asset_root: '/assets',
74
+ base_url: '/',
75
+ gfm: true
76
76
  }
77
77
 
78
78
  puts HTML::Pipeline.new(filters, context).call(ARGF.read)[:output]
@@ -1,21 +1,21 @@
1
- # -*- encoding: utf-8 -*-
2
- require File.expand_path("../lib/html/pipeline/version", __FILE__)
1
+
2
+ require File.expand_path('../lib/html/pipeline/version', __FILE__)
3
3
 
4
4
  Gem::Specification.new do |gem|
5
- gem.name = "html-pipeline"
5
+ gem.name = 'html-pipeline'
6
6
  gem.version = HTML::Pipeline::VERSION
7
- gem.license = "MIT"
8
- gem.authors = ["Ryan Tomayko", "Jerry Cheung"]
9
- gem.email = ["ryan@github.com", "jerry@github.com"]
10
- gem.description = %q{GitHub HTML processing filters and utilities}
11
- gem.summary = %q{Helpers for processing content through a chain of filters}
12
- gem.homepage = "https://github.com/jch/html-pipeline"
7
+ gem.license = 'MIT'
8
+ gem.authors = ['Ryan Tomayko', 'Jerry Cheung']
9
+ gem.email = ['ryan@github.com', 'jerry@github.com']
10
+ gem.description = 'GitHub HTML processing filters and utilities'
11
+ gem.summary = 'Helpers for processing content through a chain of filters'
12
+ gem.homepage = 'https://github.com/jch/html-pipeline'
13
13
 
14
- gem.files = `git ls-files -z`.split("\x0").reject { |f| f =~ %r(^(test|gemfiles|script)/) }
15
- gem.require_paths = ["lib"]
14
+ gem.files = `git ls-files -z`.split("\x0").reject { |f| f =~ %r{^(test|gemfiles|script)/} }
15
+ gem.require_paths = ['lib']
16
16
 
17
- gem.add_dependency "nokogiri", ">= 1.4"
18
- gem.add_dependency "activesupport", ">= 2"
17
+ gem.add_dependency 'activesupport', '>= 2'
18
+ gem.add_dependency 'nokogiri', '>= 1.4'
19
19
 
20
20
  gem.post_install_message = <<msg
21
21
  -------------------------------------------------
data/lib/html/pipeline.rb CHANGED
@@ -1,5 +1,5 @@
1
- require "nokogiri"
2
- require "active_support/xml_mini/nokogiri" # convert Documents to hashes
1
+ require 'nokogiri'
2
+ require 'active_support/xml_mini/nokogiri' # convert Documents to hashes
3
3
 
4
4
  module HTML
5
5
  # GitHub HTML processing filters and utilities. This module includes a small
@@ -43,12 +43,12 @@ module HTML
43
43
  autoload :TableOfContentsFilter, 'html/pipeline/toc_filter'
44
44
  autoload :TextFilter, 'html/pipeline/text_filter'
45
45
 
46
- class MissingDependencyError < LoadError; end
46
+ class MissingDependencyError < RuntimeError; end
47
47
  def self.require_dependency(name, requirer)
48
48
  require name
49
49
  rescue LoadError => e
50
50
  raise MissingDependencyError,
51
- "Missing dependency '#{name}' for #{requirer}. See README.md for details.\n#{e.class.name}: #{e}"
51
+ "Missing dependency '#{name}' for #{requirer}. See README.md for details.\n#{e.class.name}: #{e}"
52
52
  end
53
53
 
54
54
  # Our DOM implementation.
@@ -85,7 +85,7 @@ module HTML
85
85
  end
86
86
 
87
87
  def initialize(filters, default_context = {}, result_class = nil)
88
- raise ArgumentError, "default_context cannot be nil" if default_context.nil?
88
+ raise ArgumentError, 'default_context cannot be nil' if default_context.nil?
89
89
  @filters = filters.flatten.freeze
90
90
  @default_context = default_context.freeze
91
91
  @result_class = result_class || Hash
@@ -108,9 +108,9 @@ module HTML
108
108
  context = @default_context.merge(context)
109
109
  context = context.freeze
110
110
  result ||= @result_class.new
111
- payload = default_payload :filters => @filters.map(&:name),
112
- :context => context, :result => result
113
- instrument "call_pipeline.html_pipeline", payload do
111
+ payload = default_payload filters: @filters.map(&:name),
112
+ context: context, result: result
113
+ instrument 'call_pipeline.html_pipeline', payload do
114
114
  result[:output] =
115
115
  @filters.inject(html) do |doc, filter|
116
116
  perform_filter(filter, doc, context, result)
@@ -125,9 +125,9 @@ module HTML
125
125
  #
126
126
  # Returns the result of the filter.
127
127
  def perform_filter(filter, doc, context, result)
128
- payload = default_payload :filter => filter.name,
129
- :context => context, :result => result
130
- instrument "call_filter.html_pipeline", payload do
128
+ payload = default_payload filter: filter.name,
129
+ context: context, result: result
130
+ instrument 'call_filter.html_pipeline', payload do
131
131
  filter.call(doc, context, result)
132
132
  end
133
133
  end
@@ -178,13 +178,13 @@ module HTML
178
178
  #
179
179
  # Returns a Hash.
180
180
  def default_payload(payload = {})
181
- {:pipeline => instrumentation_name}.merge(payload)
181
+ { pipeline: instrumentation_name }.merge(payload)
182
182
  end
183
183
  end
184
184
  end
185
185
 
186
186
  # XXX nokogiri monkey patches for 1.8
187
- if not ''.respond_to?(:force_encoding)
187
+ unless ''.respond_to?(:force_encoding)
188
188
  class Nokogiri::XML::Node
189
189
  # Work around an issue with utf-8 encoded data being erroneously converted to
190
190
  # ... some other shit when replacing text nodes. See 'utf-8 output 2' in
@@ -196,8 +196,8 @@ if not ''.respond_to?(:force_encoding)
196
196
  replace_without_encoding_fix(replacement)
197
197
  end
198
198
 
199
- alias_method :replace_without_encoding_fix, :replace
200
- alias_method :replace, :replace_with_encoding_fix
199
+ alias replace_without_encoding_fix replace
200
+ alias replace replace_with_encoding_fix
201
201
 
202
202
  def swap(replacement)
203
203
  replace(replacement)
@@ -29,9 +29,9 @@ module HTML
29
29
  # the original text.
30
30
  #
31
31
  # Returns a String replaced with the return of the block.
32
- def self.mentioned_logins_in(text, username_pattern=UsernamePattern)
32
+ def self.mentioned_logins_in(text, username_pattern = UsernamePattern)
33
33
  text.gsub MentionPatterns[username_pattern] do |match|
34
- login = $1
34
+ login = Regexp.last_match(1)
35
35
  yield match, login, MentionLogins.include?(login.downcase)
36
36
  end
37
37
  end
@@ -57,22 +57,22 @@ module HTML
57
57
 
58
58
  # List of username logins that, when mentioned, link to the blog post
59
59
  # about @mentions instead of triggering a real mention.
60
- MentionLogins = %w(
60
+ MentionLogins = %w[
61
61
  mention
62
62
  mentions
63
63
  mentioned
64
64
  mentioning
65
- )
65
+ ].freeze
66
66
 
67
67
  # Don't look for mentions in text nodes that are children of these elements
68
- IGNORE_PARENTS = %w(pre code a style).to_set
68
+ IGNORE_PARENTS = %w(pre code a style script).to_set
69
69
 
70
70
  def call
71
71
  result[:mentioned_usernames] ||= []
72
72
 
73
73
  doc.search('.//text()').each do |node|
74
74
  content = node.to_html
75
- next if !content.include?('@')
75
+ next unless content.include?('@')
76
76
  next if has_ancestor?(node, IGNORE_PARENTS)
77
77
  html = mention_link_filter(content, base_url, info_url, username_pattern)
78
78
  next if html == content
@@ -103,7 +103,7 @@ module HTML
103
103
  #
104
104
  # Returns a string with @mentions replaced with links. All links have a
105
105
  # 'user-mention' class name attached for styling.
106
- def mention_link_filter(text, base_url='/', info_url=nil, username_pattern=UsernamePattern)
106
+ def mention_link_filter(text, _base_url = '/', info_url = nil, username_pattern = UsernamePattern)
107
107
  self.class.mentioned_logins_in(text, username_pattern) do |match, login, is_mentioned|
108
108
  link =
109
109
  if is_mentioned
@@ -116,22 +116,22 @@ module HTML
116
116
  end
117
117
  end
118
118
 
119
- def link_to_mention_info(text, info_url=nil)
119
+ def link_to_mention_info(text, info_url = nil)
120
120
  return "@#{text}" if info_url.nil?
121
- "<a href='#{info_url}' class='user-mention'>" +
122
- "@#{text}" +
123
- "</a>"
121
+ "<a href='#{info_url}' class='user-mention'>" \
122
+ "@#{text}" \
123
+ '</a>'
124
124
  end
125
125
 
126
126
  def link_to_mentioned_user(login)
127
127
  result[:mentioned_usernames] |= [login]
128
128
 
129
129
  url = base_url.dup
130
- url << "/" unless url =~ /[\/~]\z/
130
+ url << '/' unless url =~ /[\/~]\z/
131
131
 
132
- "<a href='#{url << login}' class='user-mention'>" +
133
- "@#{login}" +
134
- "</a>"
132
+ "<a href='#{url << login}' class='user-mention'>" \
133
+ "@#{login}" \
134
+ '</a>'
135
135
  end
136
136
  end
137
137
  end
@@ -2,7 +2,6 @@ require 'uri'
2
2
 
3
3
  module HTML
4
4
  class Pipeline
5
-
6
5
  class AbsoluteSourceFilter < Filter
7
6
  # HTML Filter for replacing relative and root relative image URLs with
8
7
  # fully qualified URLs
@@ -18,31 +17,29 @@ module HTML
18
17
  # This filter does not write additional information to the context.
19
18
  # This filter would need to be run before CamoFilter.
20
19
  def call
21
- doc.search("img").each do |element|
20
+ doc.search('img').each do |element|
22
21
  next if element['src'].nil? || element['src'].empty?
23
22
  src = element['src'].strip
24
- unless src.start_with? 'http'
25
- if src.start_with? '/'
26
- base = image_base_url
27
- else
28
- base = image_subpage_url
29
- end
30
- element["src"] = URI.join(base, src).to_s
31
- end
23
+ next if src.start_with? 'http'
24
+ base = if src.start_with? '/'
25
+ image_base_url
26
+ else
27
+ image_subpage_url
28
+ end
29
+ element['src'] = URI.join(base, src).to_s
32
30
  end
33
31
  doc
34
32
  end
35
-
33
+
36
34
  # Private: the base url you want to use
37
35
  def image_base_url
38
- context[:image_base_url] or raise "Missing context :image_base_url for #{self.class.name}"
36
+ context[:image_base_url] || raise("Missing context :image_base_url for #{self.class.name}")
39
37
  end
40
38
 
41
39
  # Private: the relative url you want to use
42
40
  def image_subpage_url
43
- context[:image_subpage_url] or raise "Missing context :image_subpage_url for #{self.class.name}"
41
+ context[:image_subpage_url] || raise("Missing context :image_subpage_url for #{self.class.name}")
44
42
  end
45
-
46
43
  end
47
44
  end
48
- end
45
+ end
@@ -1,4 +1,4 @@
1
- HTML::Pipeline.require_dependency("rinku", "AutolinkFilter")
1
+ HTML::Pipeline.require_dependency('rinku', 'AutolinkFilter')
2
2
 
3
3
  module HTML
4
4
  class Pipeline
@@ -24,7 +24,7 @@ module HTML
24
24
  def call
25
25
  return doc unless asset_proxy_enabled?
26
26
 
27
- doc.search("img").each do |element|
27
+ doc.search('img').each do |element|
28
28
  original_src = element['src']
29
29
  next unless original_src
30
30
 
@@ -86,7 +86,7 @@ module HTML
86
86
  # Private: helper to hexencode a string. Each byte ends up encoded into
87
87
  # two characters, zero padded value in the range [0-9a-f].
88
88
  def hexencode(str)
89
- str.to_enum(:each_byte).map { |byte| "%02x" % byte }.join
89
+ str.to_enum(:each_byte).map { |byte| format('%02x', byte) }.join
90
90
  end
91
91
  end
92
92
  end
@@ -1,5 +1,5 @@
1
- HTML::Pipeline.require_dependency("escape_utils", "EmailReplyFilter")
2
- HTML::Pipeline.require_dependency("email_reply_parser", "EmailReplyFilter")
1
+ HTML::Pipeline.require_dependency('escape_utils', 'EmailReplyFilter')
2
+ HTML::Pipeline.require_dependency('email_reply_parser', 'EmailReplyFilter')
3
3
 
4
4
  module HTML
5
5
  class Pipeline
@@ -17,9 +17,9 @@ module HTML
17
17
  EMAIL_QUOTED_HEADER = %(<div class="email-quoted-reply">).freeze
18
18
  EMAIL_SIGNATURE_HEADER = %(<div class="email-signature-reply">).freeze
19
19
  EMAIL_FRAGMENT_HEADER = %(<div class="email-fragment">).freeze
20
- EMAIL_HEADER_END = "</div>".freeze
20
+ EMAIL_HEADER_END = '</div>'.freeze
21
21
  EMAIL_REGEX = /[^@\s.][^@\s]*@\[?[a-z0-9.-]+\]?/
22
- HIDDEN_EMAIL_PATTERN = "***@***.***"
22
+ HIDDEN_EMAIL_PATTERN = '***@***.***'.freeze
23
23
 
24
24
  # Scans an email body to determine which bits are quoted and which should
25
25
  # be hidden. EmailReplyParser is used to split the comment into an Array
@@ -1,5 +1,5 @@
1
- require "cgi"
2
- HTML::Pipeline.require_dependency("gemoji", "EmojiFilter")
1
+ require 'cgi'
2
+ HTML::Pipeline.require_dependency('gemoji', 'EmojiFilter')
3
3
 
4
4
  module HTML
5
5
  class Pipeline
@@ -11,12 +11,11 @@ module HTML
11
11
  # :ignored_ancestor_tags (optional) - Tags to stop the emojification. Node has matched ancestor HTML tags will not be emojified. Default to pre, code, and tt tags. Extra tags please pass in the form of array, e.g., %w(blockquote summary).
12
12
  # :img_attrs (optional) - Attributes for generated img tag. E.g. Pass { "draggble" => true, "height" => nil } to set draggable attribute to "true" and clear height attribute of generated img tag.
13
13
  class EmojiFilter < Filter
14
-
15
- DEFAULT_IGNORED_ANCESTOR_TAGS = %w(pre code tt).freeze
14
+ DEFAULT_IGNORED_ANCESTOR_TAGS = %w[pre code tt].freeze
16
15
 
17
16
  def call
18
17
  doc.search('.//text()').each do |node|
19
- content = node.to_html
18
+ content = node.text
20
19
  next unless content.include?(':')
21
20
  next if has_ancestor?(node, ignored_ancestor_tags)
22
21
  html = emoji_image_filter(content)
@@ -38,8 +37,8 @@ module HTML
38
37
  #
39
38
  # Returns a String with :emoji: replaced with images.
40
39
  def emoji_image_filter(text)
41
- text.gsub(emoji_pattern) do |match|
42
- emoji_image_tag($1)
40
+ text.gsub(emoji_pattern) do |_match|
41
+ emoji_image_tag(Regexp.last_match(1))
43
42
  end
44
43
  end
45
44
 
@@ -57,9 +56,9 @@ module HTML
57
56
  # Returns the context's asset_path or the default path if no context asset_path is given.
58
57
  def asset_path(name)
59
58
  if context[:asset_path]
60
- context[:asset_path].gsub(":file_name", emoji_filename(name))
59
+ context[:asset_path].gsub(':file_name', emoji_filename(name))
61
60
  else
62
- File.join("emoji", emoji_filename(name))
61
+ File.join('emoji', emoji_filename(name))
63
62
  end
64
63
  end
65
64
 
@@ -67,12 +66,12 @@ module HTML
67
66
 
68
67
  # Build an emoji image tag
69
68
  def emoji_image_tag(name)
70
- require "active_support/core_ext/hash/indifferent_access"
69
+ require 'active_support/core_ext/hash/indifferent_access'
71
70
  html_attrs =
72
- default_img_attrs(name).
73
- merge!((context[:img_attrs] || {}).with_indifferent_access).
74
- map { |attr, value| !value.nil? && %(#{attr}="#{value.respond_to?(:call) && value.call(name) || value}") }.
75
- reject(&:blank?).join(" ".freeze)
71
+ default_img_attrs(name)
72
+ .merge!((context[:img_attrs] || {}).with_indifferent_access)
73
+ .map { |attr, value| !value.nil? && %(#{attr}="#{value.respond_to?(:call) && value.call(name) || value}") }
74
+ .reject(&:blank?).join(' '.freeze)
76
75
 
77
76
  "<img #{html_attrs}>"
78
77
  end
@@ -80,13 +79,13 @@ module HTML
80
79
  # Default attributes for img tag
81
80
  def default_img_attrs(name)
82
81
  {
83
- "class" => "emoji".freeze,
84
- "title" => ":#{name}:",
85
- "alt" => ":#{name}:",
86
- "src" => "#{emoji_url(name)}",
87
- "height" => "20".freeze,
88
- "width" => "20".freeze,
89
- "align" => "absmiddle".freeze,
82
+ 'class' => 'emoji'.freeze,
83
+ 'title' => ":#{name}:",
84
+ 'alt' => ":#{name}:",
85
+ 'src' => emoji_url(name).to_s,
86
+ 'height' => '20'.freeze,
87
+ 'width' => '20'.freeze,
88
+ 'align' => 'absmiddle'.freeze
90
89
  }
91
90
  end
92
91
 
@@ -30,7 +30,7 @@ module HTML
30
30
  class InvalidDocumentException < StandardError; end
31
31
 
32
32
  def initialize(doc, context = nil, result = nil)
33
- if doc.kind_of?(String)
33
+ if doc.is_a?(String)
34
34
  @html = doc.to_str
35
35
  @doc = nil
36
36
  else
@@ -76,8 +76,7 @@ module HTML
76
76
  end
77
77
 
78
78
  # Make sure the context has everything we need. Noop: Subclasses can override.
79
- def validate
80
- end
79
+ def validate; end
81
80
 
82
81
  # The Repository object provided in the context hash, or nil when no
83
82
  # :repository was specified.
@@ -116,9 +115,7 @@ module HTML
116
115
  # Returns true when the node has a matching ancestor.
117
116
  def has_ancestor?(node, tags)
118
117
  while node = node.parent
119
- if tags.include?(node.name.downcase)
120
- break true
121
- end
118
+ break true if tags.include?(node.name.downcase)
122
119
  end
123
120
  end
124
121
 
@@ -134,7 +131,7 @@ module HTML
134
131
  # the last filter returns a String.
135
132
  def self.to_document(input, context = nil)
136
133
  html = call(input, context)
137
- HTML::Pipeline::parse(html)
134
+ HTML::Pipeline.parse(html)
138
135
  end
139
136
 
140
137
  # Like call but guarantees that a string of HTML markup is returned.
@@ -158,7 +155,7 @@ module HTML
158
155
 
159
156
  if missing.any?
160
157
  raise ArgumentError,
161
- "Missing context keys for #{self.class.name}: #{missing.map(&:inspect).join ', '}"
158
+ "Missing context keys for #{self.class.name}: #{missing.map(&:inspect).join ', '}"
162
159
  end
163
160
  end
164
161
  end
@@ -7,8 +7,8 @@ module HTML
7
7
  # :http_url - The HTTP url to force HTTPS. Falls back to :base_url
8
8
  class HttpsFilter < Filter
9
9
  def call
10
- doc.css(%Q(a[href^="#{http_url}"])).each do |element|
11
- element['href'] = element['href'].sub(/^http:/,'https:')
10
+ doc.css(%(a[href^="#{http_url}"])).each do |element|
11
+ element['href'] = element['href'].sub(/^http:/, 'https:')
12
12
  end
13
13
  doc
14
14
  end
@@ -9,7 +9,7 @@ module HTML
9
9
  class ImageFilter < TextFilter
10
10
  def call
11
11
  @text.gsub(/(https|http)?:\/\/.+\.(jpg|jpeg|bmp|gif|png)(\?\S+)?/i) do |match|
12
- %|<img src="#{match}" alt=""/>|
12
+ %(<img src="#{match}" alt=""/>)
13
13
  end
14
14
  end
15
15
  end
@@ -17,21 +17,19 @@ module HTML
17
17
  # js injection via javascript: urls.
18
18
  next if element['src'].to_s.strip =~ /\Ajavascript/i
19
19
 
20
- element['style'] = "max-width:100%;"
20
+ element['style'] = 'max-width:100%;'
21
21
 
22
- if !has_ancestor?(element, %w(a))
23
- link_image element
24
- end
22
+ link_image element unless has_ancestor?(element, %w[a])
25
23
  end
26
24
 
27
25
  doc
28
26
  end
29
27
 
30
28
  def link_image(element)
31
- link = doc.document.create_element('a', :href => element['src'], :target => '_blank')
29
+ link = doc.document.create_element('a', href: element['src'], target: '_blank')
32
30
  link.add_child(element.dup)
33
31
  element.replace(link)
34
32
  end
35
33
  end
36
34
  end
37
- end
35
+ end
@@ -1,4 +1,4 @@
1
- HTML::Pipeline.require_dependency("commonmarker", "MarkdownFilter")
1
+ HTML::Pipeline.require_dependency('commonmarker', 'MarkdownFilter')
2
2
 
3
3
  module HTML
4
4
  class Pipeline
@@ -15,7 +15,7 @@ module HTML
15
15
  class MarkdownFilter < TextFilter
16
16
  def initialize(text, context = nil, result = nil)
17
17
  super text, context, result
18
- @text = @text.gsub "\r", ''
18
+ @text = @text.delete "\r"
19
19
  end
20
20
 
21
21
  # Convert Markdown to HTML using the best available implementation
@@ -25,7 +25,8 @@ module HTML
25
25
  options << :HARDBREAKS if context[:gfm] != false
26
26
  extensions = context.fetch(
27
27
  :commonmarker_extensions,
28
- [:table, :strikethrough, :tagfilter, :autolink])
28
+ %i[table strikethrough tagfilter autolink]
29
+ )
29
30
  html = CommonMarker.render_html(@text, options, extensions)
30
31
  html.rstrip!
31
32
  html
@@ -1,4 +1,4 @@
1
- HTML::Pipeline.require_dependency("escape_utils", "PlainTextInputFilter")
1
+ HTML::Pipeline.require_dependency('escape_utils', 'PlainTextInputFilter')
2
2
 
3
3
  module HTML
4
4
  class Pipeline
@@ -1,4 +1,4 @@
1
- HTML::Pipeline.require_dependency("sanitize", "SanitizationFilter")
1
+ HTML::Pipeline.require_dependency('sanitize', 'SanitizationFilter')
2
2
 
3
3
  module HTML
4
4
  class Pipeline
@@ -21,16 +21,16 @@ module HTML
21
21
  #
22
22
  # This filter does not write additional information to the context.
23
23
  class SanitizationFilter < Filter
24
- LISTS = Set.new(%w(ul ol).freeze)
24
+ LISTS = Set.new(%w[ul ol].freeze)
25
25
  LIST_ITEM = 'li'.freeze
26
26
 
27
27
  # List of table child elements. These must be contained by a <table> element
28
28
  # or they are not allowed through. Otherwise they can be used to break out
29
29
  # of places we're using tables to contain formatted user content (like pull
30
30
  # request review comments).
31
- TABLE_ITEMS = Set.new(%w(tr td th).freeze)
31
+ TABLE_ITEMS = Set.new(%w[tr td th].freeze)
32
32
  TABLE = 'table'.freeze
33
- TABLE_SECTIONS = Set.new(%w(thead tbody tfoot).freeze)
33
+ TABLE_SECTIONS = Set.new(%w[thead tbody tfoot].freeze)
34
34
 
35
35
  # These schemes are the only ones allowed in <a href> attributes by default.
36
36
  ANCHOR_SCHEMES = ['http', 'https', 'mailto', :relative, 'github-windows', 'github-mac'].freeze
@@ -38,77 +38,80 @@ module HTML
38
38
  # The main sanitization whitelist. Only these elements and attributes are
39
39
  # allowed through by default.
40
40
  WHITELIST = {
41
- :elements => %w(
41
+ elements: %w[
42
42
  h1 h2 h3 h4 h5 h6 h7 h8 br b i strong em a pre code img tt
43
43
  div ins del sup sub p ol ul table thead tbody tfoot blockquote
44
44
  dl dt dd kbd q samp var hr ruby rt rp li tr td th s strike summary details
45
- ),
46
- :remove_contents => ['script'],
47
- :attributes => {
45
+ ],
46
+ remove_contents: ['script'],
47
+ attributes: {
48
48
  'a' => ['href'],
49
- 'img' => ['src', 'longdesc'],
50
- 'div' => ['itemscope', 'itemtype'],
49
+ 'img' => %w[src longdesc],
50
+ 'div' => %w[itemscope itemtype],
51
51
  'blockquote' => ['cite'],
52
52
  'del' => ['cite'],
53
53
  'ins' => ['cite'],
54
54
  'q' => ['cite'],
55
- :all => ['abbr', 'accept', 'accept-charset',
56
- 'accesskey', 'action', 'align', 'alt', 'axis',
57
- 'border', 'cellpadding', 'cellspacing', 'char',
58
- 'charoff', 'charset', 'checked',
59
- 'clear', 'cols', 'colspan', 'color',
60
- 'compact', 'coords', 'datetime', 'dir',
61
- 'disabled', 'enctype', 'for', 'frame',
62
- 'headers', 'height', 'hreflang',
63
- 'hspace', 'ismap', 'label', 'lang',
64
- 'maxlength', 'media', 'method',
65
- 'multiple', 'name', 'nohref', 'noshade',
66
- 'nowrap', 'open', 'prompt', 'readonly', 'rel', 'rev',
67
- 'rows', 'rowspan', 'rules', 'scope',
68
- 'selected', 'shape', 'size', 'span',
69
- 'start', 'summary', 'tabindex', 'target',
70
- 'title', 'type', 'usemap', 'valign', 'value',
71
- 'vspace', 'width', 'itemprop']
55
+ :all => ['abbr', 'accept', 'accept-charset',
56
+ 'accesskey', 'action', 'align', 'alt', 'axis',
57
+ 'border', 'cellpadding', 'cellspacing', 'char',
58
+ 'charoff', 'charset', 'checked',
59
+ 'clear', 'cols', 'colspan', 'color',
60
+ 'compact', 'coords', 'datetime', 'dir',
61
+ 'disabled', 'enctype', 'for', 'frame',
62
+ 'headers', 'height', 'hreflang',
63
+ 'hspace', 'ismap', 'label', 'lang',
64
+ 'maxlength', 'media', 'method',
65
+ 'multiple', 'name', 'nohref', 'noshade',
66
+ 'nowrap', 'open', 'prompt', 'readonly', 'rel', 'rev',
67
+ 'rows', 'rowspan', 'rules', 'scope',
68
+ 'selected', 'shape', 'size', 'span',
69
+ 'start', 'summary', 'tabindex', 'target',
70
+ 'title', 'type', 'usemap', 'valign', 'value',
71
+ 'vspace', 'width', 'itemprop']
72
72
  },
73
- :protocols => {
74
- 'a' => {'href' => ANCHOR_SCHEMES},
75
- 'blockquote' => {'cite' => ['http', 'https', :relative]},
76
- 'del' => {'cite' => ['http', 'https', :relative]},
77
- 'ins' => {'cite' => ['http', 'https', :relative]},
78
- 'q' => {'cite' => ['http', 'https', :relative]},
73
+ protocols: {
74
+ 'a' => { 'href' => ANCHOR_SCHEMES },
75
+ 'blockquote' => { 'cite' => ['http', 'https', :relative] },
76
+ 'del' => { 'cite' => ['http', 'https', :relative] },
77
+ 'ins' => { 'cite' => ['http', 'https', :relative] },
78
+ 'q' => { 'cite' => ['http', 'https', :relative] },
79
79
  'img' => {
80
80
  'src' => ['http', 'https', :relative],
81
81
  'longdesc' => ['http', 'https', :relative]
82
82
  }
83
83
  },
84
- :transformers => [
84
+ transformers: [
85
85
  # Top-level <li> elements are removed because they can break out of
86
86
  # containing markup.
87
87
  lambda { |env|
88
- name, node = env[:node_name], env[:node]
89
- if name == LIST_ITEM && !node.ancestors.any?{ |n| LISTS.include?(n.name) }
88
+ name = env[:node_name]
89
+ node = env[:node]
90
+ if name == LIST_ITEM && node.ancestors.none? { |n| LISTS.include?(n.name) }
90
91
  node.replace(node.children)
91
92
  end
92
93
  },
93
94
 
94
95
  # Table child elements that are not contained by a <table> are removed.
95
96
  lambda { |env|
96
- name, node = env[:node_name], env[:node]
97
- if (TABLE_SECTIONS.include?(name) || TABLE_ITEMS.include?(name)) && !node.ancestors.any? { |n| n.name == TABLE }
97
+ name = env[:node_name]
98
+ node = env[:node]
99
+ if (TABLE_SECTIONS.include?(name) || TABLE_ITEMS.include?(name)) && node.ancestors.none? { |n| n.name == TABLE }
98
100
  node.replace(node.children)
99
101
  end
100
102
  }
101
103
  ]
102
- }
104
+ }.freeze
103
105
 
104
106
  # A more limited sanitization whitelist. This includes all attributes,
105
107
  # protocols, and transformers from WHITELIST but with a more locked down
106
108
  # set of allowed elements.
107
109
  LIMITED = WHITELIST.merge(
108
- :elements => %w(b i strong em a pre code img ins del sup sub p ol ul li))
110
+ elements: %w[b i strong em a pre code img ins del sup sub p ol ul li]
111
+ )
109
112
 
110
113
  # Strip all HTML tags from the document.
111
- FULL = { :elements => [] }
114
+ FULL = { elements: [] }.freeze
112
115
 
113
116
  # Sanitize markup using the Sanitize library.
114
117
  def call
@@ -1,10 +1,15 @@
1
- HTML::Pipeline.require_dependency("linguist", "SyntaxHighlightFilter")
1
+ HTML::Pipeline.require_dependency('rouge', 'SyntaxHighlightFilter')
2
2
 
3
3
  module HTML
4
4
  class Pipeline
5
5
  # HTML Filter that syntax highlights code blocks wrapped
6
6
  # in <pre lang="...">.
7
7
  class SyntaxHighlightFilter < Filter
8
+ def initialize(*args)
9
+ super(*args)
10
+ @formatter = Rouge::Formatters::HTML.new
11
+ end
12
+
8
13
  def call
9
14
  doc.search('pre').each do |node|
10
15
  default = context[:highlight] && context[:highlight].to_s
@@ -12,27 +17,26 @@ module HTML
12
17
  next unless lexer = lexer_for(lang)
13
18
  text = node.inner_text
14
19
 
15
- html = highlight_with_timeout_handling(lexer, text)
20
+ html = highlight_with_timeout_handling(text, lang)
16
21
  next if html.nil?
17
22
 
18
- if (node = node.replace(html).first)
19
- klass = node["class"]
20
- klass = [klass, "highlight-#{lang}"].compact.join " "
23
+ next unless (node = node.replace(html).first)
24
+ klass = node['class']
25
+ klass = [klass, "highlight-#{lang}"].compact.join ' '
21
26
 
22
- node["class"] = klass
23
- end
27
+ node['class'] = klass
24
28
  end
25
29
  doc
26
30
  end
27
31
 
28
- def highlight_with_timeout_handling(lexer, text)
29
- lexer.highlight(text)
30
- rescue Timeout::Error => boom
32
+ def highlight_with_timeout_handling(text, lang)
33
+ Rouge.highlight(text, lang, @formatter)
34
+ rescue Timeout::Error => _
31
35
  nil
32
36
  end
33
37
 
34
38
  def lexer_for(lang)
35
- (Linguist::Language[lang] && Linguist::Language[lang].lexer) || Pygments::Lexer[lang]
39
+ Rouge::Lexer.find(lang)
36
40
  end
37
41
  end
38
42
  end
@@ -4,11 +4,11 @@ module HTML
4
4
  attr_reader :text
5
5
 
6
6
  def initialize(text, context = nil, result = nil)
7
- raise TypeError, "text cannot be HTML" if text.is_a?(DocumentFragment)
7
+ raise TypeError, 'text cannot be HTML' if text.is_a?(DocumentFragment)
8
8
  # Ensure that this is always a string
9
9
  @text = text.respond_to?(:to_str) ? text.to_str : text.to_s
10
10
  super nil, context, result
11
11
  end
12
12
  end
13
13
  end
14
- end
14
+ end
@@ -1,4 +1,4 @@
1
- HTML::Pipeline.require_dependency("redcloth", "RedCloth")
1
+ HTML::Pipeline.require_dependency('redcloth', 'RedCloth')
2
2
 
3
3
  module HTML
4
4
  class Pipeline
@@ -23,35 +23,35 @@ module HTML
23
23
  # result[:output].to_s
24
24
  # # => "<h1>\n<a id=\"ice-cube\" class=\"anchor\" href=\"#ice-cube\">..."
25
25
  class TableOfContentsFilter < Filter
26
- PUNCTUATION_REGEXP = RUBY_VERSION > "1.9" ? /[^\p{Word}\- ]/u : /[^\w\- ]/
26
+ PUNCTUATION_REGEXP = RUBY_VERSION > '1.9' ? /[^\p{Word}\- ]/u : /[^\w\- ]/
27
27
 
28
28
  # The icon that will be placed next to an anchored rendered markdown header
29
29
  def anchor_icon
30
- context[:anchor_icon] || "<span aria-hidden=\"true\" class=\"octicon octicon-link\"></span>"
30
+ context[:anchor_icon] || '<span aria-hidden="true" class="octicon octicon-link"></span>'
31
31
  end
32
32
 
33
33
  def call
34
- result[:toc] = ""
34
+ result[:toc] = ''
35
35
 
36
36
  headers = Hash.new(0)
37
37
  doc.css('h1, h2, h3, h4, h5, h6').each do |node|
38
38
  text = node.text
39
39
  id = ascii_downcase(text)
40
40
  id.gsub!(PUNCTUATION_REGEXP, '') # remove punctuation
41
- id.gsub!(' ', '-') # replace spaces with dash
41
+ id.tr!(' ', '-') # replace spaces with dash
42
42
 
43
- uniq = (headers[id] > 0) ? "-#{headers[id]}" : ''
43
+ uniq = headers[id] > 0 ? "-#{headers[id]}" : ''
44
44
  headers[id] += 1
45
45
  if header_content = node.children.first
46
- result[:toc] << %Q{<li><a href="##{id}#{uniq}">#{text}</a></li>\n}
47
- header_content.add_previous_sibling(%Q{<a id="#{id}#{uniq}" class="anchor" href="##{id}#{uniq}" aria-hidden="true">#{anchor_icon}</a>})
46
+ result[:toc] << %(<li><a href="##{id}#{uniq}">#{text}</a></li>\n)
47
+ header_content.add_previous_sibling(%(<a id="#{id}#{uniq}" class="anchor" href="##{id}#{uniq}" aria-hidden="true">#{anchor_icon}</a>))
48
48
  end
49
49
  end
50
- result[:toc] = %Q{<ul class="section-nav">\n#{result[:toc]}</ul>} unless result[:toc].empty?
50
+ result[:toc] = %(<ul class="section-nav">\n#{result[:toc]}</ul>) unless result[:toc].empty?
51
51
  doc
52
52
  end
53
53
 
54
- if RUBY_VERSION >= "2.4"
54
+ if RUBY_VERSION >= '2.4'
55
55
  def ascii_downcase(str)
56
56
  str.downcase(:ascii)
57
57
  end
@@ -1,5 +1,5 @@
1
1
  module HTML
2
2
  class Pipeline
3
- VERSION = "2.7.1"
3
+ VERSION = '2.7.2'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: html-pipeline
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.7.1
4
+ version: 2.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Tomayko
@@ -9,36 +9,36 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-09-21 00:00:00.000000000 Z
12
+ date: 2018-04-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: nokogiri
15
+ name: activesupport
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
18
  - - ">="
19
19
  - !ruby/object:Gem::Version
20
- version: '1.4'
20
+ version: '2'
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - ">="
26
26
  - !ruby/object:Gem::Version
27
- version: '1.4'
27
+ version: '2'
28
28
  - !ruby/object:Gem::Dependency
29
- name: activesupport
29
+ name: nokogiri
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
32
  - - ">="
33
33
  - !ruby/object:Gem::Version
34
- version: '2'
34
+ version: '1.4'
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - ">="
40
40
  - !ruby/object:Gem::Version
41
- version: '2'
41
+ version: '1.4'
42
42
  description: GitHub HTML processing filters and utilities
43
43
  email:
44
44
  - ryan@github.com