html-proofer 3.0.0 → 3.1.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1ce6c96e75683a8da4de60754d83aef138221d02
4
- data.tar.gz: b341f1ee5b7237e58cba8e775dfaa152eaeeb0a5
3
+ metadata.gz: 2d69ea6f2eb74095372c3f46f5b0b40beb25d4c2
4
+ data.tar.gz: b788331194e898263a88a47f41c60f77a4f3051a
5
5
  SHA512:
6
- metadata.gz: 000ff0816076d1e8b738526f380e88309fdc04d93fa203a43d62960696064062b7942647a5f79be0f8e7239ca69e67f08f669866352cabf67152a6f95beb643b
7
- data.tar.gz: 1863ee52843f2d5071170aaed79ce2ae9f6902ffb1a99d93021b746eb9d3d792d460d4caff2f703907291915b0bc8861af8967cd4f5a394e0a6604aa23e0dec0
6
+ metadata.gz: a98a1fd90173d4481caae3c2fa7b702e1d5ab04cd262f4c555d250b7ce4518e29bcb0f3cfba7cd33d88526389bd05f3665b3ebb6ca0a46404057fa01f7663c62
7
+ data.tar.gz: 603de7c0256dde6120f0cce01e4803768c09468c620a04d81d6b053bd3d66e72573bc8fbe33efa9597a090fcd3c9f8744826021829e1619fc35fdc584c8c7513
data/bin/htmlproofer CHANGED
@@ -18,9 +18,10 @@ Mercenary.program(:htmlproofer) do |p|
18
18
  p.option 'alt_ignore', '--alt-ignore image1,[image2,...]', Array, 'A comma-separated list of Strings or RegExps containing `img`s whose missing `alt` tags are safe to ignore'
19
19
  p.option 'assume_extension', '--assume-extension', 'Automatically add extension (e.g. `.html`) to file paths, to allow extensionless URLs (as supported by Jekyll 3 and GitHub Pages) (default: `false`).'
20
20
  p.option 'checks_to_ignore', '--checks-to-ignore check1,[check2,...]', Array, ' An array of Strings indicating which checks you\'d like to not perform.'
21
- p.option 'check_external_hash', '--check-external-hash', 'Checks whether external hashes exist (even if the website exists). This slows the checker down (default: `false`).'
21
+ p.option 'check_external_hash', '--check-external-hash', 'Checks whether external hashes exist (even if the webpage exists). This slows the checker down (default: `false`).'
22
22
  p.option 'check_favicon', '--check-favicon', 'Enables the favicon checker (default: `false`).'
23
23
  p.option 'check_html', '--check-html', 'Enables HTML validation errors from Nokogiri (default: `false`).'
24
+ p.option 'check_img_http', '--check-img-http', 'Fails an image if it\'s marked as `http` (default: `false`).'
24
25
  p.option 'directory_index_file', '--directory-index-file', String, 'Sets the file to look for when a link refers to a directory. (default: `index.html`)'
25
26
  p.option 'disable_external', '--disable-external', 'If `true`, does not run the external link checker, which can take a lot of time (default: `false`)'
26
27
  p.option 'empty_alt_ignore', '--empty-alt-ignore', 'If `true`, ignores images with empty alt tags'
@@ -31,12 +32,14 @@ Mercenary.program(:htmlproofer) do |p|
31
32
  p.option 'file_ignore', '--file-ignore file1,[file2,...]', Array, 'A comma-separated list of Strings or RegExps containing file paths that are safe to ignore'
32
33
  p.option 'http_status_ignore', '--http-status-ignore 123,[xxx, ...]', Array, 'A comma-separated list of numbers representing status codes to ignore.'
33
34
  p.option 'report_invalid_tags', '--report-invalid-tags', 'Ignore `check_html` errors associated with unknown markup (default: `false`)'
35
+ p.option 'report_missing_names', '--report-missing-names', 'Ignore `check_html` errors associated with missing entities (default: `false`)'
34
36
  p.option 'report_script_embeds', '--report-script-embeds', 'Ignore `check_html` errors associated with `script`s (default: `false`)'
35
37
  p.option 'log_level', '--log-level <level>', String, 'Sets the logging level, as determined by Yell'
36
38
  p.option 'only_4xx', '--only-4xx', 'Only reports errors for links that fall within the 4xx status code range'
