Skip to content

Commit cd89a8a

Browse files
committed
Merge branch 'master' into fix-recheck-failure
2 parents 5550450 + 856f147 commit cd89a8a

19 files changed

+78
-28
lines changed

.travis.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
language: ruby
22
rvm:
3-
- 2.3.6
43
- 2.4.3
54
- 2.5.0
65
- 2.6.0

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,9 @@ You can pass in additional options to configure this validation.
321321

322322
| Option | Description | Default |
323323
| :----- | :---------- | :------ |
324+
| `report_eof_tags` | When `check_html` is enabled, HTML markup with mismatched tags are reported as errors | `false`
324325
| `report_invalid_tags` | When `check_html` is enabled, HTML markup that is unknown to Nokogumbo are reported as errors. | `false`
326+
| `report_mismatched_tags` | When `check_html` is enabled, HTML markup with tags that are malformed are reported as errors | `false`
325327
| `report_missing_doctype` | When `check_html` is enabled, HTML markup with missing or out-of-order `DOCTYPE` are reported as errors. | `false`
326328
| `report_missing_names` | When `check_html` is enabled, HTML markup that are missing entity names are reported as errors. | `false`
327329
| `report_script_embeds` | When `check_html` is enabled, `script` tags containing markup are reported as errors. | `false`

Rakefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ RuboCop::RakeTask.new(:rubocop)
1313

1414
task default: %i[spec proof_readme]
1515

16+
task :test do
17+
Rake::Task['spec'].invoke
18+
end
19+
1620
task :proof_readme do
1721
require 'html-proofer'
1822
require 'redcarpet'

bin/htmlproofer

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ Mercenary.program(:htmlproofer) do |p|
4141
p.option 'report_missing_names', '--report-missing-names', 'When `check_html` is enabled, HTML markup that are missing entity names are reported as errors (default: `false`)'
4242
p.option 'report_script_embeds', '--report-script-embeds', 'When `check_html` is enabled, `script` tags containing markup are reported as errors (default: `false`)'
4343
p.option 'report_missing_doctype', '--report-missing-doctype', 'When `check_html` is enabled, HTML markup with missing or out-of-order `DOCTYPE` are reported as errors (default: `false`)'
44+
p.option 'report_eof_tags', '--report-eof-tags', 'When `check_html` is enabled, HTML markup with tags that are malformed are reported as errors (default: `false`)'
45+
p.option 'report_mismatched_tags', '--report-mismatched-tags', 'When `check_html` is enabled, HTML markup with mismatched tags are reported as errors (default: `false`)'
4446
p.option 'log_level', '--log-level <level>', String, 'Sets the logging level, as determined by Yell. One of `:debug`, `:info`, `:warn`, `:error`, or `:fatal`. (default: `:info`)'
4547
p.option 'only_4xx', '--only-4xx', 'Only reports errors for links that fall within the 4xx status code range'
4648
p.option 'storage_dir', '--storage-dir PATH', String, 'Directory where to store the cache log (default: "tmp/.htmlproofer")'
@@ -82,6 +84,8 @@ Mercenary.program(:htmlproofer) do |p|
8284
options[:validation][:report_missing_names] = opts['report_missing_names'] unless opts['report_missing_names'].nil?
8385
options[:validation][:report_invalid_tags] = opts['report_invalid_tags'] unless opts['report_invalid_tags'].nil?
8486
options[:validation][:report_missing_doctype] = opts['report_missing_doctype'] unless opts['report_missing_doctype'].nil?
87+
options[:validation][:report_eof_tags] = opts['report_eof_tags'] unless opts['report_eof_tags'].nil?
88+
options[:validation][:report_mismatched_tags] = opts['report_mismatched_tags'] unless opts['report_mismatched_tags'].nil?
8589

8690
options[:typhoeus] = HTMLProofer::Configuration.parse_json_option('typhoeus_config', opts['typhoeus_config']) unless opts['typhoeus_config'].nil?
8791

lib/html-proofer/check.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,19 @@ module HTMLProofer
55
class Check
66
attr_reader :node, :html, :element, :src, :path, :options, :issues, :external_urls
77

8-
def initialize(src, path, html, options)
8+
def initialize(src, path, html, logger, options)
99
@src = src
1010
@path = path
1111
@html = remove_ignored(html)
12+
@logger = logger
1213
@options = options
1314
@issues = []
1415
@external_urls = {}
1516
end
1617

1718
def create_element(node)
1819
@node = node
19-
Element.new(node, self)
20+
Element.new(node, self, @logger)
2021
end
2122

2223
def run

lib/html-proofer/check/html.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ class HtmlCheck < ::HTMLProofer::Check
66
INVALID_TAG_MSG = /Tag ([\w\-:]+) invalid/.freeze
77
INVALID_PREFIX = /Namespace prefix/.freeze
88
PARSE_ENTITY_REF = /htmlParseEntityRef: no name/.freeze
9-
DOCTYPE_MSG = /The doctype must be the first token in the document/.freeze
9+
DOCTYPE_MSG = /Expected a doctype token/.freeze
10+
EOF_IN_TAG = /End of input in tag/.freeze
11+
MISMATCHED_TAGS = /That tag isn't allowed here/.freeze
1012

