lib/validate_website/core.rb
# frozen_string_literal: true
require 'set'
require 'open-uri'
require 'webrick/cookie'
require 'validate_website/option_parser'
require 'validate_website/validator'
require 'validate_website/colorful_messages'
require 'spidr'
require 'crass'
# Base module ValidateWebsite
module ValidateWebsite
autoload :Crawl, 'validate_website/crawl'
autoload :Static, 'validate_website/static'
autoload :StaticLink, 'validate_website/static_link'
# Core class for static or website validation
class Core
attr_accessor :site
attr_reader :options, :host, :errors_count, :not_founds_count
include ColorfulMessages
EXIT_SUCCESS = 0
EXIT_FAILURE_MARKUP = 64
EXIT_FAILURE_NOT_FOUND = 65
EXIT_FAILURE_MARKUP_NOT_FOUND = 66
START_MESSAGE = 'Validating'
# Initialize core ValidateWebsite class
# @example
# new({ site: "https://example.com/" }, :crawl)
# @param [Hash] options
# @param [Symbol] validation_type `crawl` for web or `static` for local
# @return [NilClass]
def initialize(options, validation_type)
@not_founds_count = 0
@errors_count = 0
@options = Parser.parse(options, validation_type).to_h
@site = @options[:site]
@service_url = @options[:html5_validator_service_url]
Validator.html5_validator_service_url = @service_url if @service_url
end
def errors?
@errors_count.positive?
end
def not_founds?
@not_founds_count.positive?
end
def exit_status
if errors? && not_founds?
EXIT_FAILURE_MARKUP_NOT_FOUND
elsif errors?
EXIT_FAILURE_MARKUP
elsif not_founds?
EXIT_FAILURE_NOT_FOUND
else
EXIT_SUCCESS
end
end
def default_cookies
WEBrick::Cookie.parse(@options[:cookies]).each_with_object({}) do |c, h|
h[c.name] = c.value
h
end
end
private
def start_message(type)
puts color(:note, "#{START_MESSAGE} #{type}\n", @options[:color])
end
def check_css_syntax(page)
nodes = Crass::Parser.parse_stylesheet(page.body)
return unless any_css_errors?(nodes)
handle_validation_error(page.url)
end
def any_css_errors?(nodes)
nodes.any? do |node|
if node[:children]
any_css_errors? node.delete(:children)
elsif node[:tokens]
any_css_errors? node.delete(:tokens)
else
node[:node] == :error || node[:error] == true
end
end
end
def print_status_line(total, failures, not_founds, errors)
puts "\n\n"
puts color(:info, ["#{total} visited",
"#{failures} failures",
"#{not_founds} not founds",
"#{errors} errors"].join(', '), options[:color])
end
def not_found_error(location)
puts "\n"
puts color(:error, "#{location} linked but not exist", options[:color])
@not_founds_count += 1
end
##
# @param [Nokogiri::HTML::Document] original_doc
# @param [String] The raw HTTP response body of the page
# @param [String] url
# @param [Hash] Validator options
#
def validate(doc, body, url, options)
validator = Validator.new(doc, body, **options)
if validator.valid?
print color(:success, '.', options[:color]) # rspec style
else
handle_html_validation_error(validator, url)
end
end
def handle_html_validation_error(validator, url)
handle_validation_error(url)
return unless options[:verbose]
puts color(:error, validator.errors.join(', '), options[:color])
end
def handle_validation_error(url)
@errors_count += 1
puts "\n"
puts color(:error, "* #{url}", options[:color])
end
end
end