deadweight 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/README.md +123 -0
  2. data/lib/deadweight.rb +37 -11
  3. data/lib/deadweight/hijack.rb +13 -0
  4. data/lib/deadweight/hijack/rails.rb +35 -0
  5. data/lib/deadweight/rack/capturing_middleware.rb +26 -0
  6. data/vendor/gems/{css_parser-1.0.0 → css_parser-1.1.5}/lib/css_parser.rb +25 -12
  7. data/vendor/gems/{css_parser-1.0.0 → css_parser-1.1.5}/lib/css_parser/parser.rb +120 -54
  8. data/vendor/gems/{css_parser-1.0.0 → css_parser-1.1.5}/lib/css_parser/regexps.rb +1 -1
  9. data/vendor/gems/{css_parser-1.0.0 → css_parser-1.1.5}/lib/css_parser/rule_set.rb +24 -13
  10. data/vendor/gems/{css_parser-1.0.0 → css_parser-1.1.5}/test/fixtures/import-circular-reference.css +0 -0
  11. data/vendor/gems/{css_parser-1.0.0 → css_parser-1.1.5}/test/fixtures/import-with-media-types.css +0 -0
  12. data/vendor/gems/{css_parser-1.0.0 → css_parser-1.1.5}/test/fixtures/import1.css +0 -0
  13. data/vendor/gems/{css_parser-1.0.0 → css_parser-1.1.5}/test/fixtures/simple.css +0 -0
  14. data/vendor/gems/{css_parser-1.0.0 → css_parser-1.1.5}/test/fixtures/subdir/import2.css +0 -0
  15. data/vendor/gems/{css_parser-1.0.0 → css_parser-1.1.5}/test/test_css_parser_basic.rb +4 -1
  16. data/vendor/gems/css_parser-1.1.5/test/test_css_parser_loading.rb +139 -0
  17. data/vendor/gems/{css_parser-1.0.0 → css_parser-1.1.5}/test/test_css_parser_media_types.rb +39 -4
  18. data/vendor/gems/{css_parser-1.0.0 → css_parser-1.1.5}/test/test_css_parser_misc.rb +1 -2
  19. data/vendor/gems/{css_parser-1.0.0 → css_parser-1.1.5}/test/test_css_parser_regexps.rb +1 -1
  20. data/vendor/gems/css_parser-1.1.5/test/test_helper.rb +6 -0
  21. data/vendor/gems/{css_parser-1.0.0 → css_parser-1.1.5}/test/test_merging.rb +16 -1
  22. data/vendor/gems/{css_parser-1.0.0 → css_parser-1.1.5}/test/test_rule_set.rb +16 -1
  23. data/vendor/gems/{css_parser-1.0.0 → css_parser-1.1.5}/test/test_rule_set_creating_shorthand.rb +1 -1
  24. data/vendor/gems/{css_parser-1.0.0 → css_parser-1.1.5}/test/test_rule_set_expanding_shorthand.rb +1 -1
  25. metadata +79 -54
  26. data/.document +0 -5
  27. data/.gitignore +0 -6
  28. data/README.rdoc +0 -85
  29. data/Rakefile +0 -58
  30. data/VERSION +0 -1
  31. data/deadweight.gemspec +0 -84
  32. data/test/cli_test.rb +0 -21
  33. data/test/deadweight_test.rb +0 -72
  34. data/test/fixtures/index.html +0 -16
  35. data/test/fixtures/index2.html +0 -21
  36. data/test/fixtures/style.css +0 -24
  37. data/test/rake_task_test.rb +0 -26
  38. data/test/test_helper.rb +0 -47
  39. data/vendor/gems/css_parser-1.0.0/test/test_css_parser_downloading.rb +0 -81
  40. data/vendor/gems/css_parser-1.0.0/test/test_helper.rb +0 -8
@@ -16,7 +16,7 @@ module CssParser
16
16
  URI_RX = /url\(("([^"]*)"|'([^']*)'|([^)]*))\)/im
17
17
 