1113
def run
1214
@html.errors.each do |error|
@@ -24,6 +26,10 @@ def report?(message)
2426
options[:validation][:report_missing_names]
2527
when DOCTYPE_MSG
2628
options[:validation][:report_missing_doctype]
29+
when EOF_IN_TAG
30+
options[:validation][:report_eof_tags]
31+
when MISMATCHED_TAGS
32+
options[:validation][:report_mismatched_tags]
2733
else
2834
true
2935
end

lib/html-proofer/check/opengraph.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
class OpenGraphElement < ::HTMLProofer::Element
44
attr_reader :src
55

6-
def initialize(obj, check)
7-
super(obj, check)
6+
def initialize(obj, check, logger)
7+
super(obj, check, logger)
88
# Fake up src from the content attribute
99
instance_variable_set('@src', @content)
1010

@@ -23,7 +23,7 @@ def empty_src?
2323

2424
def run
2525
@html.css('meta[property="og:url"], meta[property="og:image"]').each do |m|
26-
@opengraph = OpenGraphElement.new(m, self)
26+
@opengraph = OpenGraphElement.new(m, self, @logger)
2727

2828
next if @opengraph.ignore?
2929

lib/html-proofer/configuration.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ module Configuration
5252
report_script_embeds: false,
5353
report_missing_names: false,
5454
report_invalid_tags: false,
55-
report_missing_doctype: false
55+
report_missing_doctype: false,
56+
report_eof_tags: false,
57+
report_mismatched_tags: false
5658
}.freeze
5759

5860
CACHE_DEFAULTS = {}.freeze

lib/html-proofer/element.rb

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,18 @@ class Element
1010

1111
attr_reader :id, :name, :alt, :href, :link, :src, :line, :data_proofer_ignore
1212

13-
def initialize(obj, check)
13+
def initialize(obj, check, logger)
14+
@logger = logger
1415
# Construct readable ivars for every element
15-
obj.attributes.each_pair do |attribute, value|
16-
name = attribute.tr('-:.', '_').to_s.to_sym
17-
(class << self; self; end).send(:attr_reader, name)
18-
instance_variable_set("@#{name}", value.value)
16+
begin
17+
obj.attributes.each_pair do |attribute, value|
18+
name = attribute.tr('-:.;', '_').to_s.to_sym
19+
(class << self; self; end).send(:attr_reader, name)
20+
instance_variable_set("@#{name}", value.value)
21+
end
22+
rescue NameError => e
23+
@logger.log :error, "Attribute set `#{obj}` contains an error!"
24+
raise e
1925
end
2026

2127
@aria_hidden = defined?(@aria_hidden) && @aria_hidden == 'true' ? true : false

lib/html-proofer/middleware.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ def self.options
2121
allow_hash_href: true,
2222
check_external_hash: true,
2323
check_html: true,
24-
url_ignore: [/.*/] # Don't try to check local files exist
24+
url_ignore: [/.*/], # Don't try to check if local files exist
25+
validation: { report_eof_tags: true }
2526
}
2627
end
2728

lib/html-proofer/runner.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ def check_parsed(html, path)
100100
@src.each do |src|
101101
checks.each do |klass|
102102
@logger.log :debug, "Checking #{klass.to_s.downcase} on #{path} ..."
103-
check = Object.const_get(klass).new(src, path, html, @options)
103+
check = Object.const_get(klass).new(src, path, html, @logger, @options)
104104
check.run
105105
external_urls = check.external_urls
106106
external_urls = Hash[check.external_urls.map { |url, file| [swap(url, @options[:url_swap]), file] }] if @options[:url_swap]
@@ -147,6 +147,8 @@ def ignore_file?(file)
147147
def checks
148148
return @checks if defined?(@checks) && !@checks.nil?
149149

150+
return (@checks = ['LinkCheck']) if @type == :links
151+
150152
@checks = HTMLProofer::Check.subchecks.map(&:name)
151153
@checks.delete('FaviconCheck') unless @options[:check_favicon]
152154
@checks.delete('HtmlCheck') unless @options[:check_html]

lib/html-proofer/utils.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def create_nokogiri(path)
1515
path
1616
end
1717

18-
Nokogiri::HTML5(content)
18+
Nokogiri::HTML5(content, max_errors: -1)
1919
end
2020

2121
def swap(href, replacement)

lib/html-proofer/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# frozen_string_literal: true
22

33
module HTMLProofer
4-
VERSION = '3.15.1'
4+
VERSION = '3.15.2'
55
end

spec/html-proofer/command_spec.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,9 @@
8989
end
9090

9191
it 'works with check-html' do
92-
broken = "#{FIXTURES_DIR}/html/unmatched_end_tag.html"
93-
output = make_bin('--check-html --report-invalid-tags', broken)
94-
expect(output).to match('HTML-Proofer finished successfully')
92+
broken = "#{FIXTURES_DIR}/html/missing_closing_quotes.html"
93+
output = make_bin('--check-html --report-eof-tags', broken)
94+
expect(output).to match('1 failure')
9595
end
9696

