module HTML
class Proofer
class Checkable
def initialize(obj, type, check)
@src = obj['src']
@href = obj['href']
@alt = obj['alt']
@name = obj['name']
@id = obj['id']
@rel = obj['rel']
@data_ignore_proofer = obj['data-proofer-ignore']
@content = obj.content
@check = check
@checked_paths = {}
@type = type
if @href && @check.options[:href_swap]
@check.options[:href_swap].each do |link, replace|
@href = @href.gsub(link, replace)
end
end
# fix up missing protocols
@href.insert 0, "http:" if @href =~ /^\/\//
@src.insert 0, "http:" if @src =~ /^\/\//
end
def url
@src || @href || ""
end
def valid?
begin
URI.parse url
rescue
false
end
end
def parts
URI.parse url
end
def path
parts.path
end
def hash
parts.fragment
end
# path is to an external server
def remote?
uri = URI.parse url
%w( http https ).include?(uri.scheme)
rescue URI::BadURIError
false
rescue URI::InvalidURIError
false
end
def ignore?
return true if @data_ignore_proofer
case @type
when "favicon"
return true if url.match(/^data:image/)
when "link"
return true if ignores_pattern_check(@check.additional_href_ignores)
when "image"
return true if url.match(/^data:image/)
return true if ignores_pattern_check(@check.additional_alt_ignores)
end
uri = URI.parse url
%w( mailto tel ).include?(uri.scheme)
rescue URI::BadURIError
false
rescue URI::InvalidURIError
false
end
# path is external to the file
def external?
!internal?
end
# path is an anchor
def internal?
url[0] == "#"
end
def file_path
return if path.nil?
if path =~ /^\// # path relative to root
base = File.directory?(@check.src) ? @check.src : File.dirname(@check.src)
elsif File.exist?(File.expand_path path, @check.src) # relative links, path is a file
base = File.dirname @check.path
elsif File.exist?(File.join(File.dirname(@check.path), path)) # relative links in nested dir, path is a file
base = File.dirname @check.path
else # relative link, path is a directory
base = @check.path
end
file = File.join base, path
# implicit /index.html support, with support for trailing slashes
file = File.join path, "index.html" if File.directory? File.expand_path file, @check.src
file
end
# checks if a file exists relative to the current pwd
def exists?
return @checked_paths[absolute_path] if @checked_paths.has_key? absolute_path
@checked_paths[absolute_path] = File.exist? absolute_path
end
def absolute_path
path = file_path || @check.path
File.expand_path path, Dir.pwd
end
def ignores_pattern_check(links)
links.each do |ignore|
if ignore.is_a? String
return true if ignore == url
elsif ignore.is_a? Regexp
return true if ignore =~ url
end
end
false
end
end
end
end