18
18
  # Initial parsing
19
- RE_AT_IMPORT_RULE = /\@import[\s]+(url\()?["']+(.[^'"]*)["']\)?([\w\s\,]*);?/i
19
+ RE_AT_IMPORT_RULE = /\@import[\s]+(url\()?["''"]?(.[^'"\s"']*)["''"]?\)?([\w\s\,^\])]*)\)?;?/
20
20
 
21
21
  #--
22
22
  #RE_AT_MEDIA_RULE = Regexp.new('(\"(.[^\n\r\f\\"]*|\\\\' + RE_NL.to_s + '|' + RE_ESCAPE.to_s + ')*\")')
@@ -14,6 +14,7 @@ module CssParser
14
14
  @selectors = []
15
15
  @specificity = specificity
16
16
  @declarations = {}
17
+ @order = 0
17
18
  parse_selectors!(selectors) if selectors
18
19
  parse_declarations!(block)
19
20
  end
@@ -57,7 +58,9 @@ module CssParser
57
58
  is_important = !value.gsub!(CssParser::IMPORTANT_IN_PROPERTY_RX, '').nil?
58
59
  property = property.downcase.strip
59
60
  #puts "SAVING #{property} #{value} #{is_important.inspect}"
60
- @declarations[property] = {:value => value, :is_important => is_important}
61
+ @declarations[property] = {
62
+ :value => value, :is_important => is_important, :order => @order += 1
63
+ }
61
64
  end
62
65
  alias_method :[]=, :add_declaration!
63
66
 
@@ -81,9 +84,9 @@ module CssParser
81
84
 
82
85
  # Iterate through declarations.
83
86
  def each_declaration # :yields: property, value, is_important
84
- @declarations.each do |property, data|
87
+ decs = @declarations.sort { |a,b| a[1][:order].nil? || b[1][:order].nil? ? 0 : a[1][:order] <=> b[1][:order] }
88
+ decs.each do |property, data|
85
89
  value = data[:value]
86
- #value += ' !important' if data[:is_important]
87
90
  yield property.downcase.strip, value.strip, data[:is_important]
88
91
  end
89
92
  end
@@ -95,8 +98,10 @@ module CssParser
95
98
  def declarations_to_s(options = {})
96
99
  options = {:force_important => false}.merge(options)
97
100
  str = ''
98
- importance = options[:force_important] ? ' !important' : ''
99
- each_declaration { |prop, val| str += "#{prop}: #{val}#{importance}; " }
101
+ each_declaration do |prop, val, is_important|
102
+ importance = (options[:force_important] || is_important) ? ' !important' : ''
103
+ str += "#{prop}: #{val}#{importance}; "
104
+ end
100
105
  str.gsub(/^[\s]+|[\n\r\f\t]*|[\s]+$/mx, '').strip
101
106
  end
102
107
 
@@ -154,6 +159,7 @@ public
154
159
 
155
160
  value = @declarations[property][:value]
156
161
  is_important = @declarations[property][:is_important]
162
+ order = @declarations[property][:order]
157
163
  t, r, b, l = nil
158
164
 
159
165
  matches = value.scan(CssParser::BOX_MODEL_UNITS_RX)
@@ -175,10 +181,11 @@ public
175
181
  l = matches[3][0]
176
182
  end
177
183
 
178
- @declarations["#{property}-top"] = {:value => t.to_s, :is_important => is_important}
179
- @declarations["#{property}-right"] = {:value => r.to_s, :is_important => is_important}
180
- @declarations["#{property}-bottom"] = {:value => b.to_s, :is_important => is_important}
181
- @declarations["#{property}-left"] = {:value => l.to_s, :is_important => is_important}
184
+ values = { :is_important => is_important, :order => order }
185
+ @declarations["#{property}-top"] = values.merge(:value => t.to_s)
186
+ @declarations["#{property}-right"] = values.merge(:value => r.to_s)
187
+ @declarations["#{property}-bottom"] = values.merge(:value => b.to_s)
188
+ @declarations["#{property}-left"] = values.merge(:value => l.to_s)
182
189
  @declarations.delete(property)