37
39
  p.option 'timeframe', '--timeframe <time>', String, 'A string representing the caching timeframe.'
38
40
  p.option 'url_ignore', '--url-ignore link1,[link2,...]', Array, 'A comma-separated list of Strings or RegExps containing URLs that are safe to ignore. It affects all HTML attributes. Note that non-HTTP(S) URIs are always ignored'
39
- p.option 'url_swap', '--url-swap re:string,[re:string,...]', Array, 'A comma-separated list containing key-value pairs of `RegExp => String`. It transforms URLs that match `RegExp` into `String` via `gsub`.'
41
+ p.option 'url_swap', '--url-swap re:string,[re:string,...]', Array, 'A comma-separated list containing key-value pairs of `RegExp => String`. It transforms URLs that match `RegExp` into `String` via `gsub`. The escape sequences `\\:` should be used to produce literal `:`s.'
42
+ p.option 'internal_domains', '--internal-domains domain1,[domain2,...]', Array, 'A comma-separated list of Strings containing domains that will be treated as internal urls.'
40
43
 
41
44
  p.action do |args, opts|
42
45
  args = ['.'] if args.empty?
@@ -46,7 +49,7 @@ Mercenary.program(:htmlproofer) do |p|
46
49
 
47
50
  # prepare everything to go to proofer
48
51
  p.options.select { |o| !opts[o.config_key].nil? }.each do |option|
49
- if option.return_type.to_s == 'Array' # TODO: is_a? doesn't work here?
52
+ if opts[option.config_key].is_a?(Array)
50
53
  opts[option.config_key] = opts[option.config_key].map { |i| HTMLProofer::Configuration.to_regex?(i) }
51
54
  end
52
55
  options[option.config_key.to_sym] = opts[option.config_key]
@@ -56,8 +59,11 @@ Mercenary.program(:htmlproofer) do |p|
56
59
  unless opts['url_swap'].nil?
57
60
  options[:url_swap] = {}
58
61
  opts['url_swap'].each do |s|
59
- pair = s.split(':', 2)
60
- options[:url_swap][Regexp.new(pair[0])] = pair[1]
62
+ splt = s.split(/(?<!\\):/,2)
63
+
64
+ re = splt[0].gsub(/\\:/, ':')
65
+ string = splt[1].gsub(/\\:/, ':')
66
+ options[:url_swap][Regexp.new(re)] = string
61
67
  end
62
68
  end
63
69
 
@@ -67,11 +73,14 @@ Mercenary.program(:htmlproofer) do |p|
67
73
  # FIXME: this is gross
68
74
  options[:validation] = {}
69
75
  options[:validation][:report_script_embeds] = opts['report_script_embeds']
76
+ options[:validation][:report_missing_names] = opts['report_missing_names']
70
77
  options[:validation][:report_invalid_tags] = opts['report_invalid_tags']
71
78
 
72
79
  options[:cache] = {}
73
80
  options[:cache][:timeframe] = opts['timeframe'] unless opts['timeframe'].nil?
74
81
 
82
+ options[:http_status_ignore] = Array(options[:http_status_ignore]).map(&:to_i)
83
+
75
84
  paths = path.split(',')
76
85
  if opts['as_links']
77
86
  links = path.delete(' ').split(',')
@@ -2,6 +2,7 @@ class HtmlCheck < ::HTMLProofer::Check
2
2
  SCRIPT_EMBEDS_MSG = /Element script embeds close tag/
3
3
  INVALID_TAG_MSG = /Tag ([\w\-:]+) invalid/
4
4
  INVALID_PREFIX = /Namespace prefix/
5
+ PARSE_ENTITY_REF = /htmlParseEntityRef: no name/
5
6
 
6
7
  def run
7
8
  @html.errors.each do |error|
@@ -12,6 +13,10 @@ class HtmlCheck < ::HTMLProofer::Check
12
13
  next unless options[:validation][:report_invalid_tags]
13
14
  end
14
15
 
16
+ if message =~ PARSE_ENTITY_REF
17
+ next unless options[:validation][:report_missing_names]
18
+ end
19
+
15
20
  # tags embedded in scripts are used in templating languages: http://git.io/vOovv
16
21
  next if !options[:validation][:report_script_embeds] && message =~ SCRIPT_EMBEDS_MSG
17
22
 
