sass 3.2.5 → 3.2.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/VERSION +1 -1
  2. data/VERSION_DATE +1 -1
  3. data/bin/sass +2 -1
  4. data/bin/sass-convert +2 -1
  5. data/bin/scss +2 -1
  6. data/lib/sass/cache_stores/chain.rb +1 -1
  7. data/lib/sass/cache_stores/filesystem.rb +0 -1
  8. data/lib/sass/engine.rb +7 -1
  9. data/lib/sass/importers/filesystem.rb +1 -1
  10. data/lib/sass/media.rb +1 -4
  11. data/lib/sass/script/funcall.rb +43 -8
  12. data/lib/sass/script/lexer.rb +0 -2
  13. data/lib/sass/script/parser.rb +0 -2
  14. data/lib/sass/scss/parser.rb +13 -1
  15. data/lib/sass/selector/simple_sequence.rb +1 -1
  16. data/lib/sass/tree/comment_node.rb +2 -2
  17. data/lib/sass/tree/visitors/cssize.rb +10 -1
  18. data/lib/sass/tree/visitors/perform.rb +4 -2
  19. data/lib/sass/util.rb +54 -1
  20. data/lib/sass/util/multibyte_string_scanner.rb +29 -8
  21. data/test/sass/engine_test.rb +16 -0
  22. data/test/sass/extend_test.rb +15 -0
  23. data/test/sass/script_test.rb +3 -1
  24. data/vendor/listen/CHANGELOG.md +76 -2
  25. data/vendor/listen/CONTRIBUTING.md +38 -0
  26. data/vendor/listen/Gemfile +8 -1
  27. data/vendor/listen/Guardfile +1 -1
  28. data/vendor/listen/LICENSE +1 -1
  29. data/vendor/listen/README.md +8 -5
  30. data/vendor/listen/lib/listen.rb +7 -5
  31. data/vendor/listen/lib/listen/adapter.rb +76 -29
  32. data/vendor/listen/lib/listen/adapters/bsd.rb +112 -0
  33. data/vendor/listen/lib/listen/adapters/darwin.rb +11 -10
  34. data/vendor/listen/lib/listen/adapters/linux.rb +33 -30
  35. data/vendor/listen/lib/listen/adapters/polling.rb +2 -1
  36. data/vendor/listen/lib/listen/adapters/windows.rb +27 -21
  37. data/vendor/listen/lib/listen/dependency_manager.rb +126 -0
  38. data/vendor/listen/lib/listen/directory_record.rb +63 -10
  39. data/vendor/listen/lib/listen/listener.rb +22 -0
  40. data/vendor/listen/lib/listen/multi_listener.rb +22 -0
  41. data/vendor/listen/lib/listen/version.rb +1 -1
  42. data/vendor/listen/listen.gemspec +0 -4
  43. data/vendor/listen/spec/listen/adapter_spec.rb +45 -4
  44. data/vendor/listen/spec/listen/adapters/bsd_spec.rb +36 -0
  45. data/vendor/listen/spec/listen/adapters/darwin_spec.rb +6 -0
  46. data/vendor/listen/spec/listen/adapters/linux_spec.rb +6 -0
  47. data/vendor/listen/spec/listen/adapters/windows_spec.rb +7 -1
  48. data/vendor/listen/spec/listen/dependency_manager_spec.rb +107 -0
  49. data/vendor/listen/spec/listen/directory_record_spec.rb +91 -4
  50. data/vendor/listen/spec/listen/listener_spec.rb +14 -0
  51. data/vendor/listen/spec/listen/multi_listener_spec.rb +19 -1
  52. data/vendor/listen/spec/spec_helper.rb +6 -3
  53. data/vendor/listen/spec/support/adapter_helper.rb +125 -212
  54. data/vendor/listen/spec/support/listeners_helper.rb +13 -1
  55. data/vendor/listen/spec/support/platform_helper.rb +4 -0
  56. metadata +9 -3
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.2.5
1
+ 3.2.6
@@ -1 +1 @@
1
- 05 January 2013 02:49:12 UTC
1
+ 23 February 2013 01:41:39 UTC
data/bin/sass CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
  # The command line Sass parser.
