Class: Utterson

Inherits:
Object
  • Object
show all
Defined in:
lib/utterson.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ Utterson

Returns a new instance of Utterson.



9
10
11
12
13
14
15
# File 'lib/utterson.rb', line 9

def initialize(opts={})
  @dir = opts[:dir] || './'
  @root = opts[:root] || @dir
  @errors = {}
  @checked_urls = {}
  @stats = {errors: 0, files: 0, urls: 0}
end

Instance Attribute Details

#errorsObject (readonly)

Returns the value of attribute errors.



7
8
9
# File 'lib/utterson.rb', line 7

def errors
  @errors
end

Instance Method Details

#add_error(file, url, response) ⇒ Object



84
85
86
87
88
# File 'lib/utterson.rb', line 84

def add_error(file, url, response)
  @stats[:errors] += 1
  @errors[file] = {} if @errors[file].nil?
  @errors[file][url] = response
end

#checkObject



17
18
19
20
21
22
23
24
25
26
27
# File 'lib/utterson.rb', line 17

def check
  Dir.glob(File.join(@dir, '**/*.{html,htm}')) do |f|
    @stats[:files] += 1
    puts "Checking #{f}"
    collect_uris_from(f).each do |u|
      @stats[:urls] += 1
      check_uri(u, f)
    end
  end
  print_results
end

#check_local_uri(url, file) ⇒ Object



74
75
76
77
78
79
80
81
82
# File 'lib/utterson.rb', line 74

def check_local_uri(url, file)
  url.gsub!(/\?.*$/, '')
  if url =~ /^\//
    path = File.expand_path(".#{url}", @root)
  else
    path = File.expand_path(url, File.dirname(file))
  end
  add_error(file, url, "File not found") unless File.exists? path
end

#check_remote_uri(url, file) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/utterson.rb', line 50

def check_remote_uri(url, file)
  begin
    uri = URI(url.gsub(/^\/\//, 'http://'))
  rescue URI::InvalidURIError => e
    return add_error(file, uri.to_s, e.message)
  end
  begin
    response = Net::HTTP.start(uri.host, uri.port,
                               :use_ssl => uri.scheme == 'https') do |http|
      p = uri.path.empty? ? "/" : uri.path
      http.head(p)
    end
    if response.code =~ /^[^23]/
      add_error(file, uri.to_s, response)
    end
  rescue Timeout::Error
    add_error(file, uri.to_s, "Reading buffer timed out")
  rescue Errno::ETIMEDOUT
    add_error(file, uri.to_s, "Connection timed out")
  rescue SocketError => e
    add_error(file, uri.to_s, e.message)
  end
end

#check_uri(url, file) ⇒ Object



39
40
41
42
43
44
45
46
47
48
# File 'lib/utterson.rb', line 39

def check_uri(url, file)
  return if @checked_urls[url]

  if url =~ /^(https?:)?\/\//
    check_remote_uri url, file
  else
    check_local_uri url, file
  end
  @checked_urls[url] = true
end

#collect_uris_from(f) ⇒ Object



29
30
31
32
33
34
35
36
37
# File 'lib/utterson.rb', line 29

def collect_uris_from(f)
  ret = []
  doc = Nokogiri::HTML(File.read(f))
  doc.traverse do |el|
    ret << el['src'] unless el['src'].nil?
    ret << el['href'] unless el['href'].nil?
  end
  ret
end


90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/utterson.rb', line 90

def print_results
  @errors.each do |file, info|
    puts file
    info.each do |url, response|
      s = response.respond_to?(:code) ? "HTTP #{response.code}" : response
      puts "\t#{url}\n\t\t#{s}"
    end
  end
  if @stats[:errors] == 0
    puts "#{@stats[:files]} files with #{@stats[:urls]} urls checked."
  else
    puts "#{@stats[:files]} files with #{@stats[:urls]} urls checked and #{@stats[:errors]} errors found."
  end
end