@@ -37,9 +37,13 @@ class ImageCheck < ::HTMLProofer::Check
37
37
  end
38
38
  end
39
39
 
40
- if @img.alt.nil? || (empty_alt_tag? && !@img.ignore_empty_alt?)
40
+ if !@img.ignore_alt? && (@img.alt.nil? || (empty_alt_tag? && !@img.ignore_empty_alt?))
41
41
  add_issue("image #{@img.url} does not have an alt attribute", line: line)
42
42
  end
43
+
44
+ if @img.check_img_http? && @img.scheme == 'http'
45
+ add_issue("image #{@img.url} uses the http scheme", line: line)
46
+ end
43
47
  end
44
48
 
45
49
  external_urls
@@ -9,6 +9,7 @@ module HTMLProofer
9
9
  :check_external_hash => false,
10
10
  :check_favicon => false,
11
11
  :check_html => false,
12
+ :check_img_http => false,
12
13
  :checks_to_ignore => [],
13
14
  :directory_index_file => 'index.html',
14
15
  :disable_external => false,
@@ -19,10 +20,11 @@ module HTMLProofer
19
20
  :external_only => false,
20
21
  :file_ignore => [],
21
22
  :http_status_ignore => [],
23
+ :internal_domains => [],
22
24
  :log_level => :info,
23
25
  :only_4xx => false,
24
26
  :url_ignore => [],
25
- :url_swap => []
27
+ :url_swap => {}
26
28
  }
27
29
 
