headhunter 0.1.4 → 0.1.5

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
  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