deadweight 0.1.1 → 0.1.2

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.
Files changed (31) hide show
  1. data/README.rdoc +17 -5
  2. data/Rakefile +0 -1
  3. data/VERSION +1 -1
  4. data/deadweight.gemspec +29 -9
  5. data/lib/deadweight.rb +51 -15
  6. data/lib/deadweight/cli.rb +8 -2
  7. data/test/cli_test.rb +9 -6
  8. data/test/test_helper.rb +2 -2
  9. data/vendor/gems/css_parser-0.9.1/CHANGELOG +13 -0
  10. data/vendor/gems/css_parser-0.9.1/LICENSE +21 -0
  11. data/vendor/gems/css_parser-0.9.1/README +58 -0
  12. data/vendor/gems/css_parser-0.9.1/lib/css_parser.rb +149 -0
  13. data/vendor/gems/css_parser-0.9.1/lib/css_parser/parser.rb +345 -0
  14. data/vendor/gems/css_parser-0.9.1/lib/css_parser/regexps.rb +46 -0
  15. data/vendor/gems/css_parser-0.9.1/lib/css_parser/rule_set.rb +380 -0
  16. data/vendor/gems/css_parser-0.9.1/test/fixtures/import-circular-reference.css +4 -0
  17. data/vendor/gems/css_parser-0.9.1/test/fixtures/import-with-media-types.css +3 -0
  18. data/vendor/gems/css_parser-0.9.1/test/fixtures/import1.css +3 -0
  19. data/vendor/gems/css_parser-0.9.1/test/fixtures/simple.css +6 -0
  20. data/vendor/gems/css_parser-0.9.1/test/fixtures/subdir/import2.css +3 -0
  21. data/vendor/gems/css_parser-0.9.1/test/test_css_parser_basic.rb +56 -0
  22. data/vendor/gems/css_parser-0.9.1/test/test_css_parser_downloading.rb +81 -0
  23. data/vendor/gems/css_parser-0.9.1/test/test_css_parser_media_types.rb +71 -0
  24. data/vendor/gems/css_parser-0.9.1/test/test_css_parser_misc.rb +143 -0
  25. data/vendor/gems/css_parser-0.9.1/test/test_css_parser_regexps.rb +68 -0
  26. data/vendor/gems/css_parser-0.9.1/test/test_helper.rb +8 -0
  27. data/vendor/gems/css_parser-0.9.1/test/test_merging.rb +88 -0
  28. data/vendor/gems/css_parser-0.9.1/test/test_rule_set.rb +74 -0
  29. data/vendor/gems/css_parser-0.9.1/test/test_rule_set_creating_shorthand.rb +90 -0
  30. data/vendor/gems/css_parser-0.9.1/test/test_rule_set_expanding_shorthand.rb +178 -0
  31. metadata +25 -13
@@ -6,7 +6,11 @@ Deadweight is a CSS coverage tool. Given a set of stylesheets and a set of URLs,
6
6
 
7
7
  Ryan Bates has worked his magic once again. Head over here for an excellent introduction to deadweight: http://railscasts.com/episodes/180-finding-unused-css
8
8
 
9
- === A Simple Example
9
+ === Install It
10
+
11
+ gem install deadweight -s http://gemcutter.org
12
+
13
+ === Make a Rake Task
10
14
 
11
15
  # lib/tasks/deadweight.rake
12
16
 
@@ -19,7 +23,7 @@ Ryan Bates has worked his magic once again. Head over here for an excellent intr
19
23
 
20
24
  Running <tt>rake deadweight</tt> will output all unused rules, one per line. Note that it looks at http://localhost:3000 by default, so you'll need to have <tt>script/server</tt> (or whatever your server command looks like) running.
21
25
 
22
- Alternately, you can run it from the command-line:
26
+ === Or Run it From the Command Line
23
27
 
24
28
  $ deadweight -s styles.css -s ie.css index.html about.html
25
29
 
@@ -31,15 +35,23 @@ And you can use it as an HTTP proxy:
31
35
 
32
36
  $ deadweight -l deadweight.log -s styles.css -w http://github.com/ -P
33
37
 
34
- === How You Install It
38
+ There's also experimental support for Lyndon (http://github.com/defunkt/lyndon) with <tt>-L</tt>.
35
39
 