28
30
  TYPHOEUS_DEFAULTS = {
@@ -40,6 +42,7 @@ module HTMLProofer
40
42
 
41
43
  VALIDATION_DEFAULTS = {
42
44
  :report_script_embeds => false,
45
+ :report_missing_names => false,
43
46
  :report_invalid_tags => false
44
47
  }
45
48
 
@@ -6,10 +6,10 @@ module HTMLProofer
6
6
  class Element
7
7
  include HTMLProofer::Utils
8
8
 
9
- attr_reader :id, :name, :alt, :href, :link, :src, :line
9
+ attr_reader :id, :name, :alt, :href, :link, :src, :line, :data_proofer_ignore
10
10
 
11
11
  def initialize(obj, check)
12
- # Contruct readable ivars for every element
12
+ # Construct readable ivars for every element
13
13
  obj.attributes.each_pair do |attribute, value|
14
14
  name = "#{attribute.tr('-:.', '_')}".to_sym
15
15
  (class << self; self; end).send(:attr_reader, name)
@@ -25,10 +25,11 @@ module HTMLProofer
25
25
  # fix up missing protocols
26
26
  @href.insert 0, 'http:' if @href =~ %r{^//}
27
27
  @src.insert 0, 'http:' if @src =~ %r{^//}
28
+ @srcset.insert 0, 'http:' if @srcset =~ %r{^//}
28
29
  end
29
30
 
30
31
  def url
31
- url = @src || @srcset || @href || ''
32
+ url = (@src || @srcset || @href || '').gsub("\u200b", '')
32
33
  return url if @check.options[:url_swap].empty?
33
34
  swap(url, @check.options[:url_swap])
34
35
  end
@@ -39,7 +40,7 @@ module HTMLProofer
39
40
 
40
41
  def parts
41
42
  @parts ||= Addressable::URI.parse url
42
- rescue URI::Error, Addressable::URI::InvalidURIError
43
+ rescue URI::Error, Addressable::URI::InvalidURIError => e
43
44
  @parts = nil
44
45
  end
45
46
 
@@ -76,9 +77,9 @@ module HTMLProofer
76
77
 
77
78
  # ignore user defined URLs
78
79
  return true if ignores_pattern_check(@check.options[:url_ignore])
80
+ end
79
81
 
80
- # ignore user defined alts
81
- return false unless 'ImageCheck' == @type
82
+ def ignore_alt?
82
83
  return true if ignores_pattern_check(@check.options[:alt_ignore])
83
84
  end
84
85
 
@@ -90,6 +91,10 @@ module HTMLProofer
90
91
  @check.options[:allow_hash_href]
91
92
  end
92
93
 
94
+ def check_img_http?
95
+ @check.options[:check_img_http]
96
+ end
97
+
93
98
  # path is external to the file
94
99
  def external?
95
100
  !internal?
@@ -23,6 +23,15 @@ module HTMLProofer
23
23
  FileUtils.mkdir_p(STORAGE_DIR)
24
24
  end
25
25
 
26
+ # Add swap patterns for internal domains
27
+ unless @options[:internal_domains].empty?
28
+ @options[:internal_domains].each do |dom|
29
+ @options[:url_swap][Regexp.new("^http://#{dom}")] = ''
30
+ @options[:url_swap][Regexp.new("^https://#{dom}")] = ''
31
+ @options[:url_swap][Regexp.new("^//#{dom}")] = ''
32
+ end
33
+ end
34
+
26
35
  @failures = []
27
36
  end
28
37
 
@@ -96,7 +105,11 @@ module HTMLProofer
96
105
  @logger.log :debug, "Checking #{klass.to_s.downcase} on #{path} ..."
97
106
  check = Object.const_get(klass).new(src, path, html, @options)
98
107
  check.run
99
- result[:external_urls].merge!(check.external_urls)
108
+ external_urls = check.external_urls
109
+ if @options[:url_swap]
110
+ external_urls = Hash[check.external_urls.map { |url, file| [swap(url, @options[:url_swap]), file] }]
111
+ end
112
+ result[:external_urls].merge!(external_urls)
100
113
  result[:failures].concat(check.issues)
101
114
  end
102
115
  end
@@ -150,7 +150,7 @@ module HTMLProofer
150
150
  elsif response.timed_out?
151
151
  handle_timeout(href, filenames, response_code)
152
152
  elsif response_code == 0
153
- handle_failure(href, filenames, response_code)
153
+ handle_failure(href, filenames, response_code, response.return_message)
154
154
  elsif method == :head
155
155
  queue_request(:get, href, filenames)
156
156
  else
@@ -192,8 +192,11 @@ module HTMLProofer
192
192
  add_external_issue(filenames, msg, response_code)
193
193
  end
194
194
 
195
- def handle_failure(href, filenames, response_code)
196
- msg = "External link #{href} failed: response code #{response_code} means something's wrong"
195
+ def handle_failure(href, filenames, response_code, return_message)
196
+ msg = "External link #{href} failed: response code #{response_code} means something's wrong.
197
+ It's possible libcurl couldn't connect to the server or perhaps the request timed out.
198
+ Sometimes, making too many requests at once also breaks things.
199
+ Either way, the return message (if any) from the server is: #{return_message}"
197
200
  @cache.add(href, filenames, 0, msg)
198
201
  return if @options[:only_4xx]
199
202
  add_external_issue(filenames, msg, response_code)
@@ -1,3 +1,3 @@
1
1
  module HTMLProofer
2
- VERSION = '3.0.0'
2
+ VERSION = '3.1.0'.freeze
3
3
  end
data/lib/html-proofer.rb CHANGED
@@ -1,10 +1,11 @@
1
1
  def require_all(path)
2
- glob = File.join(File.dirname(__FILE__), path, '*.rb')
3
- Dir[glob].each do |f|
2
+ dir = File.join(File.dirname(__FILE__), path)
3
+ Dir[File.join(dir, '*.rb')].each do |f|
4
4
  require f
5
5
  end
6
6
  end
7
7
 
8
+ require_relative 'html-proofer/utils'
8
9
  require_all 'html-proofer'
9
10
  require_all 'html-proofer/check'
10
11
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: html-proofer
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Garen Torikian
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-05 00:00:00.000000000 Z
11
+ date: 2016-09-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mercenary
@@ -112,16 +112,22 @@ dependencies:
112
112
  name: activesupport
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - "~>"
115
+ - - ">="
116
116
  - !ruby/object:Gem::Version
117
117
  version: '4.2'
118
+ - - "<"
119
+ - !ruby/object:Gem::Version
120
+ version: '6.0'
118
121
  type: :runtime
119
122
  prerelease: false
120
123
  version_requirements: !ruby/object:Gem::Requirement
121
124
  requirements:
122
- - - "~>"
125
+ - - ">="
123
126
  - !ruby/object:Gem::Version
124
127
  version: '4.2'
128
+ - - "<"
129
+ - !ruby/object:Gem::Version
130
+ version: '6.0'
125
131
  - !ruby/object:Gem::Dependency
126
132
  name: redcarpet
127
133
  requirement: !ruby/object:Gem::Requirement