headhunter 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: df58d59328c6942d9153f49b22765fbef1aa7c62
4
- data.tar.gz: 4e7c82703bb398fbb1a08f3d8b33e80f4793621e
3
+ metadata.gz: 14ca57c35b2c4f399b3f3d3a475489f9ae3b50fc
4
+ data.tar.gz: 8d3fe32d258b3952fe649ff35d375635ad162afc
5
5
  SHA512:
6
- metadata.gz: 68c02e914808c4fababacc1edea8d50d5c7576522154d023434edf6b54fe46fe4026998a57e7991b24848de0eac634b2a85da8105c844a1389fdf6f790dd0922
7
- data.tar.gz: 5b93567d530e2e222476b825f5e0f53f33d3c1f8bb05f90571c06ead976462f3a61741ed9ed32d93135023a2a87aa2a1f9d806dcaad7d56d51562ff062ce12d0
6
+ metadata.gz: 3478cf3aac060a39857d989640622f6b0eeaea7ead4fb1add028c4513336ce38e972a4a6ce757864b2b6ae7a7c9c91a821c61a468fea6917cbb7a5d825dc384e
7
+ data.tar.gz: f9861651aeed1cc736d042ab0f86d567b6c5b0ea3c8522fb05825e641c8907c34972b9fde3c82845cf311614468c400a79c7aa4e9e8958b7de62398980b9ede6
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- headhunter (0.1.3)
4
+ headhunter (0.1.4)
5
5
  colorize
6
6
  css_parser (>= 1.2.6)
7
7
  html_validation
