deadweight 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +17 -5
- data/Rakefile +0 -1
- data/VERSION +1 -1
- data/deadweight.gemspec +29 -9
- data/lib/deadweight.rb +51 -15
- data/lib/deadweight/cli.rb +8 -2
- data/test/cli_test.rb +9 -6
- data/test/test_helper.rb +2 -2
- data/vendor/gems/css_parser-0.9.1/CHANGELOG +13 -0
- data/vendor/gems/css_parser-0.9.1/LICENSE +21 -0
- data/vendor/gems/css_parser-0.9.1/README +58 -0
- data/vendor/gems/css_parser-0.9.1/lib/css_parser.rb +149 -0
- data/vendor/gems/css_parser-0.9.1/lib/css_parser/parser.rb +345 -0
- data/vendor/gems/css_parser-0.9.1/lib/css_parser/regexps.rb +46 -0
- data/vendor/gems/css_parser-0.9.1/lib/css_parser/rule_set.rb +380 -0
- data/vendor/gems/css_parser-0.9.1/test/fixtures/import-circular-reference.css +4 -0
- data/vendor/gems/css_parser-0.9.1/test/fixtures/import-with-media-types.css +3 -0
- data/vendor/gems/css_parser-0.9.1/test/fixtures/import1.css +3 -0
- data/vendor/gems/css_parser-0.9.1/test/fixtures/simple.css +6 -0
- data/vendor/gems/css_parser-0.9.1/test/fixtures/subdir/import2.css +3 -0
- data/vendor/gems/css_parser-0.9.1/test/test_css_parser_basic.rb +56 -0
- data/vendor/gems/css_parser-0.9.1/test/test_css_parser_downloading.rb +81 -0
- data/vendor/gems/css_parser-0.9.1/test/test_css_parser_media_types.rb +71 -0
- data/vendor/gems/css_parser-0.9.1/test/test_css_parser_misc.rb +143 -0
- data/vendor/gems/css_parser-0.9.1/test/test_css_parser_regexps.rb +68 -0
- data/vendor/gems/css_parser-0.9.1/test/test_helper.rb +8 -0
- data/vendor/gems/css_parser-0.9.1/test/test_merging.rb +88 -0
- data/vendor/gems/css_parser-0.9.1/test/test_rule_set.rb +74 -0
- data/vendor/gems/css_parser-0.9.1/test/test_rule_set_creating_shorthand.rb +90 -0
- data/vendor/gems/css_parser-0.9.1/test/test_rule_set_expanding_shorthand.rb +178 -0
- metadata +25 -13
data/README.rdoc
CHANGED
@@ -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
|
-
===
|
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
|
-
|
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
|
-
|
38
|
+
There's also experimental support for Lyndon (http://github.com/defunkt/lyndon) with <tt>-L</tt>.
|
35
39
|
|
36
|
-
|
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
|
-
-
|
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
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.2
|
data/deadweight.gemspec
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
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.
|
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-
|
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.
|
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
|
+
|
data/lib/deadweight.rb
CHANGED
@@ -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
|
-
|
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.
|
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
|
-
|
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.
|
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.
|
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
|
-
|
118
|
-
|
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
|
-
|
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 ||=
|
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.
|
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'
|
data/lib/deadweight/cli.rb
CHANGED
@@ -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
|
data/test/cli_test.rb
CHANGED
@@ -1,18 +1,21 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class CliTest < Test::Unit::TestCase
|
4
|
-
COMMAND
|
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
|
-
|
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
|
-
|
12
|
+
assert `echo ".something { display: block; }" | #{FULL_COMMAND}`.include?('.something')
|
13
|
+
end
|
14
14
|
|
15
|
-
|
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
|
|
data/test/test_helper.rb
CHANGED
@@ -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.
|