36
- gem install deadweight -s http://gemcutter.org
40
+ === Or Call it Directly
41
+
42
+ require 'deadweight'
43
+
44
+ dw = Deadweight.new
45
+ dw.stylesheets = %w( /stylesheets/style.css )
46
+ dw.pages = %w( / /page/1 /about )
47
+ puts dw.run
37
48
 
38
49
  === Things to Note
39
50
 
51
+ - You can tell it what URL root to use (rather than <tt>http://localhost:3000</tt>) by setting +root+.
40
52
  - It's completely dumb about any classes, IDs or tags that are only added by your Javascript layer, but you can filter them out by setting +ignore_selectors+.
41
53
  - You can optionally tell it to use Mechanize, and set up more complicated targets for scraping by specifying them as Procs.
42
- - There is experimental support for Lyndon (http://github.com/defunkt/lyndon) with -L
54
+ - If you have the <tt>colored</tt> gem installed, it'll spruce up the STDERR output.
43
55
 
44
56
  === A More Complex Example, In Light of All That
45
57
 
data/Rakefile CHANGED
@@ -10,7 +10,6 @@ begin
10
10
  gem.homepage = "http://github.com/aanand/deadweight"
11
11
  gem.authors = ["Aanand Prasad"]
12
12
 
13
- gem.add_dependency('css_parser')
14
13
  gem.add_dependency('hpricot')
15
14
  end
16
15
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.1.2
@@ -1,15 +1,15 @@
1
1
  # Generated by jeweler
2
- # DO NOT EDIT THIS FILE
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{deadweight}
8
- s.version = "0.1.1"
8
+ s.version = "0.1.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Aanand Prasad"]
12
- s.date = %q{2009-10-18}
12
+ s.date = %q{2009-12-15}
13
13
  s.default_executable = %q{deadweight}
14
14
  s.email = %q{aanand.prasad@gmail.com}
15
15
  s.executables = ["deadweight"]
@@ -35,12 +35,34 @@ Gem::Specification.new do |s|
35
35
  "test/fixtures/index2.html",
36
36
  "test/fixtures/style.css",
37
37
  "test/rake_task_test.rb",
38
- "test/test_helper.rb"
38
+ "test/test_helper.rb",
39
+ "vendor/gems/css_parser-0.9.1/CHANGELOG",
40
+ "vendor/gems/css_parser-0.9.1/LICENSE",
41
+ "vendor/gems/css_parser-0.9.1/README",
42
+ "vendor/gems/css_parser-0.9.1/lib/css_parser.rb",
43
+ "vendor/gems/css_parser-0.9.1/lib/css_parser/parser.rb",
44
+ "vendor/gems/css_parser-0.9.1/lib/css_parser/regexps.rb",
45
+ "vendor/gems/css_parser-0.9.1/lib/css_parser/rule_set.rb",
46
+ "vendor/gems/css_parser-0.9.1/test/fixtures/import-circular-reference.css",
47
+ "vendor/gems/css_parser-0.9.1/test/fixtures/import-with-media-types.css",
48
+ "vendor/gems/css_parser-0.9.1/test/fixtures/import1.css",
49
+ "vendor/gems/css_parser-0.9.1/test/fixtures/simple.css",
50
+ "vendor/gems/css_parser-0.9.1/test/fixtures/subdir/import2.css",
51
+ "vendor/gems/css_parser-0.9.1/test/test_css_parser_basic.rb",
52
+ "vendor/gems/css_parser-0.9.1/test/test_css_parser_downloading.rb",
53
+ "vendor/gems/css_parser-0.9.1/test/test_css_parser_media_types.rb",
54
+ "vendor/gems/css_parser-0.9.1/test/test_css_parser_misc.rb",
55
+ "vendor/gems/css_parser-0.9.1/test/test_css_parser_regexps.rb",
56
+ "vendor/gems/css_parser-0.9.1/test/test_helper.rb",
57
+ "vendor/gems/css_parser-0.9.1/test/test_merging.rb",
58
+ "vendor/gems/css_parser-0.9.1/test/test_rule_set.rb",
59
+ "vendor/gems/css_parser-0.9.1/test/test_rule_set_creating_shorthand.rb",
60
+ "vendor/gems/css_parser-0.9.1/test/test_rule_set_expanding_shorthand.rb"
39
61
  ]
