validate-website 1.9.1 → 1.11.1

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
  SHA256:
3
- metadata.gz: 60082f1dc222de92a3465b0487e6047597d7605fd2199e15f246a5930ddd5ea3
4
- data.tar.gz: 1fd7bd74bc0b58bbb16e82ae396309db5638362f6f9853d80161849299ff28d8
3
+ metadata.gz: 7208a9c728f7798aecc7a10bec8a3537940a6857e3eb4f6612efa551f2871a94
4
+ data.tar.gz: 25e5112b42c14a6ed86f0271fba1bb9ada63c1d92cc75414a227716289e241f8
5
5
  SHA512:
6
- metadata.gz: 3ab5fa6da0d050fc39acabdd4cb26a764acfdb609df4786cb22f55af5d2f500e0638a55e67505cb1d6e1595e0c04ede5ad4ed88b46bf078bc09f58585b7f481c
7
- data.tar.gz: '0199501f535de09d55bc9a8f28549f4c01a94d9444f12732ad02fc503e36158daa1535a61e9b349ea462eb4799bebb5a599417e93dbe2b0abd92b0e0319abb28'
6
+ metadata.gz: 95962fe71e144cc5c8f244e1960556e56c9956bdcd5852e194532ee16b40dfbda5ba39db75169651ddd4048afc79311fdee2aa1087dddc3388aaa894c4dc27fe
7
+ data.tar.gz: 6a6e8185f8a359e0482c0ef5893b28d307a31be560a2e83bfd19f88f042cfbd3ec37e244f602e5ea4a6876afce9b8d2a38f98f645452168b752c03ee62fdc70d
data/History.md CHANGED
@@ -1,4 +1,48 @@
1
1
 
2
+ 1.11.1 / 2021-01-10
3
+ ===================
4
+
5
+ * Add nokogumbo doc
6
+ * nokogumbo support for ruby engine
7
+ * Add support for nokogumbo
8
+ * Add jruby to github actions
9
+ * Merge pull request #24 from @marocchino / patch-1
10
+ * Some minor improvements
11
+ * Remove travis ci
12
+ * Init github actions ci
13
+
14
+ 1.11.0 / 2021-01-08
15
+ ===================
16
+
17
+ * Merge pull request #23 from @marocchino / ruby-3-support
18
+ * Use webrick's escape instead of encode_www_form_component
19
+ * Support ruby 3
20
+ * Fix doc for ValidateWebsite::Core initialize
21
+ * Switch to gitlab ci and remove 2.{3,4} support
22
+ * Update rubocop to 0.76.0
23
+
24
+ 1.10.0 / 2020-07-03
25
+ ==================
26
+
27
+ * Fix build for Ruby 2.3 and 2.4
28
+ * Remove rbx-3 from build
29
+ * Remove minitest-focus and fix minitest 6 warnings
30
+ * Fix html5_validator option and change html5_validator_service_url
31
+ * Add Ruby 2.7 to CI and update jruby
32
+ * Update rubocop and fix offences
33
+ * Remove Ruby 2.2 support and update rubocop
34
+
35
+ 1.9.3 / 2019-04-11
36
+ ==================
37
+
38
+ * Update tidy_ffi to 1.0
39
+ * Avoid testing tidy bug with js
40
+
41
+ 1.9.2 / 2019-03-09
42
+ ==================
43
+
44
+ * Load schema when needed instead of boot
45
+
2
46
  1.9.1 / 2019-03-05
3
47
  ==================
4
48
 
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License
2
2
 
3
- Copyright (c) 2009-2019 Laurent Arnoud <laurent@spkdev.net>
3
+ Copyright (c) 2009-2021 Laurent Arnoud <laurent@spkdev.net>
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining
6
6
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -95,6 +95,11 @@ If the libtidy5 is found on your system this will be the default to validate
95
95
  your html5 document. This does not depend on a tier service everything is done
96
96
  locally.
97
97
 
98
+ #### Nokogumbo
99
+
100
+ Nokogumbo can validate html5 document without tier service but reports less
101
+ errors than tidy.
102
+
98
103
  #### Validator.nu web service