3
3
 
4
- require File.dirname(__FILE__) + '/../lib/sass'
4
+ THIS_FILE = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
5
+ require File.dirname(THIS_FILE) + '/../lib/sass'
5
6
  require 'sass/exec'
6
7
 
7
8
  opts = Sass::Exec::Sass.new(ARGV)
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require File.dirname(__FILE__) + '/../lib/sass'
3
+ THIS_FILE = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
4
+ require File.dirname(THIS_FILE) + '/../lib/sass'
4
5
  require 'sass/exec'
5
6
 
6
7
  opts = Sass::Exec::SassConvert.new(ARGV)
data/bin/scss CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
  # The command line Sass parser.
3
3
 
4
- require File.dirname(__FILE__) + '/../lib/sass'
4
+ THIS_FILE = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
5
+ require File.dirname(THIS_FILE) + '/../lib/sass'
5
6
  require 'sass/exec'
6
7
 
7
8
  opts = Sass::Exec::Scss.new(ARGV)
@@ -23,7 +23,7 @@ module Sass
23
23
  def retrieve(key, sha)
24
24
  @caches.each_with_index do |c, i|
25
25
  next unless obj = c.retrieve(key, sha)
26
- @caches[0...i].each {|c| c.store(key, sha, obj)}
26
+ @caches[0...i].each {|prev| prev.store(key, sha, obj)}
27
27
  return obj
28
28
  end
29
29
  nil
@@ -17,7 +17,6 @@ module Sass
17
17
  # @see Base#\_retrieve
18
18
  def _retrieve(key, version, sha)
19
19
  return unless File.readable?(path_to(key))
20
- contents = nil
21
20
  File.open(path_to(key), "rb") do |f|
22
21
  if f.readline("\n").strip == version && f.readline("\n").strip == sha
23
22
  return f.read
@@ -293,7 +293,7 @@ module Sass
293
293
  # @return [[Sass::Engine]] The dependency documents.
294
294
  def dependencies
295
295
  _dependencies(Set.new, engines = Set.new)
296
- engines - [self]
296
+ Sass::Util.array_minus(engines, [self])
297
297
  end
298
298
 
299
299
  # Helper for \{#dependencies}.
@@ -714,6 +714,12 @@ WARNING
714
714
  parser = Sass::SCSS::Parser.new(value, @options[:filename], @line)
715
715
  Tree::MediaNode.new(parser.parse_media_query_list.to_a)
716
716
  else
717
+ unprefixed_directive = directive.gsub(/^-[a-z0-9]+-/i, '')
718
+ if unprefixed_directive == 'supports'
719
+ parser = Sass::SCSS::Parser.new(value, @options[:filename], @line)
720
+ return Tree::SupportsNode.new(directive, parser.parse_supports_condition)
721
+ end
722
+
717
723
  Tree::DirectiveNode.new(
718
724
  value.nil? ? ["@#{directive}"] : ["@#{directive} "] + parse_interp(value, offset))
719
725
  end
@@ -30,7 +30,7 @@ module Sass
30
30
 
31
31
  # @see Base#mtime
32
32
  def mtime(name, options)
33
- file, s = Sass::Util.destructure(find_real_file(@root, name, options))
33
+ file, _ = Sass::Util.destructure(find_real_file(@root, name, options))
34
34
  File.mtime(file) if file
35
35
  rescue Errno::ENOENT
36
36
  nil
@@ -140,10 +140,7 @@ module Sass::Media
140
140
  type = t1
141
141
  mod = m1.empty? ? m2 : m1
142
142
  end
143
- q = Query.new([], [], other.expressions + expressions)
144
- q.type = [type]
145
- q.modifier = [mod]
146
- return q
143
+ return Query.new([mod], [type], other.expressions + expressions)
147
144
  end
148
145
 
149
146
  # Returns the CSS for the media query.