183
190
  end
184
191
  end
@@ -198,6 +205,7 @@ public
198
205
 
199
206
  value = @declarations['font'][:value]
200
207
  is_important = @declarations['font'][:is_important]
208
+ order = @declarations['font'][:order]
201
209
 
202
210
  in_fonts = false
203
211
 
@@ -232,7 +240,7 @@ public
232
240
  end
233
241
  end
234
242
 
235
- font_props.each { |font_prop, font_val| @declarations[font_prop] = {:value => font_val, :is_important => is_important} }
243
+ font_props.each { |font_prop, font_val| @declarations[font_prop] = {:value => font_val, :is_important => is_important, :order => order} }
236
244
 
237
245
  @declarations.delete('font')
238
246
  end
@@ -247,6 +255,7 @@ public
247
255
 
248
256
  value = @declarations['background'][:value]
249
257
  is_important = @declarations['background'][:is_important]
258
+ order = @declarations['background'][:order]
250
259
 
251
260
  bg_props = {}
252
261
 
@@ -283,7 +292,7 @@ public
283
292
  end
284
293
  end
285
294
 
286
- bg_props.each { |bg_prop, bg_val| @declarations[bg_prop] = {:value => bg_val, :is_important => is_important} }
295
+ bg_props.each { |bg_prop, bg_val| @declarations[bg_prop] = {:value => bg_val, :is_important => is_important, :order => order} }
287
296
 
288
297
  @declarations.delete('background')
289
298
  end
@@ -291,11 +300,13 @@ public
291
300
 
292
301
  # Looks for long format CSS background properties (e.g. <tt>background-color</tt>) and
293
302
  # converts them into a shorthand CSS <tt>background</tt> property.
303
+ #
304
+ # Leaves properties declared !important alone.
294
305
  def create_background_shorthand! # :nodoc:
295
306
  new_value = ''
296
307
  ['background-color', 'background-image', 'background-repeat',
297
308
  'background-position', 'background-attachment'].each do |property|
298
- if @declarations.has_key?(property)
309
+ if @declarations.has_key?(property) and not @declarations[property][:is_important]
299
310
  new_value += @declarations[property][:value] + ' '
300
311
  @declarations.delete(property)
301
312
  end
@@ -380,4 +391,4 @@ public
380
391
 
381
392
  end
382
393
  end
383
- end
394
+ end
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/test_helper'
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
2
 
3
3
  # Test cases for reading and generating CSS shorthand properties
4
4
  class CssParserBasicTests < Test::Unit::TestCase
@@ -10,6 +10,7 @@ class CssParserBasicTests < Test::Unit::TestCase
10
10
  html, body, p { margin: 0px; }
11
11
  p { padding: 0px; }
12
12
  #content { font: 12px/normal sans-serif; }
13
+ .content { color: red; }
13
14
  EOT
14
15
  end
15
16
 
@@ -17,6 +18,8 @@ class CssParserBasicTests < Test::Unit::TestCase
17
18
  @cp.add_block!(@css)
18
19
  assert_equal 'margin: 0px;', @cp.find_by_selector('body').join(' ')
19
20
  assert_equal 'margin: 0px; padding: 0px;', @cp.find_by_selector('p').join(' ')
21
+ assert_equal 'font: 12px/normal sans-serif;', @cp.find_by_selector('#content').join(' ')
22
+ assert_equal 'color: red;', @cp.find_by_selector('.content').join(' ')
20
23
  end
21
24
 
22
25
  def test_adding_block