9797
it 'works with empty-alt-ignore' do

spec/html-proofer/element_spec.rb

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,55 +4,55 @@
44

55
describe HTMLProofer::Element do
66
before(:each) do
7-
@check = HTMLProofer::Check.new('', '', Nokogiri::HTML5(''), HTMLProofer::Configuration::PROOFER_DEFAULTS)
7+
@check = HTMLProofer::Check.new('', '', Nokogiri::HTML5(''), nil, HTMLProofer::Configuration::PROOFER_DEFAULTS)
88
end
99

1010
describe '#initialize' do
1111
it 'accepts the xmlns attribute' do
1212
nokogiri = Nokogiri::HTML5('<a xmlns:cc="http://creativecommons.org/ns#">Creative Commons</a>')
13-
checkable = HTMLProofer::Element.new(nokogiri.css('a').first, @check)
13+
checkable = HTMLProofer::Element.new(nokogiri.css('a').first, @check, nil)
1414
expect(checkable.instance_variable_get(:@xmlns_cc)).to eq 'http://creativecommons.org/ns#'
1515
end
1616

1717
it 'assignes the text node' do
1818
nokogiri = Nokogiri::HTML5('<p>One')
19-
checkable = HTMLProofer::Element.new(nokogiri.css('p').first, @check)
19+
checkable = HTMLProofer::Element.new(nokogiri.css('p').first, @check, nil)
2020
expect(checkable.instance_variable_get(:@text)).to eq 'One'
2121
end
2222

2323
it 'accepts the content attribute' do
2424
nokogiri = Nokogiri::HTML5('<meta name="twitter:card" content="summary">')
25-
checkable = HTMLProofer::Element.new(nokogiri.css('meta').first, @check)
25+
checkable = HTMLProofer::Element.new(nokogiri.css('meta').first, @check, nil)
2626
expect(checkable.instance_variable_get(:@content)).to eq 'summary'
2727
end
2828
end
2929

3030
describe '#ignores_pattern_check' do
3131
it 'works for regex patterns' do
3232
nokogiri = Nokogiri::HTML5('<script src=/assets/main.js></script>')
33-
checkable = HTMLProofer::Element.new(nokogiri.css('script').first, @check)
33+
checkable = HTMLProofer::Element.new(nokogiri.css('script').first, @check, nil)
3434
expect(checkable.ignores_pattern_check([%r{\/assets\/.*(js|css|png|svg)}])).to eq true
3535
end
3636

3737
it 'works for string patterns' do
3838
nokogiri = Nokogiri::HTML5('<script src=/assets/main.js></script>')
39-
checkable = HTMLProofer::Element.new(nokogiri.css('script').first, @check)
39+
checkable = HTMLProofer::Element.new(nokogiri.css('script').first, @check, nil)
4040
expect(checkable.ignores_pattern_check(['/assets/main.js'])).to eq true
4141
end
4242
end
4343

4444
describe '#url' do
4545
it 'works for src attributes' do
4646
nokogiri = Nokogiri::HTML5('<img src=image.png />')
47-
checkable = HTMLProofer::Element.new(nokogiri.css('img').first, @check)
47+
checkable = HTMLProofer::Element.new(nokogiri.css('img').first, @check, nil)
4848
expect(checkable.url).to eq 'image.png'
4949
end
5050
end
5151

5252
describe '#ignore' do
5353
it 'works for twitter cards' do
5454
nokogiri = Nokogiri::HTML5('<meta name="twitter:url" data-proofer-ignore content="http://example.com/soon-to-be-published-url">')
55-
checkable = HTMLProofer::Element.new(nokogiri.css('meta').first, @check)
55+
checkable = HTMLProofer::Element.new(nokogiri.css('meta').first, @check, nil)
5656
expect(checkable.ignore?).to eq true
5757
end
5858
end
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<!DOCTYPE html><html><!-- -- --></a>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<img
2+
class="img-fluid"
3+
src="./gpl.png"
4+
alt="Frank Blank"
5+
;
6+
width="365"
7+
;
8+
height="365"
9+
/><br />

spec/html-proofer/html_spec.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,4 +124,11 @@
124124
proofer = run_proofer(file, :file, opts)
125125
expect(proofer.failed_tests).to eq []
126126
end
127+
128+
it 'reports failures' do
129+
opts = { check_html: true, validation: { report_mismatched_tags: true } }
130+
file = "#{FIXTURES_DIR}/html/parse_failure.html"
131+
proofer = run_proofer(file, :file, opts)
132+
expect(proofer.failed_tests.first).to match(/ERROR: That tag isn't allowed here/)
133+
end
127134
end

spec/html-proofer/images_spec.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,4 +201,10 @@
201201
proofer = run_proofer(relative_images, :file)
202202
expect(proofer.failed_tests).to eq []
203203
end
204+
205+
it 'ignores semicolon outside attribute name' do
206+
relative_images = "#{FIXTURES_DIR}/images/semicolon.html"
207+
proofer = run_proofer(relative_images, :file)
208+
expect(proofer.failed_tests).to eq []
209+
end
204210
end

0 commit comments

Comments
 (0)