@@ -106,18 +106,53 @@ module Sass
106
106
  opts(Functions::EvaluationContext.new(environment.options).send(ruby_name, *args))
107
107
  end
108
108
  rescue ArgumentError => e
109
+ message = e.message
110
+
109
111
  # If this is a legitimate Ruby-raised argument error, re-raise it.
110
112
  # Otherwise, it's an error in the user's stylesheet, so wrap it.
111
- if e.message =~ /^wrong number of arguments \(\d+ for \d+\)/ &&
112
- e.backtrace[0] !~ /:in `(block in )?#{ruby_name}'$/ &&
113
- # JRuby (as of 1.6.7.2) doesn't put the actual method for
114
- # which the argument error was thrown in the backtrace, so
115
- # we detect whether our send threw an argument error.
116
- (RUBY_PLATFORM !~ /java/ || e.backtrace[0] !~ /:in `send'$/ ||
117
- e.backtrace[1] !~ /:in `_perform'$/)
113
+ if Sass::Util.rbx?
114
+ # Rubinius has a different error report string than vanilla Ruby. It
115
+ # also doesn't put the actual method for which the argument error was
116
+ # thrown in the backtrace, nor does it include `send`, so we look for
117
+ # `_perform`.
118
+ if e.message =~ /^method '([^']+)': given (\d+), expected (\d+)/
119
+ error_name, given, expected = $1, $2, $3
120
+ raise e if error_name != ruby_name || e.backtrace[0] !~ /:in `_perform'$/
121
+ message = "wrong number of arguments (#{given} for #{expected})"
122
+ end
123
+ elsif Sass::Util.jruby?
124
+ if Sass::Util.jruby1_6?
125
+ should_maybe_raise = e.message =~ /^wrong number of arguments \((\d+) for (\d+)\)/ &&
126
+ # The one case where JRuby does include the Ruby name of the function
127
+ # is manually-thrown ArgumentErrors, which are indistinguishable from
128
+ # legitimate ArgumentErrors. We treat both of these as
129
+ # Sass::SyntaxErrors even though it can hide Ruby errors.
130
+ e.backtrace[0] !~ /:in `(block in )?#{ruby_name}'$/
131
+ else
132
+ should_maybe_raise = e.message =~ /^wrong number of arguments calling `[^`]+` \((\d+) for (\d+)\)/
133
+ given, expected = $1, $2
134
+ end
135
+
136
+ if should_maybe_raise
137
+ # JRuby 1.7 includes __send__ before send and _perform.
138
+ trace = e.backtrace.dup
139
+ raise e if !Sass::Util.jruby1_6? && trace.shift !~ /:in `__send__'$/
140
+
141
+ # JRuby (as of 1.7.2) doesn't put the actual method
142
+ # for which the argument error was thrown in the backtrace, so we
143
+ # detect whether our send threw an argument error.
144
+ if !(trace[0] =~ /:in `send'$/ && trace[1] =~ /:in `_perform'$/)
145
+ raise e
146
+ elsif !Sass::Util.jruby1_6?
147
+ # JRuby 1.7 doesn't use standard formatting for its ArgumentErrors.
148
+ message = "wrong number of arguments (#{given} for #{expected})"
149
+ end
150
+ end
151
+ elsif e.message =~ /^wrong number of arguments \(\d+ for \d+\)/ &&
152
+ e.backtrace[0] !~ /:in `(block in )?#{ruby_name}'$/
118
153
  raise e
119
154
  end
120
- raise Sass::SyntaxError.new("#{e.message} for `#{name}'")
155
+ raise Sass::SyntaxError.new("#{message} for `#{name}'")
121
156
  end
122
157
 
123
158
  # This method is factored out from `_perform` so that compass can override
@@ -245,8 +245,6 @@ module Sass
245
245
  end
246
246
 
247
247
  def _variable(rx)
248
- line = @line
249
- offset = @offset
250
248
  return unless scan(rx)
251
249
 
252
250
  [:const, @scanner[2]]
@@ -346,8 +346,6 @@ RUBY
346
346
  splat = nil
347
347
  must_have_default = false