@@ -0,0 +1,139 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
+
3
+ # Test cases for the CssParser's loading functions.
4
+ class CssParserLoadingTests < Test::Unit::TestCase
5
+ include CssParser
6
+ include WEBrick
7
+
8
+ def setup
9
+ # from http://nullref.se/blog/2006/5/17/testing-with-webrick
10
+ @cp = Parser.new
11
+
12
+ @uri_base = 'http://localhost:12000'
13
+
14
+ @www_root = File.dirname(__FILE__) + '/fixtures/'
15
+
16
+ @server_thread = Thread.new do
17
+ s = WEBrick::HTTPServer.new(:Port => 12000, :DocumentRoot => @www_root, :Logger => Log.new(nil, BasicLog::FATAL), :AccessLog => [])
18
+ @port = s.config[:Port]
19
+ begin
20
+ s.start
21
+ ensure
22
+ s.shutdown
23
+ end
24
+ end
25
+
26
+ sleep 1 # ensure the server has time to load
27
+ end
28
+
29
+ def teardown
30
+ @server_thread.kill
31
+ @server_thread.join(5)
32
+ @server_thread = nil
33
+ end
34
+
35
+ def test_loading_a_local_file
36
+ file_name = File.dirname(__FILE__) + '/fixtures/simple.css'
37
+ @cp.load_file!(file_name)
38
+ assert_equal 'margin: 0px;', @cp.find_by_selector('p').join(' ')
39
+ end
40
+
41
+ def test_loading_a_local_file_with_scheme
42
+ file_name = 'file://' + File.expand_path(File.dirname(__FILE__)) + '/fixtures/simple.css'
43
+ @cp.load_uri!(file_name)
44
+ assert_equal 'margin: 0px;', @cp.find_by_selector('p').join(' ')
45
+ end
46
+
47
+ def test_loading_a_remote_file
48
+ @cp.load_uri!("#{@uri_base}/simple.css")
49
+ assert_equal 'margin: 0px;', @cp.find_by_selector('p').join(' ')
50
+ end
51
+
52
+ # http://github.com/alexdunae/css_parser/issues#issue/4
53
+ def test_loading_a_remote_file_over_ssl
54
+ # TODO: test SSL locally
55
+ @cp.load_uri!("https://www.expresspardons.com/inc/screen.css")
56
+ assert_match /margin\: 0\;/, @cp.find_by_selector('body').join(' ')
57
+ end
58
+
59
+
60
+ def test_following_at_import_rules_local
61
+ base_dir = File.dirname(__FILE__) + '/fixtures'
62
+ @cp.load_file!('import1.css', base_dir)
63
+
64
+ # from '/import1.css'
65
+ assert_equal 'color: lime;', @cp.find_by_selector('div').join(' ')
66
+
67
+ # from '/subdir/import2.css'
68
+ assert_equal 'text-decoration: none;', @cp.find_by_selector('a').join(' ')
69
+
70
+ # from '/subdir/../simple.css'
71
+ assert_equal 'margin: 0px;', @cp.find_by_selector('p').join(' ')
72
+ end
73
+
74
+ def test_following_at_import_rules_remote
75
+ @cp.load_uri!("#{@uri_base}/import1.css")
76
+
77
+ # from '/import1.css'
78
+ assert_equal 'color: lime;', @cp.find_by_selector('div').join(' ')
79
+
80
+ # from '/subdir/import2.css'
81
+ assert_equal 'text-decoration: none;', @cp.find_by_selector('a').join(' ')
82
+
83
+ # from '/subdir/../simple.css'
84
+ assert_equal 'margin: 0px;', @cp.find_by_selector('p').join(' ')
85
+ end
86
+
87
+ def test_following_at_import_rules_from_add_block
88
+ css_block = '@import "../simple.css";'
89
+
90
+ @cp.add_block!(css_block, :base_uri => "#{@uri_base}/subdir/")
91
+
92
+ # from 'simple.css'
93
+ assert_equal 'margin: 0px;', @cp.find_by_selector('p').join(' ')
94
+ end
95
+
96
+ def test_importing_with_media_types
97
+ @cp.load_uri!("#{@uri_base}/import-with-media-types.css")
98
+
99
+ # from simple.css with :screen media type
100
+ assert_equal 'margin: 0px;', @cp.find_by_selector('p', :screen).join(' ')
101
+ assert_equal '', @cp.find_by_selector('p', :tty).join(' ')
102
+ end
103
+
104
+ def test_throwing_circular_reference_exception
105
+ assert_raise CircularReferenceError do
106
+ @cp.load_uri!("#{@uri_base}/import-circular-reference.css")
107
+ end
108
+
109
+ cp_without_exceptions = Parser.new(:io_exceptions => false)
110
+
111
+ assert_nothing_raised CircularReferenceError do
112
+ cp_without_exceptions.load_uri!("#{@uri_base}/import-circular-reference.css")
113
+ end
114
+
115
+ end
116
+
117
+ def test_toggling_circular_reference_exception
118
+ cp_without_exceptions = Parser.new(:io_exceptions => false)
119
+
120
+ assert_nothing_raised CircularReferenceError do
121
+ cp_without_exceptions.load_uri!("#{@uri_base}/import-circular-reference.css")
122
+ end
123
+ end
124
+
125
+ def test_toggling_not_found_exceptions
126
+ cp_with_exceptions = Parser.new(:io_exceptions => true)
127
+
128
+ assert_raise RemoteFileError do
129
+ cp_with_exceptions.load_uri!("#{@uri_base}/no-exist.xyz")
130
+ end
131
+
132
+ cp_without_exceptions = Parser.new(:io_exceptions => false)
133
+
134
+ assert_nothing_raised RemoteFileError do
135
+ cp_without_exceptions.load_uri!("#{@uri_base}/no-exist.xyz")
136
+ end
137
+ end
138
+
139
+ end
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/test_helper'
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
2
 