40
62
  s.homepage = %q{http://github.com/aanand/deadweight}
41
63
  s.rdoc_options = ["--charset=UTF-8"]
42
64
  s.require_paths = ["lib"]
43
- s.rubygems_version = %q{1.3.4}
65
+ s.rubygems_version = %q{1.3.5}
44
66
  s.summary = %q{A coverage tool for finding unused CSS}
45
67
  s.test_files = [
46
68
  "test/cli_test.rb",
@@ -54,14 +76,12 @@ Gem::Specification.new do |s|
54
76
  s.specification_version = 3
55
77
 
56
78
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
57
- s.add_runtime_dependency(%q<css_parser>, [">= 0"])
58
79
  s.add_runtime_dependency(%q<hpricot>, [">= 0"])
59
80
  else
60
- s.add_dependency(%q<css_parser>, [">= 0"])
61
81
  s.add_dependency(%q<hpricot>, [">= 0"])
62
82
  end
63
83
  else
64
- s.add_dependency(%q<css_parser>, [">= 0"])
65
84
  s.add_dependency(%q<hpricot>, [">= 0"])
66
85
  end
67
86
  end
87
+
@@ -1,7 +1,18 @@
1
+ $LOAD_PATH.concat Dir.glob(File.expand_path('../../vendor/gems/*/lib', __FILE__))
2
+
1
3
  require 'css_parser'
2
4
  require 'hpricot'
3
5
  require 'open-uri'
4
- require 'logger'
6
+
7
+ begin
8
+ require 'colored'
9
+ rescue LoadError
10
+ class String
11
+ %w(red green blue yellow).each do |color|
12
+ define_method(color) { self }
13
+ end
14
+ end
15
+ end
5
16
 
6
17
  class Deadweight
7
18
  attr_accessor :root, :stylesheets, :rules, :pages, :ignore_selectors, :mechanize, :log_file
@@ -21,13 +32,11 @@ class Deadweight
21
32
  def analyze(html)
22
33
  doc = Hpricot(html)
23
34
 
24
- found_selectors = []
25
-
26
35
  @unused_selectors.collect do |selector, declarations|
27
36
  # We test against the selector stripped of any pseudo classes,
28
37
  # but we report on the selector with its pseudo classes.
29
38
  unless doc.search(strip(selector)).empty?
30
- log.info(" #{selector}")
39
+ log.puts(" #{selector.green}")
31
40
  selector
32
41
  end
33
42
  end
@@ -45,12 +54,9 @@ class Deadweight
45
54
 
46
55
  @parsed_rules = {}
47
56
  @unused_selectors = []
48
- total_selectors = 0
49
57
 
50
58
  css.each_selector do |selector, declarations, specificity|
51
59
  unless @unused_selectors.include?(selector)
52
- total_selectors += 1
53
-
54
60
  unless selector =~ ignore_selectors
55
61
  @unused_selectors << selector
56
62
  @parsed_rules[selector] = declarations
@@ -67,7 +73,11 @@ class Deadweight
67
73
  end
68
74
  end
69
75
 
76
+ total_selectors = @unused_selectors.size
77
+
70
78
  pages.each do |page|
79
+ log.puts
80
+
71
81
  if page.respond_to?(:read)
72
82
  html = page.read
73
83
  elsif page.respond_to?(:call)
@@ -80,13 +90,20 @@ class Deadweight
80
90
  @agent.page.body
81
91
  end
82
92
  else
83
- html = fetch(page)
93
+ begin
94
+ html = fetch(page)
95
+ rescue FetchError => e
96
+ log.puts(e.message.red)
97
+ next
98
+ end
84
99
  end
85
100
 
86
101
  process!(html)
87
102
  end
88
103
 
89
- log.info "found #{@unused_selectors.size} unused selectors out of #{total_selectors} total"
104
+ log.puts
105
+ log.puts "found #{@unused_selectors.size} unused selectors out of #{total_selectors} total".yellow
106
+ log.puts
90
107
 
91
108
  @unused_selectors
92
109
  end
@@ -108,17 +125,30 @@ class Deadweight
108
125
 
109
126
  # Fetch a path, using Mechanize if +mechanize+ is set to +true+.
110
127
  def fetch(path)
111
- log.info(path)
128
+ log.puts(path)
112
129
 
113
130
  loc = root + path
114
131
 
115
132
  if @mechanize
116
133
  loc = "file://#{File.expand_path(loc)}" unless loc =~ %r{^\w+://}
117
- page = agent.get(loc)
118
- log.warn("#{path} redirected to #{page.uri}") unless page.uri.to_s == loc
134
+
135
+ begin
136
+ page = agent.get(loc)
137
+ rescue WWW::Mechanize::ResponseCodeError => e
138
+ raise FetchError.new("#{loc} returned a response code of #{e.response_code}")
139
+ end
140
+
141
+ log.puts("#{loc} redirected to #{page.uri}".red) unless page.uri.to_s == loc
142
+
119
143
  page.body
120
144
  else
121
- open(loc).read
145
+ begin
146
+ open(loc).read
147
+ rescue Errno::ENOENT
148
+ raise FetchError.new("#{loc} was not found")
149
+ rescue OpenURI::HTTPError => e
150
+ raise FetchError.new("retrieving #{loc} raised an HTTP error: #{e.message}")
151
+ end
122
152
  end
123
153
  end
124
154
 
@@ -133,7 +163,11 @@ private
133
163
  end
134
164
 
135
165
  def log
136
- @log ||= Logger.new(@log_file)
166
+ @log ||= if @log_file.respond_to?(:puts)
167
+ @log_file
168
+ else
169
+ open(@log_file, 'w+')
170
+ end
137
171
  end
138
172
 
139
173
  def initialize_agent
@@ -141,7 +175,7 @@ private
141
175
  require 'mechanize'
142
176
  return WWW::Mechanize.new
143
177
  rescue LoadError
144
- log.info %{
178
+ log.puts %{
145
179
  =================================================================
146
180
  Couldn't load 'mechanize', which is required for remote scraping.
147
181
  Install it like so: gem install mechanize
@@ -151,6 +185,8 @@ private
151
185
  raise
152
186
  end
153
187
  end
188
+
189
+ class FetchError < StandardError; end
154
190
  end
155
191
 
156
192
  require 'deadweight/rake_task'
@@ -9,6 +9,7 @@ class Deadweight
9
9
 
10
10
  def self.execute(stdout, stdin, stderr, arguments = [])
11
11
  @options = {
12
+ :root => "",
12
13
  :log_file => stderr,
13
14
  :output => stdout,
14
15
  :proxy_port => 8002
@@ -51,6 +52,11 @@ class Deadweight
51
52
  @options[:stylesheets] << v
52
53
  end
53
54
 
55
+ opts.on("-r", "--root URL-OR-PATH",
56
+ "Specify a root for all urls/paths") do |r|
57
+ @options[:root] = r
58
+ end
59
+
54
60
  opts.on("-w", "--whitelist URL-PREFIX",
55
61
  "Specifies a prefix for URLs to process") do |v|
56
62
  @options[:whitelist] ||= []
@@ -88,7 +94,7 @@ class Deadweight
88
94
  dw = Deadweight.new
89
95
 
90
96
  # TODO this should be the default
91
- dw.root = ""
97
+ dw.root = options[:root]
92
98
 
93
99
  dw.log_file = options[:log_file]
94
100
 
@@ -112,7 +118,7 @@ class Deadweight
112
118
  dw = Deadweight.new
113
119
 
114
120
  # TODO note the boilerplate shared with #process
115
- dw.root = ""
121
+ dw.root = options[:root]
116
122
  dw.log_file = options[:log_file]
117
123
  dw.stylesheets = options[:stylesheets]
118
124
  dw.rules = stdin.read if stdin.stat.size > 0
@@ -1,18 +1,21 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class CliTest < Test::Unit::TestCase
4
- COMMAND = "ruby -rubygems -Ilib bin/deadweight -s test/fixtures/style.css test/fixtures/index.html 2>/dev/null"
4
+ COMMAND = "ruby -rubygems -Ilib bin/deadweight"
5
+ FULL_COMMAND = "#{COMMAND} -s test/fixtures/style.css test/fixtures/index.html 2>/dev/null"
5
6
 
6
7
  should "output unused selectors on STDOUT" do
7
- @result = `#{COMMAND}`
8
-
9
- assert_correct_selectors_in_output(@result)
8
+ assert_correct_selectors_in_output(`#{FULL_COMMAND}`)
10
9
  end
11
10
 
12
11
  should "accept CSS rules on STDIN" do
13
- @result = `echo ".something { display: block; }" | #{COMMAND}`
12
+ assert `echo ".something { display: block; }" | #{FULL_COMMAND}`.include?('.something')
13
+ end
14
14
 
15
- assert @result.include?('.something')
15
+ should "accept a [-r | --root] argument and relative paths" do
16
+ %w(-r --root).each do |arg|
17
+ assert_correct_selectors_in_output(`#{COMMAND} #{arg} test/fixtures -s /style.css /index.html 2>/dev/null`)
18
+ end
16
19
  end
17
20
  end
18
21
 
@@ -28,13 +28,13 @@ class Test::Unit::TestCase
28
28
 
29
29
  def assert_reports_unused_selectors(output)
30
30
  UNUSED_SELECTORS.each do |s|
31
- assert output.include?(s)
31
+ assert output.include?(s), "output is missing #{s.inspect}:\n#{output}"
32
32
  end
33
33
  end
34
34
 
35
35
  def assert_does_not_report_used_selectors(output)
36
36
  USED_SELECTORS.each do |s|
37
- assert !output.include?(s)
37
+ assert !output.include?(s), "output should not contain #{s.inspect}:\n#{output}"
38
38
  end
39
39
  end
40
40
 
@@ -0,0 +1,13 @@
1
+ === Ruby CSS Parser CHANGELOG
2
+
3
+ ==== Version 0.9.1
4
+ * Fixed RuleSet#declaration_to_s so it would respect <tt>!important</tt>
5
+ rules (thanks to Dana - http://github.com/DanaDanger)
6
+
7
+ ==== Version 0.9
8
+ * Initial version forked from Premailer project
9
+
10
+ ==== TODO: Future
11
+ * border shorthand/folding support
12
+ * re-implement caching on CssParser.merge
13
+ * correctly parse http://www.webstandards.org/files/acid2/test.html
@@ -0,0 +1,21 @@
1
+ === Ruby CSS Parser License
2
+
3
+ Copyright (c) 2007 Alex Dunae
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,58 @@
1
+ === Ruby CSS Parser
2
+
3
+ Load, parse and cascade CSS rule sets in Ruby.
4
+
5
+ ==== Setup
6
+
7
+ Install the gem from RubyGems.
8
+
9
+ gem install css_parser
10
+
11
+ Done.
12
+
13
+ ==== An example
14
+ require 'css_parser'
15
+ include CssParser
16
+
17
+ parser = CssParser::Parser.new
18
+ parser.load_file!('http://example.com/styles/style.css')
19
+
20
+ # lookup a rule by a selector
21
+ parser.find('#content')
22
+ #=> 'font-size: 13px; line-height: 1.2;'
23
+
24
+ # lookup a rule by a selector and media type
25
+ parser.find('#content', [:screen, :handheld])
26
+
27
+ # iterate through selectors by media type
28
+ parser.each_selector(:screen) do |selector, declarations, specificity|
29
+ ...
30
+ end
31
+
32
+ # add a block of CSS
33
+ css = <<-EOT
34
+ body { margin: 0 1em; }
35
+ EOT
36
+
37
+ parser.add_block!(css)
38
+
39
+ # output all CSS rules in a single stylesheet
40
+ parser.to_s
41
+ => #content { font-size: 13px; line-height: 1.2; }
42
+ body { margin: 0 1em; }
43
+
44
+ ==== Testing
45
+
46
+ You can run the suite of unit tests using <tt>rake test</tt>.
47
+
48
+ The download/import tests require that WEBrick is installed. The tests set up
49
+ a temporary server on port 12000 and pull down files from the <tt>test/fixtures/</tt>
50
+ directory.
51
+
52
+ ==== Credits and code
53
+
54
+ By Alex Dunae (dunae.ca, e-mail 'code' at the same domain), 2007-08.
55
+
56
+ Thanks to Dana (http://github.com/DanaDanger) for the 0.9.1 update.
57
+
58
+ Made on Vancouver Island.