348
348
  loop do
349
- line = @lexer.line
350
- offset = @lexer.offset + 1
351
349
  c = assert_tok(:const)
352
350
  var = Script::Variable.new(c.value)
353
351
  if try_tok(:colon)
@@ -52,6 +52,18 @@ module Sass
52
52
  ql
53
53
  end
54
54
 
55
+ # Parses a supports query condition.
56
+ #
57
+ # @return [Sass::Supports::Condition] The parsed condition
58
+ # @raise [Sass::SyntaxError] if there's a syntax error in the condition,
59
+ # or if it doesn't take up the entire input string.
60
+ def parse_supports_condition
61
+ init_scanner!
62
+ condition = supports_condition
63
+ expected("supports condition") unless @scanner.eos?
64
+ condition
65
+ end
66
+
55
67
  private
56
68
 
57
69
  include Sass::SCSS::RX
@@ -986,7 +998,7 @@ MESSAGE
986
998
  line = @line
987
999
  @strs.push ""
988
1000
  throw_error {yield} && @strs.last
989
- rescue Sass::SyntaxError => e
1001
+ rescue Sass::SyntaxError
990
1002
  @scanner.pos = pos
991
1003
  @line = line
992
1004
  nil
@@ -101,7 +101,7 @@ module Sass
101
101
  # If A {@extend B} and C {...},
102
102
  # seq is A, sels is B, and self is C
103
103
 
104
- self_without_sel = self.members - sels
104
+ self_without_sel = Sass::Util.array_minus(self.members, sels)
105
105
  group.each {|e, _| e.result = :failed_to_unify unless e.result == :succeeded}
106
106
  next unless unified = seq.members.last.unify(self_without_sel, subject?)
107
107
  group.each {|e, _| e.result = :succeeded}
@@ -70,13 +70,13 @@ module Sass::Tree
70
70
  private
71
71
 
72
72
  def normalize_indentation(str)
73
- pre = str.split("\n").inject(str[/^[ \t]*/].split("")) do |pre, line|
73
+ ind = str.split("\n").inject(str[/^[ \t]*/].split("")) do |pre, line|
74
74
  line[/^[ \t]*/].split("").zip(pre).inject([]) do |arr, (a, b)|
75
75
  break arr if a != b
76
76
  arr << a
77
77
  end
78
78
  end.join