99
104
 
100
105
  When `--html5-validator nu` option is used HTML5 support is done by using the
@@ -145,12 +150,12 @@ See [GitHub](https://github.com/spk/validate-website/graphs/contributors).
145
150
 
146
151
  The MIT License
147
152
 
148
- Copyright (c) 2009-2019 Laurent Arnoud <laurent@spkdev.net>
153
+ Copyright (c) 2009-2021 Laurent Arnoud <laurent@spkdev.net>
149
154
 
150
155
  ---
151
- [![Build](https://img.shields.io/travis/spk/validate-website.svg)](https://travis-ci.org/spk/validate-website)
156
+ [![Build](https://img.shields.io/gitlab/pipeline/spkdev/validate-website/master)](https://gitlab.com/spkdev/validate-website/-/commits/master)
157
+ [![Coverage](https://gitlab.com/spkdev/validate-website/badges/master/coverage.svg)](https://gitlab.com/spkdev/validate-website/-/commits/master)
152
158
  [![Version](https://img.shields.io/gem/v/validate-website.svg)](https://rubygems.org/gems/validate-website)
153
159
  [![Documentation](https://img.shields.io/badge/doc-rubydoc-blue.svg)](http://www.rubydoc.info/gems/validate-website)
154
160
  [![License](https://img.shields.io/badge/license-MIT-blue.svg)](http://opensource.org/licenses/MIT "MIT")
155
- [![Coverage Status](https://img.shields.io/coveralls/github/spk/validate-website.svg)](https://coveralls.io/github/spk/validate-website?branch=master)
156
161
  [![Inline docs](https://inch-ci.org/github/spk/validate-website.svg?branch=master)](http://inch-ci.org/github/spk/validate-website)
data/Rakefile CHANGED
@@ -1,9 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rake/testtask'
2
4
  require 'rubocop/rake_task'
3
5
  require 'asciidoctor'
4
6
 
5
- default = %i[test]
6
- default << :rubocop unless RUBY_ENGINE == 'rbx'
7
+ default = %i[test rubocop]
7
8
  task default: default
8
9
 
9
10
  desc 'Update manpage from asciidoc file'
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'validate_website/runner'
4
5
  exit_status = ValidateWebsite::Runner.run_crawl(ARGV)
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'validate_website/runner'
4
5
  exit_status = ValidateWebsite::Runner.run_static(ARGV)
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'validate_website/core'
2
4
  require 'validate_website/version'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'paint'
2
4
 
3
5
  module ValidateWebsite
@@ -5,6 +7,7 @@ module ValidateWebsite
5
7
  module ColorfulMessages
6
8
  def color(type, message, colored = true)
7
9
  return message unless colored
10
+
8
11
  send(type, message)
9
12
  end
10
13
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'set'
2
4
  require 'open-uri'
3
5
  require 'webrick/cookie'
@@ -26,12 +28,13 @@ module ValidateWebsite
26
28
  EXIT_FAILURE_MARKUP = 64
27
29
  EXIT_FAILURE_NOT_FOUND = 65
28
30
  EXIT_FAILURE_MARKUP_NOT_FOUND = 66
29
- START_MESSAGE = 'Validating'.freeze
31
+ START_MESSAGE = 'Validating'
30
32
 
31
33
  # Initialize core ValidateWebsite class
32
34
  # @example
33
35
  # new({ site: "https://example.com/" }, :crawl)
34
36
  # @param [Hash] options
37
+ # @param [Symbol] validation_type `crawl` for web or `static` for local
35
38
  # @return [NilClass]
36
39
  def initialize(options, validation_type)
37
40
  @not_founds_count = 0
@@ -43,11 +46,11 @@ module ValidateWebsite
43
46
  end
44
47
 
45
48
  def errors?
46
- @errors_count > 0
49
+ @errors_count.positive?
47
50
  end
48
51
 
49
52
  def not_founds?
50
- @not_founds_count > 0
53
+ @not_founds_count.positive?
51
54
  end
52
55
 
53
56
  def exit_status
@@ -78,6 +81,7 @@ module ValidateWebsite
78
81
  def check_css_syntax(page)
79
82
  nodes = Crass::Parser.parse_stylesheet(page.body)
80
83
  return unless any_css_errors?(nodes)
84
+
81
85
  handle_validation_error(page.url)
82
86
  end
83
87
 
@@ -111,10 +115,10 @@ module ValidateWebsite
111
115
  # @param [Nokogiri::HTML::Document] original_doc
112
116
  # @param [String] The raw HTTP response body of the page
113
117
  # @param [String] url
114
- # @param [Regexp] Errors to ignore
118
+ # @param [Hash] Validator options
115
119
  #
116
- def validate(doc, body, url, ignore = nil)
117
- validator = Validator.new(doc, body, ignore: ignore)
120
+ def validate(doc, body, url, options)
121
+ validator = Validator.new(doc, body, **options)
118
122
  if validator.valid?
119
123
  print color(:success, '.', options[:color]) # rspec style
120
124
  else
@@ -125,6 +129,7 @@ module ValidateWebsite
125
129
  def handle_html_validation_error(validator, url)
126
130
  handle_validation_error(url)
127
131
  return unless options[:verbose]
132
+
128
133
  puts color(:error, validator.errors.join(', '), options[:color])
129
134
  end
130
135
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'validate_website/core'
2
4
  require 'validate_website/utils'
3
5
 
@@ -41,9 +43,10 @@ module ValidateWebsite
41
43
  #
42
44
  def extract_imgs_from_page(page)
43
45
  return Set[] if page.is_redirect?
46
+
44
47
  page.doc.search('//img[@src]').reduce(Set[]) do |result, elem|
45
48
  u = elem.attributes['src'].content
46
- result << page.to_absolute(URI.parse(URI.encode(u)))
49
+ result << page.to_absolute(URI.parse(WEBrick::HTTPUtils.escape(u)))
47
50
  end
48
51
  end
49
52
 
@@ -77,7 +80,10 @@ module ValidateWebsite
77
80
  end
78
81
 
79
82
  if validate?(page)
80
- validate(page.doc, page.body, page.url, options[:ignore])
83
+ keys = %i[ignore html5_validator]
84
+ # slice does not exists on Ruby <= 2.4
85
+ slice = Hash[[keys, options.values_at(*keys)].transpose]
86
+ validate(page.doc, page.body, page.url, slice)
81
87
  end
82
88
  end
83
89
  end
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'slop'
4
+ require File.expand_path('version', __dir__)
2
5
 
3
6
  module ValidateWebsite
4
7
  # Internal class for parse command line args
@@ -28,6 +31,7 @@ module ValidateWebsite
28
31
  # Generic parse method for crawl or static options
29
32
  def self.parse(options, type)
30
33
  raise ArgumentError unless VALID_TYPES.include?(type)
34
+
31
35
  # We are in command line (ARGV)
32
36
  if options.is_a?(Array)
33
37
  send("command_line_parse_#{type}", options)
@@ -52,7 +56,7 @@ module ValidateWebsite
52
56
  opt.regexp('-i', '--ignore',
53
57
  'Validation errors to ignore (ex: "valign|autocorrect")')
54
58
  opt.string('-x', '--html5-validator',
55
- 'Change default html5 validator engine (ex: tidy or nu)',
59
+ 'Change default html5 validator engine (tidy/nu/nokogumbo)',
56
60
  default: DEFAULT_OPTIONS[:html5_validator])
57
61
  opt.string('-5', '--html5-validator-service-url',
58
62
  'Change default html5 validator service URL for "nu" engine')
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'validate_website/core'
2
4
 
3
5
  module ValidateWebsite
@@ -5,7 +7,7 @@ module ValidateWebsite
5
7
  class Runner
6
8
  def self.trap_interrupt
7
9
  trap('INT') do
8
- STDERR.puts "\nExiting..."
10
+ warn "\nExiting..."
9
11
  exit!(1)
10
12
  end
11
13
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'validate_website/core'
2
4
  require 'validate_website/utils'
3
5
 
@@ -5,7 +7,7 @@ module ValidateWebsite
5
7
  # Class for validation Static website
6
8
  class Static < Core
7
9
  CONTENT_TYPES = ['text/html', 'text/xhtml+xml'].freeze
8
- START_MESSAGE_TYPE = 'files'.freeze
10
+ START_MESSAGE_TYPE = 'files'
9
11
 
10
12
  attr_reader :history_count
11
13
 
@@ -24,7 +26,8 @@ module ValidateWebsite
24
26
  files = Dir.glob(@options[:pattern])
25
27
  files.each do |file|
26
28
  next unless File.file?(file)
27
- next if @options[:exclude] && @options[:exclude].match(file)
29
+ next if @options[:exclude]&.match(file)
30
+
28
31
  @history_count += 1
29
32
  check_static_file(file)
30
33
  end
@@ -57,7 +60,10 @@ module ValidateWebsite
57
60
 
58
61
  def check_page(file, page)
59
62
  if page.html? && options[:markup]
60
- validate(page.doc, page.body, file, options[:ignore])
63
+ keys = %i[ignore html5_validator]
64
+ # slice does not exists on Ruby <= 2.4
65
+ slice = Hash[[keys, options.values_at(*keys)].transpose]
66
+ validate(page.doc, page.body, file, slice)
61
67
  end
62
68
  check_static_not_found(page.links) if options[:not_found]
63
69
  end
@@ -68,11 +74,13 @@ module ValidateWebsite
68
74
  static_links = links.map { |l| StaticLink.new(l, @site) }
69
75
  static_links.each do |static_link|
70
76
  next unless static_link.check?
77
+
71
78
  unless File.exist?(static_link.file_path)
72
79
  not_found_error(static_link.file_path)
73
80
  next
74
81
  end
75
82
  next unless static_link.css?
83
+
76
84
  check_static_not_found static_link.extract_urls_from_fake_css_response
77
85
  end
78
86
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'uri'
2
4
  require 'validate_website/utils'
3
5
  require 'validate_website/static'
@@ -6,7 +8,7 @@ require 'spidr'
6
8
  # rubocop:disable Metrics/BlockLength
7
9
  StaticLink = Struct.new(:link, :site) do
8
10
  def link_uri
9
- @link_uri = URI.parse(URI.encode(link))
11
+ @link_uri = URI.parse(WEBrick::HTTPUtils.escape(link))
10
12
  @link_uri = URI.join(site, @link_uri) if @link_uri.host.nil?
11
13
  @link_uri
12
14
  end
@@ -25,9 +27,9 @@ StaticLink = Struct.new(:link, :site) do
25
27
 
26
28
  def body
27
29
  if File.exist?(link)
28
- open(link).read
30
+ File.open(link).read
29
31
  else
30
- open(file_path).read
32
+ File.open(file_path).read
31
33
  end
32
34
  end
33
35
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Base module ValidateWebsite
2
4
  module ValidateWebsite
3
5
  # Utils class for CSS helpers
@@ -10,6 +12,7 @@ module ValidateWebsite
10
12
  def self.extract_urls_from_css(page)
11
13
  return Set[] unless page
12
14
  return Set[] if page.body.nil?
15
+
13
16
  nodes = Crass::Parser.parse_stylesheet(page.body)
14
17
  extract_urls_from_nodes nodes, page
15
18
  end
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'uri'
2
4
 
3
- require 'nokogiri'
5
+ require 'nokogumbo' unless ValidateWebsite.jruby?
4
6
  require 'w3c_validators'
5
7
 
6
8
  require 'validate_website/validator_class_methods'
@@ -10,27 +12,25 @@ module ValidateWebsite
10
12
  class Validator
11
13
  extend ValidatorClassMethods
12
14
 
13
- @html5_validator_service_url = 'https://checker.html5.org/'
15
+ @html5_validator_service_url = 'https://validator.nu/'
16
+ XHTML_SCHEMA_PATH = File.expand_path('../../data/schemas', __dir__)
17
+ @mutex = Mutex.new
18
+
14
19
  class << self
15
20
  attr_accessor :html5_validator_service_url
16
- end
17
-
18
- XHTML_PATH = File.expand_path('../../data/schemas', __dir__)
19
21
 
20
- @xsd_schemas ||= {}
21
-
22
- # `Dir.chdir` is needed by `Nokogiri::XML::Schema` to validate with local
23
- # files and cannot use file absolute path.
24
- Dir.glob(File.join(XHTML_PATH, '*.xsd')).each do |schema|
25
- Dir.chdir(XHTML_PATH) do
26
- schema_name = File.basename(schema, '.xsd')
27
- schema_content = File.read(File.basename(schema))
28
- begin
29
- @xsd_schemas[schema_name] = Nokogiri::XML::Schema(schema_content)
30
- rescue Nokogiri::XML::SyntaxError
31
- STDERR.puts "XSD SCHEMA: #{schema} cannot be loaded"
22
+ # http://www.w3.org/TR/xhtml1-schema/
23
+ def schema(namespace)
24
+ @mutex.synchronize do
25
+ Dir.chdir(XHTML_SCHEMA_PATH) do
26
+ if File.exist?("#{namespace}.xsd")
27
+ Nokogiri::XML::Schema(File.read("#{namespace}.xsd"))
28
+ end
29
+ end
32
30
  end
33
31
  end
32
+
33
+ alias xsd schema
34
34
  end
35
35
 
36
36
  attr_reader :original_doc, :body, :dtd, :doc, :namespace, :html5_validator
@@ -65,25 +65,22 @@ module ValidateWebsite
65
65
  @ignore ? @errors.reject { |e| @ignore =~ e } : @errors
66
66
  end
67
67
 
68
- # http://www.w3.org/TR/xhtml1-schema/
69
- def self.xsd(namespace)
70
- return unless namespace
71
- @xsd_schemas[namespace] if @xsd_schemas.key? namespace
72
- end
73
-
74
68
  private
75
69
 
76
70
  # http://www.w3.org/TR/xhtml1/#dtds
77
71
  def find_namespace(dtd)
78
72
  return unless dtd.system_id
73
+
79
74
  dtd_uri = URI.parse(dtd.system_id)
80
75
  return unless dtd_uri.path
76
+
81
77
  @dtd_uri = dtd_uri
82
78
  File.basename(@dtd_uri.path, '.dtd')
83
79
  end
84
80
 
85
81
  def document
86
82
  return @document if @document
83
+
87
84
  @document = if @dtd_uri && @body.match(@dtd_uri.to_s)
88
85
  @body.sub(@dtd_uri.to_s, @namespace + '.dtd')
89
86
  else
@@ -95,11 +92,11 @@ module ValidateWebsite
95
92
  def validate
96
93
  if document =~ /^\<!DOCTYPE html\>/i
97
94
  html5_validate
98
- elsif self.class.xsd(@namespace)
99
- self.class.xsd(@namespace).validate(xhtml_doc)
95
+ elsif self.class.schema(@namespace)
96
+ self.class.schema(@namespace).validate(xhtml_doc)
100
97
  else
101
98
  # dont have xsd fall back to dtd
102
- Dir.chdir(XHTML_PATH) do
99
+ Dir.chdir(XHTML_SCHEMA_PATH) do
103
100
  Nokogiri::HTML.parse(document)
104
101
  end.errors
105
102
  end
@@ -115,8 +112,10 @@ module ValidateWebsite
115
112
  def html5_validate
116
113
  if html5_validator.to_sym == :tidy && self.class.tidy
117
114
  tidy_validate
118
- else
115
+ elsif html5_validator.to_sym == :nu
119
116
  nu_validate
117
+ else
118
+ Nokogiri::HTML5(document, max_errors: -1).errors
120
119
  end
121
120
  end
122
121
 
@@ -138,7 +137,7 @@ module ValidateWebsite
138
137
  end
139
138
 
140
139
  def xhtml_doc
141
- Dir.chdir(XHTML_PATH) do
140
+ Dir.chdir(XHTML_SCHEMA_PATH) do
142
141
  Nokogiri::XML(document) { |cfg| cfg.nonoent.dtdload.dtdvalid.nonet }
143
142
  end
144
143
  end