3
3
  # Test cases for the handling of media types
4
4
  class CssParserMediaTypesTests < Test::Unit::TestCase
@@ -28,7 +28,7 @@ class CssParserMediaTypesTests < Test::Unit::TestCase
28
28
  assert_equal 'font-size: 13px; line-height: 1.2;', @cp.find_by_selector('body', :screen).join(' ')
29
29
  end
30
30
 
31
- def atest_finding_by_multiple_media_types
31
+ def test_finding_by_multiple_media_types
32
32
  css = <<-EOT
33
33
  @media print {
34
34
  body { font-size: 10pt }
@@ -55,14 +55,49 @@ class CssParserMediaTypesTests < Test::Unit::TestCase
55
55
  assert_equal 'font-size: 10pt;', @cp.find_by_selector('body', :screen).join(' ')
56
56
  assert @cp.find_by_selector('body', :handheld).empty?
57
57
  end
58
+
59
+ def test_adding_block_and_limiting_media_types1
60
+ css = <<-EOT
61
+ @import "import1.css", print
62
+ EOT
63
+
64
+ base_dir = File.dirname(__FILE__) + '/fixtures/'
65
+
66
+ @cp.add_block!(css, :only_media_types => :screen, :base_dir => base_dir)
67
+ assert @cp.find_by_selector('div').empty?
68
+
69
+ end
70
+
71
+ def test_adding_block_and_limiting_media_types2
72
+ css = <<-EOT
73
+ @import "import1.css", print
74
+ EOT
75
+
76
+ base_dir = File.dirname(__FILE__) + '/fixtures/'
77
+
78
+ @cp.add_block!(css, :only_media_types => :print, :base_dir => base_dir)
79
+ assert_match 'color: lime', @cp.find_by_selector('div').join(' ')
80
+ end
81
+
82
+ def test_adding_block_and_limiting_media_types
83
+ css = <<-EOT
84
+ @import "import1.css"
85
+ EOT
86
+
87
+ base_dir = File.dirname(__FILE__) + '/fixtures/'
88
+
89
+ @cp.add_block!(css, :only_media_types => :print, :base_dir => base_dir)
90
+ assert_match 'color: lime', @cp.find_by_selector('div').join(' ')
91
+ end
92
+
58
93
 
59
- def atest_adding_rule_set_with_media_type
94
+ def test_adding_rule_set_with_media_type
60
95
  @cp.add_rule!('body', 'color: black;', [:handheld,:tty])
61
96
  @cp.add_rule!('body', 'color: blue;', :screen)
62
97
  assert_equal 'color: black;', @cp.find_by_selector('body', :handheld).join(' ')
63
98
  end
64
99
 
65
- def atest_selecting_with_all_meda_type
100
+ def test_selecting_with_all_meda_type
66
101
  @cp.add_rule!('body', 'color: black;', [:handheld,:tty])
67
102
  assert_equal 'color: black;', @cp.find_by_selector('body', :all).join(' ')
68
103
  end
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/test_helper'
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
2
 
3
3
  # Test cases for the CssParser.
4
4
  class CssParserTests < Test::Unit::TestCase
@@ -83,7 +83,6 @@ class CssParserTests < Test::Unit::TestCase
83
83
  end
84
84
 
85
85
  def test_ignoring_malformed_declarations
86
- flunk
87
86
  # dervived from http://www.w3.org/TR/CSS21/syndata.html#parsing-errors
88
87
  css = <<-EOT
89
88
  p { color:green }
@@ -1,5 +1,5 @@
1
1
  # coding: iso-8859-1
2
- require File.dirname(__FILE__) + '/test_helper'
2
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
3
3
 
4
4
  # Test cases for CSS regular expressions
5
5
  #
@@ -0,0 +1,6 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'net/http'
4
+ require 'open-uri'
5
+ require 'WEBrick'
6
+ require File.dirname(__FILE__) + '/../lib/css_parser'
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/test_helper'
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
2
 
3
3
  class MergingTests < Test::Unit::TestCase
4
4
  include CssParser
@@ -85,4 +85,19 @@ class MergingTests < Test::Unit::TestCase
85
85
  merged = CssParser.merge(rs)
86
86
  assert_equal rs.object_id, merged.object_id
87
87
  end
88
+
89
+ def test_merging_important
90
+ rs1 = RuleSet.new(nil, 'color: black !important;')
91
+ rs2 = RuleSet.new(nil, 'color: red;')
92
+ merged = CssParser.merge(rs1, rs2)
93
+ assert_equal 'black !important;', merged['color']
94
+ end
95
+
96
+ def test_merging_shorthand_important
97
+ rs1 = RuleSet.new(nil, 'background: black none !important;')
98
+ rs2 = RuleSet.new(nil, 'background-color: red;')
99
+ merged = CssParser.merge(rs1, rs2)
100
+ assert_equal 'black !important;', merged['background-color']
101
+ end
102
+
88
103
  end
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/test_helper'
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
2
  require "set"
3
3
 
4
4
  # Test cases for parsing CSS blocks
@@ -60,12 +60,27 @@ class RuleSetTests < Test::Unit::TestCase
60
60
  assert_equal(expected, actual)
61
61
  end
62
62
 
63
+ def test_each_declaration_respects_order
64
+ css_fragment = "margin: 0; padding: 20px; margin-bottom: 28px;"
65
+ rs = RuleSet.new(nil, css_fragment)
66
+ expected = %w(margin padding margin-bottom)
67
+ actual = []
68
+ rs.each_declaration { |prop, val, imp| actual << prop }
69
+ assert_equal(expected, actual)
70
+ end
71
+
63
72
  def test_declarations_to_s
64
73
  declarations = 'color: #fff; font-weight: bold;'
65
74
  rs = RuleSet.new('#content p, a', declarations)
66
75
  assert_equal(declarations.split(' ').sort, rs.declarations_to_s.split(' ').sort)
67
76
  end
68
77
 
78
+ def test_important_declarations_to_s
79
+ declarations = 'color: #fff; font-weight: bold !important;'
80
+ rs = RuleSet.new('#content p, a', declarations)
81
+ assert_equal(declarations.split(' ').sort, rs.declarations_to_s.split(' ').sort)
82
+ end
83
+
69
84
  def test_overriding_specificity
70
85
  rs = RuleSet.new('#content p, a', 'color: white', 1000)
71
86
  rs.each_selector do |sel, decs, spec|