79
- str.gsub(/^#{pre}/, '')
79
+ str.gsub(/^#{ind}/, '')
80
80
  end
81
81
  end
82
82
  end
@@ -32,6 +32,8 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
32
32
  end
33
33
  end
34
34
 
35
+ MERGEABLE_DIRECTIVES = [Sass::Tree::MediaNode]
36
+
35
37
  # Runs a block of code with the current parent node
36
38
  # replaced with the given node.
37
39
  #
@@ -39,11 +41,18 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
39
41
  # @yield A block in which the parent is set to `parent`.
40
42
  # @return [Object] The return value of the block.
41
43
  def with_parent(parent)
42
- @parent_directives.push parent if parent.is_a?(Sass::Tree::DirectiveNode)
44
+ if parent.is_a?(Sass::Tree::DirectiveNode)
45
+ if MERGEABLE_DIRECTIVES.any? {|klass| parent.is_a?(klass)}
46
+ old_parent_directive = @parent_directives.pop
47
+ end
48
+ @parent_directives.push parent
49
+ end
50
+
43
51
  old_parent, @parent = @parent, parent
44
52
  yield
45
53
  ensure
46
54
  @parent_directives.pop if parent.is_a?(Sass::Tree::DirectiveNode)
55
+ @parent_directives.push old_parent_directive if old_parent_directive
47
56
  @parent = old_parent
48
57
  end
49
58
 
@@ -14,11 +14,13 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
14
14
 
15
15
  begin
16
16
  unless keywords.empty?
17
- unknown_args = keywords.keys - callable.args.map {|var| var.first.underscored_name}
17
+ unknown_args = Sass::Util.array_minus(keywords.keys,
18
+ callable.args.map {|var| var.first.underscored_name})
18
19
  if callable.splat && unknown_args.include?(callable.splat.underscored_name)
19
20
  raise Sass::SyntaxError.new("Argument $#{callable.splat.name} of #{downcase_desc} cannot be used as a named argument.")
20
21
  elsif unknown_args.any?
21
- raise Sass::SyntaxError.new("#{desc} doesn't have #{unknown_args.length > 1 ? 'the following arguments:' : 'an argument named'} #{unknown_args.map{|name| "$#{name}"}.join ', '}.")
22
+ description = unknown_args.length > 1 ? 'the following arguments:' : 'an argument named'
23
+ raise Sass::SyntaxError.new("#{desc} doesn't have #{description} #{unknown_args.map {|name| "$#{name}"}.join ', '}.")
22
24
  end
23
25
  end
24
26
  rescue Sass::SyntaxError => keyword_exception
@@ -256,6 +256,33 @@ module Sass
256
256
  arr
257
257
  end
258
258
 
259
+ # Returns a sub-array of `minuend` containing only elements that are also in
260
+ # `subtrahend`. Ensures that the return value has the same order as
261
+ # `minuend`, even on Rubinius where that's not guaranteed by {Array#-}.
262
+ #
263
+ # @param minuend [Array]
264
+ # @param subtrahend [Array]
265
+ # @return [Array]
266
+ def array_minus(minuend, subtrahend)
267
+ return minuend - subtrahend unless rbx?
268
+ set = Set.new(minuend) - subtrahend
269
+ minuend.select {|e| set.include?(e)}
270
+ end
271
+
272
+ # Returns a string description of the character that caused an
273
+ # `Encoding::UndefinedConversionError`.
274
+ #
275
+ # @param [Encoding::UndefinedConversionError]
276
+ # @return [String]
277
+ def undefined_conversion_error_char(e)
278
+ # Rubinius (as of 2.0.0.rc1) pre-quotes the error character.
279
+ return e.error_char if rbx?
280
+ # JRuby (as of 1.7.2) doesn't have an error_char field on
281
+ # Encoding::UndefinedConversionError.
282
+ return e.error_char.dump unless jruby?
283
+ e.message[/^"[^"]+"/] #"
284
+ end
285
+
259
286
  # Asserts that `value` falls within `range` (inclusive), leaving
260
287
  # room for slight floating-point errors.
261
288
  #
@@ -462,6 +489,27 @@ module Sass
462
489
  RUBY_ENGINE == "ironruby"
463
490
  end
464
491
 
492
+ # Whether or not this is running on Rubinius.
493
+ #
494
+ # @return [Boolean]
495
+ def rbx?
496
+ RUBY_ENGINE == "rbx"
497
+ end
498
+
499
+ # Whether or not this is running on JRuby.
500
+ #
501
+ # @return [Boolean]
502
+ def jruby?
503
+ RUBY_PLATFORM =~ /java/
504
+ end
505
+
506
+ # Returns an array of ints representing the JRuby version number.
507
+ #
508
+ # @return [Array<Fixnum>]
509
+ def jruby_version
510
+ $jruby_version ||= ::JRUBY_VERSION.split(".").map {|s| s.to_i}
511
+ end
512
+
465
513
  # Like `Dir.glob`, but works with backslash-separated paths on Windows.
466
514
  #
467
515
  # @param path [String]
@@ -512,6 +560,11 @@ module Sass
512
560
  ruby1_8? && Sass::Util::RUBY_VERSION[2] < 7
513
561
  end
514
562
 
563
+ # Wehter or not this is running under JRuby 1.6 or lower.
564
+ def jruby1_6?
565
+ jruby? && jruby_version[0] == 1 && jruby_version[1] < 7
566
+ end
567
+
515
568
  # Whether or not this is running under MacRuby.
516
569
  #
517
570
  # @return [Boolean]
@@ -548,7 +601,7 @@ module Sass
548
601
  line.encode(encoding)
549
602
  rescue Encoding::UndefinedConversionError => e
550
603
  yield <<MSG.rstrip, i + 1
551
- Invalid #{encoding.name} character #{e.error_char.dump}
604
+ Invalid #{encoding.name} character #{undefined_conversion_error_char(e)}
552
605
  MSG
553
606
  end
554
607
  end
@@ -3,23 +3,44 @@ require 'strscan'
3
3
  if Sass::Util.ruby1_8?
4
4
  Sass::Util::MultibyteStringScanner = StringScanner
5
5
  else
6
+ if Sass::Util.rbx?
7
+ # Rubinius's StringScanner class implements some of its methods in terms of
8
+ # others, which causes us to double-count bytes in some cases if we do
9
+ # straightforward inheritance. To work around this, we use a delegate class.
10
+ require 'delegate'
11
+ class Sass::Util::MultibyteStringScanner < DelegateClass(StringScanner)
12
+ def initialize(str)
13
+ super(StringScanner.new(str))
14
+ @mb_pos = 0
15
+ @mb_matched_size = nil
16
+ @mb_last_pos = nil
17
+ end
18
+
19
+ def is_a?(klass)
20
+ __getobj__.is_a?(klass) || super
21
+ end
22
+ end
23
+ else
24
+ class Sass::Util::MultibyteStringScanner < StringScanner
25
+ def initialize(str)
26
+ super
27
+ @mb_pos = 0
28
+ @mb_matched_size = nil
29
+ @mb_last_pos = nil
30
+ end
31
+ end
32
+ end
33
+
6
34
  # A wrapper of the native StringScanner class that works correctly with
7
35
  # multibyte character encodings. The native class deals only in bytes, not
8
36
  # characters, for methods like [#pos] and [#matched_size]. This class deals
9
37
  # only in characters, instead.
10
- class Sass::Util::MultibyteStringScanner < StringScanner
38
+ class Sass::Util::MultibyteStringScanner
11
39
  def self.new(str)
12
40
  return StringScanner.new(str) if str.ascii_only?
13
41
  super
14
42
  end
15
43
 
16
- def initialize(str)
17
- super
18
- @mb_pos = 0
19
- @mb_matched_size = nil
20
- @mb_last_pos = nil
21
- end
22
-
23
44
  alias_method :byte_pos, :pos
24
45
  alias_method :byte_matched_size, :matched_size
25
46
 
@@ -2381,6 +2381,22 @@ SASS
2381
2381
 
2382
2382
  # Regression tests
2383
2383
 
2384
+ def test_supports_bubbles
2385
+ assert_equal <<CSS, render(<<SASS)
2386
+ parent {
2387
+ background: orange; }
2388
+ @supports (perspective: 10px) or (-moz-perspective: 10px) {
2389
+ parent child {
2390
+ background: blue; } }
2391
+ CSS
2392
+ parent
2393
+ background: orange
2394
+ @supports (perspective: 10px) or (-moz-perspective: 10px)
2395
+ child
2396
+ background: blue
2397
+ SASS
2398
+ end
2399
+
2384
2400
  def test_line_numbers_with_dos_line_endings
2385
2401
  assert_equal <<CSS, render(<<SASS, :line_comments => true)
2386
2402
  /* line 5, test_line_numbers_with_dos_line_endings_inline.sass */
@@ -1186,6 +1186,21 @@ SCSS
1186
1186
 
1187
1187
  # Regression Tests
1188
1188
 
1189
+ def test_extend_in_double_nested_media_query
1190
+ assert_equal <<CSS, render(<<SCSS)
1191
+ @media all and (orientation: landscape) {
1192
+ .bar {
1193
+ color: blue; } }
1194
+ CSS
1195
+ @media all {
1196
+ @media (orientation: landscape) {
1197
+ %foo {color: blue}
1198
+ .bar {@extend %foo}
1199
+ }
1200
+ }
1201
+ SCSS
1202
+ end
1203
+
1189
1204
  def test_partially_failed_extend
1190
1205
  assert_no_warning {assert_equal(<<CSS, render(<<SCSS))}
1191
1206
  .rc, test {