data/README.md CHANGED
@@ -6,6 +6,8 @@
6
6
  [![Code Climate](https://codeclimate.com/github/jmuheim/headhunter.png)](https://codeclimate.com/github/jmuheim/headhunter)
7
7
  [![Travis CI](https://api.travis-ci.org/jmuheim/headhunter.png)](https://travis-ci.org/jmuheim/headhunter)
8
8
  [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/jmuheim/headhunter/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
9
+ [![Dependency Status](https://gemnasium.com/jmuheim/headhunter.png)](https://gemnasium.com/jmuheim/headhunter)
10
+ [![Coverage Status](https://coveralls.io/repos/jmuheim/headhunter/badge.png)](https://coveralls.io/r/jmuheim/headhunter)
9
11
 
10
12
  Headhunter is an HTML and CSS validation tool that injects itself into your Rails feature tests and auto<strong>magic</strong>ally checks all your generated HTML and CSS for validity.
11
13
 
@@ -59,8 +61,11 @@ You need a **Java Runtime Environment** to run CSS validation. This should norma
59
61
  - In feature tests, the same views are getting rendered again and again. These same sources shouldn't be validated over and over again!
60
62
  - More configuration options needed! CSS1, CSS2, CSS2.1, CSS3! XHTML, HTML5, etc.
61
63
  - Better output needed! With context lines, etc.
64
+ - HTML output: info about GET/POST/PUT/DELETE!
62
65
  - Look out for multiple used IDs on the same page and raise error!
63
66
  - Look out for invalid tags and raise error (tidy doesn't seem to do this?!)!
67
+ - Cache HTML validations: use MD5 to prevent validating the same source again and again! (Maybe even keep the cache between running specs!)
68
+ - Add option to CssHunter that ignores "bare" rules like applet, blockquote, etc. (which usually stem from libraries like Compass reset or Normalize)
64
69
 
65
70
  ## Disclaimer
66
71
 
@@ -1,104 +1,76 @@
1
1
  require 'css_parser'
2
2
  require 'nokogiri'
3
- require 'open-uri'
4
3
 
5
4
  module Headhunter
6
5
  class CssHunter
7
- def initialize(stylesheets)
6
+ attr_reader :unused_selectors, :used_selectors, :error_selectors
7
+
8
+ def initialize(stylesheets = [])
8
9
  @stylesheets = stylesheets
9
- @parsed_rules = {}
10
10
  @unused_selectors = []
11
11
  @used_selectors = []
12
12
  @error_selectors = []
13
13
 
14
- load_css!
14
+ @stylesheets.each do |stylesheet|
15
+ add_css_selectors_from(IO.read(stylesheet))
16
+ end
15
17
  end
16
18
 
17
- def process!(url, html)
18
- analyze(html).each do |selector|
19
+ def process(html)
20
+ detect_used_selectors_in(html).each do |selector|
21
+ @used_selectors << selector
19
22
  @unused_selectors.delete(selector)
20
23
  end
21
24
  end
22
25
 
23
- def report
24
- puts "Found #{@used_selectors.size + @unused_selectors.size + @error_selectors.size} CSS selectors.".yellow
25
- puts "#{@used_selectors.size} selectors are in use.".green if @used_selectors.size > 0
26
- puts "#{@unused_selectors.size} selectors are not in use: #{@unused_selectors.sort.join(', ').red}".red if @unused_selectors.size > 0
27
- puts "#{@error_selectors.size} selectors could not be parsed: #{@error_selectors.sort.join(', ').red}".red if @unused_selectors.size > 0
28
- puts
29
- end
26
+ def statistics
27
+ lines = []
30
28
 
31
- private
29
+ lines << "Found #{used_selectors.size + unused_selectors.size + error_selectors.size} CSS selectors.".yellow
30
+ lines << 'All selectors are in use.'.green if unused_selectors.size + error_selectors.size == 0
31
+ lines << "#{unused_selectors.size} selectors are not in use: #{unused_selectors.sort.join(', ').red}".red if unused_selectors.size > 0
32
+ lines << "#{error_selectors.size} selectors could not be parsed: #{error_selectors.sort.join(', ').red}".red if error_selectors.size > 0
32
33
 
33
- def analyze(html)
34
- doc = Nokogiri::HTML(html)
34
+ lines.join("\n")
35
+ end
35
36
 
36
- @unused_selectors.collect do |selector, declarations|
37
- # We test against the selector stripped of any pseudo classes,
38
- # but we report on the selector with its pseudo classes.
39
- stripped_selector = strip(selector)
37
+ def detect_used_selectors_in(html)
38
+ document = Nokogiri::HTML(html)
40
39
 
41
- next if stripped_selector.empty?
40
+ @unused_selectors.collect do |selector, declarations|
41
+ bare_selector = bare_selector_from(selector)
42
42
 
43
43
  begin
44
- if doc.search(stripped_selector).any?
45
- @used_selectors << selector
46
- selector
47
- end
44
+ selector if document.search(bare_selector).any?
48
45
  rescue Nokogiri::CSS::SyntaxError => e
49
46
  @error_selectors << selector
47
+ @unused_selectors.delete(selector)
50
48
  end
51
- end
52
- end
53
-
54
- def load_css!
55
- @stylesheets.each do |stylesheet|
56
- new_selector_count = add_css!(fetch(stylesheet))
57
- end
58
- end
59
-
60
- def fetch(path)
61
- loc = path
62
-
63
- begin
64
- open(loc).read
65
- rescue Errno::ENOENT
66
- raise FetchError.new("#{loc} was not found")
67
- rescue OpenURI::HTTPError => e
68
- raise FetchError.new("retrieving #{loc} raised an HTTP error: #{e.message}")
69
- end
49
+ end.compact # FIXME: Why is compact needed?
70
50
  end
71
51
 
72
- def add_css!(css)
52
+ def add_css_selectors_from(css)
73
53
  parser = CssParser::Parser.new
74
54
  parser.add_block!(css)
75
55
 
76
- selector_count = 0
77
-
78
56
  parser.each_selector do |selector, declarations, specificity|
79
- next if @unused_selectors.include?(selector)
80
- next if selector =~ @ignore_selectors
81
- next if has_pseudo_classes(selector) and @unused_selectors.include?(strip(selector))
82
-
57
+ # next if @unused_selectors.include?(selector)
58
+ # next if has_pseudo_classes?(selector) and @unused_selectors.include?(bare_selector_from(selector))
83
59
  @unused_selectors << selector
84
- @parsed_rules[selector] = declarations
85
-
86
- selector_count += 1
87
60
  end
88
-
89
- selector_count
90
61
  end
91
62
 
92
- def has_pseudo_classes(selector)
93
- selector =~ /::?[\w\-]+/
63
+ # def has_pseudo_classes?(selector)
64
+ # selector =~ /::?[\w\-]+/
65
+ # end
66
+
67
+ def bare_selector_from(selector)
68
+ # Add more clean up stuff here, e.g. stuff like @keyframe (Deadweight implemented this)?
69
+ remove_pseudo_classes_from(selector)
94
70
  end
95
71
 
96
- def strip(selector)
97
- selector = selector.gsub(/^@.*/, '') # @-webkit-keyframes ...
98
- selector = selector.gsub(/:.*/, '') # input#x:nth-child(2):not(#z.o[type='file'])
99
- selector
72
+ def remove_pseudo_classes_from(selector)
73
+ selector.gsub(/:.*/, '') # input#x:nth-child(2):not(#z.o[type='file'])
100
74
  end
101
75
  end
102
-
103
- class FetchError < StandardError; end
104
76
  end
@@ -1,73 +1,65 @@
1
1
  require 'net/http'
2
- require 'rexml/document'
2
+ require 'nokogiri/xml'
3
3
 
4
4
  module Headhunter
5
- class LocalResponse
6
- attr_reader :body
7
-
8
- def initialize(body)
9
- @body = body
10
- @headers = {'x-w3c-validator-status' => valid?(body)}
11
- end
5
+ class CssValidator
6
+ VALIDATOR_PATH = Gem.loaded_specs['headhunter'].full_gem_path + '/lib/css-validator/'
12
7
 
13
- def [](key)
14
- @headers[key]
15
- end
8
+ attr_reader :stylesheets, :responses
16
9
 
17
- private
10
+ def initialize(stylesheets = [], profile = 'css3', vextwarning = true)
11
+ @stylesheets = stylesheets
12
+ @profile = profile # TODO!
13
+ @vextwarning = vextwarning # TODO!
18
14
 
19
- def valid?(body)
20
- REXML::Document.new(body).root.each_element('//m:validity') { |e| return e.text == 'true' }
15
+ @responses = @stylesheets.map do |stylesheet|
16
+ validate(stylesheet)
17
+ end
21
18
  end
22
- end
23
19
 
24
- class CssValidator
25
- USE_LOCAL_VALIDATOR = true
20
+ def validate(uri)
21
+ # See http://stackoverflow.com/questions/1137884/is-there-an-open-source-css-validator-that-can-be-run-locally
22
+ # More config options see http://jigsaw.w3.org/css-validator/manual.html
23
+ results = if File.exists?(uri)
24
+ Dir.chdir(VALIDATOR_PATH) { `java -jar css-validator.jar --output=soap12 file:#{uri}` }
25
+ else
26
+ raise "Couldn't locate uri #{uri}"
27
+ end
26
28
 
27
- def initialize(stylesheets = [])
28
- @profile = 'css3' # TODO: Option for profile css1 and css21
29
- @stylesheets = stylesheets
30
- @messages_per_stylesheet = {}
29
+ Response.new(results)
31
30
  end
32
31
 
33
- def add_stylesheet(stylesheet)
34
- @stylesheets << stylesheet
32
+ def valid_responses
33
+ @responses.select(&:valid?)
35
34
  end
36
35
 
37
- def process!
38
- @stylesheets.each do |stylesheet|
39
- css = fetch(stylesheet)
40
- css = ' ' if css.empty? # The validator returns a 500 error if it receives an empty string
41
-
42
- response = get_validation_response({text: css, profile: @profile, vextwarning: 'true'})
43
- unless response_indicates_valid?(response)
44
- process_errors(stylesheet, css, response)
45
- end
46
- end
36
+ def invalid_responses
37
+ @responses.reject(&:valid?)
47
38
  end
48
39
 
49
- def report
50
- puts "Validated #{@stylesheets.size} stylesheets.".yellow
51
- puts "#{x_stylesheets_be(@stylesheets.size - @messages_per_stylesheet.size)} valid.".green if @messages_per_stylesheet.size < @stylesheets.size
52
- puts "#{x_stylesheets_be(@messages_per_stylesheet.size)} invalid.".red if @messages_per_stylesheet.size > 0
40
+ def statistics
41
+ lines = []
42
+
43
+ lines << "Validated #{responses.size} stylesheets.".yellow
44
+ lines << "All stylesheets are valid.".green if invalid_responses.size == 0
45
+ lines << "#{x_stylesheets_be(invalid_responses.size)} invalid.".red if invalid_responses.size > 0
53
46
 
54
- @messages_per_stylesheet.each_pair do |stylesheet, messages|
55
- puts " #{extract_filename(stylesheet)}:".red
47
+ invalid_responses.each do |response|
48
+ lines << " #{extract_filename(response.uri)}:".red
56
49
 
57
- messages.each { |message| puts " - #{message}".red }
50
+ response.errors.each do |error|
51
+ lines << " - #{error.to_s}".red
52
+ end
58
53
  end
59
54
 
60
- puts
55
+ lines.join("\n")
61
56
  end
62
57
 
63
- private
64
-
65
- # Converts a path like public/assets/application-d205d6f344d8623ca0323cb6f6bd7ca1.css to application.css
66
58
  def extract_filename(path)
67
- if matches = path.match(/^public\/assets\/(.*)-?([a-z0-9]*)(\.css)/)
68
- matches[1] + matches[3]
59
+ if matches = path.match(/public\/assets\/([a-z\-_]*)-([a-z0-9]{32})(\.css)$/)
60
+ matches[1] + matches[3] # application-d205d6f344d8623ca0323cb6f6bd7ca1.css becomes application.css
69
61
  else
70
- raise "Unexpected path: #{path}"
62
+ File.basename(path)
71
63
  end
72
64
  end
73
65
 
@@ -79,115 +71,72 @@ module Headhunter
79
71
  end
80
72
  end
81
73
 
82
- def process_errors(file, css, response)
83
- @messages_per_stylesheet[file] = []
84
-
85
- REXML::Document.new(response.body).root.each_element('//m:error') do |e|
86
- @messages_per_stylesheet[file] << "Line #{extract_line_from_error(e)}: #{extract_message_from_error(e)}"
74
+ class Response
75
+ def initialize(response = nil)
76
+ @document = Nokogiri::XML(convert_soap_to_xml(response)) if response
87
77
  end
88
- end
89
-
90
- def extract_line_from_error(e)
91
- e.elements['m:line'].text
92
- end
93
78
 
94
- def extract_message_from_error(e)
95
- e.elements['m:message'].get_text.value.strip[0..-2]
96
- end
97
-
98
- def fetch(path) # TODO: Move to Headhunter!
99
- loc = path
100
-
101
- begin
102
- open(loc).read
103
- rescue Errno::ENOENT
104
- raise FetchError.new("#{loc} was not found")
105
- rescue OpenURI::HTTPError => e
106
- raise FetchError.new("retrieving #{loc} raised an HTTP error: #{e.message}")
79
+ def [](key)
80
+ @headers[key]
107
81
  end
108
- end
109
-
110
- def get_validation_response(query_params)
111
- query_params.merge!({:output => 'soap12'})
112
82
 
113
- if USE_LOCAL_VALIDATOR
114
- call_local_validator(query_params)
115
- else
116
- call_remote_validator(query_params)
83
+ def valid?
84
+ @document.css('validity').text == 'true'
117
85
  end
118
- end
119
-
120
- def response_indicates_valid?(response)
121
- response['x-w3c-validator-status'] == 'Valid'
122
- end
123
-
124
- def call_remote_validator(query_params = {})
125
- boundary = Digest::MD5.hexdigest(Time.now.to_s)
126
- data = encode_multipart_params(boundary, query_params)
127
- response = http_start(validator_host).post2(validator_path,
128
- data,
129
- 'Content-type' => "multipart/form-data; boundary=#{boundary}")
130
86
 
131
- raise "HTTP error: #{response.code}" unless response.is_a? Net::HTTPSuccess
132
- response
133
- end
134
-
135
- def call_local_validator(query_params)
136
- path = Gem.loaded_specs['headhunter'].full_gem_path + '/lib/css-validator/'
137
- css_file = 'tmp.css'
138
- results_file = 'results'
139
- results = nil
140
-
141
- Dir.chdir(path) do
142
- File.open(css_file, 'a') { |f| f.write query_params[:text] }
143
-
144
- # See http://stackoverflow.com/questions/1137884/is-there-an-open-source-css-validator-that-can-be-run-locally
145
- if system "java -jar css-validator.jar --output=soap12 file:#{css_file} > #{results_file}"
146
- results = IO.read results_file
147
- else
148
- raise 'Could not execute local validation!'
87
+ def errors
88
+ @document.css('errors error').map do |error|
89
+ Error.new( error.css('line').text.strip.to_i,
90
+ error.css('message').text.strip[0..-3],
91
+ errortype: error.css('errortype').text.strip,
92
+ context: error.css('context').text.strip,
93
+ errorsubtype: error.css('errorsubtype').text.strip,
94
+ skippedstring: error.css('skippedstring').text.strip
95
+ )
149
96
  end
97
+ end
150
98
 
151
- File.delete css_file
152
- File.delete results_file
99
+ def uri
100
+ @document.css('cssvalidationresponse > uri').text
153
101
  end
154
102
 
155
- LocalResponse.new(results)
156
- end
103
+ private
157
104
 
158
- def encode_multipart_params(boundary, params = {})
159
- ret = ''
160
- params.each do |k,v|
161
- unless v.empty?
162
- ret << "\r\n--#{boundary}\r\n"
163
- ret << "Content-Disposition: form-data; name=\"#{k.to_s}\"\r\n\r\n"
164
- ret << v
165
- end
105
+ def convert_soap_to_xml(soap)
106
+ sanitize_prefixed_tags_from(
107
+ remove_first_line_from(soap)
108
+ )
166
109
  end
167
- ret << "\r\n--#{boundary}--\r\n"
168
- ret
169
- end
170
110
 
171
- def http_start(host)
172
- if ENV['http_proxy']
173
- uri = URI.parse(ENV['http_proxy'])
174
- proxy_user, proxy_pass = uri.userinfo.split(/:/) if uri.userinfo
175
- Net::HTTP.start(host, nil, uri.host, uri.port, proxy_user, proxy_pass)
176
- else
177
- Net::HTTP.start(host)
111
+ # The first line of the validator's response contains parameter options like this:
112
+ #
113
+ # {vextwarning=false, output=soap, lang=en, warning=2, medium=all, profile=css3}
114
+ #
115
+ # We remove this so Nokogiri can parse the document as XML.
116
+ def remove_first_line_from(soap)
117
+ soap.split("\n")[1..-1].join("\n")
178
118
  end
179
- end
180
119
 
181
- def validator_host
182
- 'jigsaw.w3.org'
183
- end
120
+ # The validator's response contains strange SOAP tags like `m:error` or `env:body` which need to be sanitized for Nokogiri.
121
+ #
122
+ # We simply remove the `m:` and `env:` prefixes from the source, so e.g. `<env:body>` becomes `<body>`.
123
+ def sanitize_prefixed_tags_from(soap)
124
+ soap.gsub /(m|env):/, ''
125
+ end
184
126
 
185
- def validator_path
186
- '/css-validator/validator'
187
- end
127
+ class Error
128
+ attr_reader :line, :message, :details
129
+
130
+ def initialize(line, message, details = {})
131
+ @line = line
132
+ @message = message
133
+ @details = details
134
+ end
188
135
 
189
- def error_line_prefix
190
- 'Invalid css'
136
+ def to_s
137
+ "Line #{@line}: #{@message}."
138
+ end
139
+ end
191
140
  end
192
141
  end
193
142
  end
@@ -2,46 +2,43 @@ require 'html_validation'
2
2
 
3
3
  module Headhunter
4
4
  class HtmlValidator
5
+ attr_reader :responses
6
+
5
7
  def initialize
6
- @valid_results = []
7
- @invalid_results = []
8
+ @responses = []
8
9
  end
9
10
 
10
- def process!(url, html)
11
- html_validation = PageValidations::HTMLValidation.new.validation(html, random_name)
12
- (html_validation.valid? ? @valid_results : @invalid_results) << html_validation
11
+ def validate(url, html)
12
+ # Docs for Tidy: http://tidy.sourceforge.net/docs/quickref.html
13
+ @responses << PageValidations::HTMLValidation.new.validation(html, url)
14
+ @responses.last
13
15
  end
14
16
 
15
- def prepare_results_html
16
- html = File.read File.dirname(File.expand_path(__FILE__)) + '/templates/results.html'
17
- html.gsub! '{{VALID_RESULTS}}', prepare_results_for(@valid_results)
18
- html.gsub! '{{INVALID_RESULTS}}', prepare_results_for(@invalid_results)
19
- File.open('.validation/results.html', 'w') { |file| file.write(html) }
17
+ def valid_responses
18
+ @responses.select(&:valid?)
20
19
  end
21
20
 
22
- def prepare_results_for(results)
23
- results.map do |result|
24
- exceptions_html = ::Rack::Utils.escape_html(File.read(".validation/#{result.resource}.exceptions.txt"))
21
+ def invalid_responses
22
+ @responses.reject(&:valid?)
23
+ end
25
24
 
26
- full_result_html = File.read File.dirname(File.expand_path(__FILE__)) + '/templates/result.html'
27
- full_result_html.gsub! '{{RESOURCE}}', result.resource
28
- full_result_html.gsub! '{{EXCEPTIONS}}', exceptions_html
29
- full_result_html.gsub! '{{HTML_CONTEXT}}', 'context'
30
- full_result_html.gsub! '{{LINK}}', "#{result.resource}.html.txt"
25
+ def statistics
26
+ lines = []
31
27
 
32
- full_result_html
33
- end.join
34
- end
28
+ lines << "Validated #{responses.size} pages.".yellow
29
+ lines << "All pages are valid.".green if invalid_responses.size == 0
30
+ lines << "#{x_pages_be(invalid_responses.size)} invalid.".red if invalid_responses.size > 0
35
31
 
36
- def report
37
- puts "Validated #{@valid_results.size + @invalid_results.size} HTML pages.".yellow
38
- puts "#{x_pages_be(@valid_results.size)} valid.".green if @valid_results.size > 0
39
- puts "#{x_pages_be(@invalid_results.size)} invalid.".red if @invalid_results.size > 0
40
- puts 'Open .validation/results.html to view full results.'
41
- puts
42
- end
32
+ invalid_responses.each do |response|
33
+ lines << " #{response.resource}:".red
34
+
35
+ ([response.exceptions].flatten).each do |exception|
36
+ lines << " - #{exception.strip}".red
37
+ end
38
+ end
43
39
 
44
- private
40
+ lines.join("\n")
41
+ end
45
42
 
46
43
  def x_pages_be(size)
47
44
  if size <= 1
@@ -50,9 +47,5 @@ module Headhunter
50
47
  "#{size} pages are"
51
48
  end
52
49
  end
53
-
54
- def random_name
55
- (0...8).map { (65 + rand(26)).chr }.join
56
- end
57
50
  end
58
51
  end
@@ -16,7 +16,7 @@ module Headhunter
16
16
  status, headers, response = rack_response
17
17
 
18
18
  if html = extract_html_from(response)
19
- @hh.process!('unknown', html)
19
+ @hh.process('unknown', html)
20
20
  end
21
21
  end
22
22
 
@@ -16,12 +16,11 @@ module Headhunter
16
16
  @css_hunter = CssHunter.new(stylesheets)
17
17
 
18
18
  @css_validator = CssValidator.new(stylesheets)
19
- @css_validator.process!
20
19
  end
21
20
 
22
- def process!(url, html)
23
- @html_validator.process!(url, html)
24
- @css_hunter.process!(url, html)
21
+ def process(url, html)
22
+ @html_validator.validate(url, html)
23
+ @css_hunter.process(url, html)
25
24
  end
26
25
 
27
26
  def clean_up!
@@ -31,11 +30,12 @@ module Headhunter
31
30
  end
32
31
 
33
32
  def report
34
- @html_validator.prepare_results_html
33
+ puts [ @html_validator.statistics,
34
+ @css_validator.statistics,
35
+ @css_hunter.statistics
36
+ ].join "\n\n"
35
37
 
36
- @html_validator.report
37
- @css_validator.report
38
- @css_hunter.report
38
+ puts
39
39
  end
40
40
 
41
41
  private
@@ -58,7 +58,7 @@ module Headhunter
58
58
  end
59
59
 
60
60
  def stylesheets
61
- Dir["#{ASSETS_PATH}/*.css"]
61
+ Dir["#{::Rails.root}/#{ASSETS_PATH}/*.css"]
62
62
  end
63
63
  end
64
64
  end
@@ -1,3 +1,3 @@
1
1
  module Headhunter
2
- VERSION = '0.1.4'
2
+ VERSION = '0.1.5'
3
3
  end
Binary file
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: headhunter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua Muheim
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-03 00:00:00.000000000 Z
11
+ date: 2014-02-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -195,7 +195,6 @@ files:
195
195
  - lib/headhunter/css_hunter.rb
196
196
  - lib/headhunter/css_validator.rb
197
197
  - lib/headhunter/html_validator.rb
198
- - lib/headhunter/local_response.rb
199
198
  - lib/headhunter/rack/capturing_middleware.rb
200
199
  - lib/headhunter/rails.rb
201
200
  - lib/headhunter/runner.rb
@@ -203,6 +202,7 @@ files:
203
202
  - lib/headhunter/templates/results.html
204
203
  - lib/headhunter/version.rb
205
204
  - lib/headhunter.rb
205
+ - lib/tidy/tidy
206
206
  - Gemfile
207
207
  - Gemfile.lock
208
208
  - Rakefile
@@ -1,20 +0,0 @@
1
- require 'rexml/document'
2
-
3
- module Headhunter
4
- class LocalResponse
5
- attr_reader :body
6
-
7
- def initialize(body)
8
- @body = body
9
- @headers = {'x-w3c-validator-status' => valid?}
10
- end
11
-
12
- def [](key)
13
- @headers[key]
14
- end
15
-
16
- def valid?
17
- REXML::Document.new(@body).root.each_element('//m:validity') { |e| return e.text == 'true' }
18
- end
19
- end
20
- end