sass 3.3.0 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +58 -50
  4. data/Rakefile +1 -4
  5. data/VERSION +1 -1
  6. data/VERSION_DATE +1 -1
  7. data/VERSION_NAME +1 -1
  8. data/bin/sass +1 -1
  9. data/bin/scss +1 -1
  10. data/lib/sass/cache_stores/filesystem.rb +6 -2
  11. data/lib/sass/css.rb +1 -3
  12. data/lib/sass/engine.rb +37 -46
  13. data/lib/sass/environment.rb +13 -17
  14. data/lib/sass/error.rb +6 -9
  15. data/lib/sass/exec/base.rb +187 -0
  16. data/lib/sass/exec/sass_convert.rb +264 -0
  17. data/lib/sass/exec/sass_scss.rb +424 -0
  18. data/lib/sass/exec.rb +5 -771
  19. data/lib/sass/features.rb +7 -0
  20. data/lib/sass/importers/base.rb +7 -2
  21. data/lib/sass/importers/filesystem.rb +9 -25
  22. data/lib/sass/importers.rb +0 -1
  23. data/lib/sass/media.rb +1 -4
  24. data/lib/sass/plugin/compiler.rb +200 -83
  25. data/lib/sass/plugin/staleness_checker.rb +1 -1
  26. data/lib/sass/plugin.rb +3 -3
  27. data/lib/sass/script/css_lexer.rb +1 -1
  28. data/lib/sass/script/functions.rb +622 -268
  29. data/lib/sass/script/lexer.rb +99 -34
  30. data/lib/sass/script/parser.rb +24 -23
  31. data/lib/sass/script/tree/funcall.rb +1 -1
  32. data/lib/sass/script/tree/interpolation.rb +20 -2
  33. data/lib/sass/script/tree/selector.rb +26 -0
  34. data/lib/sass/script/tree/string_interpolation.rb +1 -1
  35. data/lib/sass/script/tree.rb +1 -0
  36. data/lib/sass/script/value/base.rb +7 -5
  37. data/lib/sass/script/value/bool.rb +0 -5
  38. data/lib/sass/script/value/color.rb +39 -21
  39. data/lib/sass/script/value/helpers.rb +107 -0
  40. data/lib/sass/script/value/list.rb +0 -15
  41. data/lib/sass/script/value/null.rb +0 -5
  42. data/lib/sass/script/value/number.rb +62 -14
  43. data/lib/sass/script/value/string.rb +59 -11
  44. data/lib/sass/script/value.rb +0 -1
  45. data/lib/sass/scss/css_parser.rb +8 -2
  46. data/lib/sass/scss/parser.rb +190 -328
  47. data/lib/sass/scss/rx.rb +15 -6
  48. data/lib/sass/scss/static_parser.rb +298 -1
  49. data/lib/sass/selector/abstract_sequence.rb +28 -13
  50. data/lib/sass/selector/comma_sequence.rb +92 -13
  51. data/lib/sass/selector/pseudo.rb +256 -0
  52. data/lib/sass/selector/sequence.rb +94 -24
  53. data/lib/sass/selector/simple.rb +14 -25
  54. data/lib/sass/selector/simple_sequence.rb +97 -33
  55. data/lib/sass/selector.rb +57 -194
  56. data/lib/sass/shared.rb +1 -1
  57. data/lib/sass/source/map.rb +26 -12
  58. data/lib/sass/stack.rb +0 -6
  59. data/lib/sass/supports.rb +2 -3
  60. data/lib/sass/tree/at_root_node.rb +1 -0
  61. data/lib/sass/tree/charset_node.rb +1 -1
  62. data/lib/sass/tree/directive_node.rb +8 -2
  63. data/lib/sass/tree/error_node.rb +18 -0
  64. data/lib/sass/tree/extend_node.rb +1 -1
  65. data/lib/sass/tree/function_node.rb +4 -0
  66. data/lib/sass/tree/keyframe_rule_node.rb +15 -0
  67. data/lib/sass/tree/prop_node.rb +1 -1
  68. data/lib/sass/tree/rule_node.rb +12 -7
  69. data/lib/sass/tree/visitors/check_nesting.rb +38 -10
  70. data/lib/sass/tree/visitors/convert.rb +16 -18
  71. data/lib/sass/tree/visitors/cssize.rb +29 -29
  72. data/lib/sass/tree/visitors/deep_copy.rb +5 -0
  73. data/lib/sass/tree/visitors/perform.rb +45 -33
  74. data/lib/sass/tree/visitors/set_options.rb +14 -0
  75. data/lib/sass/tree/visitors/to_css.rb +15 -14
  76. data/lib/sass/util/subset_map.rb +1 -1
  77. data/lib/sass/util.rb +222 -99
  78. data/lib/sass/version.rb +5 -5
  79. data/lib/sass.rb +0 -5
  80. data/test/sass/cache_test.rb +62 -20
  81. data/test/sass/callbacks_test.rb +1 -1
  82. data/test/sass/compiler_test.rb +19 -10
  83. data/test/sass/conversion_test.rb +58 -1
  84. data/test/sass/css2sass_test.rb +23 -4
  85. data/test/sass/encoding_test.rb +219 -0
  86. data/test/sass/engine_test.rb +136 -199
  87. data/test/sass/exec_test.rb +2 -2
  88. data/test/sass/extend_test.rb +236 -19
  89. data/test/sass/functions_test.rb +295 -253
  90. data/test/sass/importer_test.rb +31 -21
  91. data/test/sass/logger_test.rb +1 -1
  92. data/test/sass/more_results/more_import.css +1 -1
  93. data/test/sass/plugin_test.rb +14 -13
  94. data/test/sass/results/compact.css +1 -1
  95. data/test/sass/results/complex.css +4 -4
  96. data/test/sass/results/expanded.css +1 -1
  97. data/test/sass/results/import.css +1 -1
  98. data/test/sass/results/import_charset_ibm866.css +2 -2
  99. data/test/sass/results/mixins.css +17 -17
  100. data/test/sass/results/nested.css +1 -1
  101. data/test/sass/results/parent_ref.css +2 -2
  102. data/test/sass/results/script.css +3 -3
  103. data/test/sass/results/scss_import.css +1 -1
  104. data/test/sass/script_conversion_test.rb +10 -7
  105. data/test/sass/script_test.rb +288 -74
  106. data/test/sass/scss/css_test.rb +141 -24
  107. data/test/sass/scss/rx_test.rb +4 -4
  108. data/test/sass/scss/scss_test.rb +457 -18
  109. data/test/sass/source_map_test.rb +115 -25
  110. data/test/sass/superselector_test.rb +191 -0
  111. data/test/sass/templates/scss_import.scss +2 -1
  112. data/test/sass/test_helper.rb +1 -1
  113. data/test/sass/util/multibyte_string_scanner_test.rb +1 -1
  114. data/test/sass/util/normalized_map_test.rb +1 -1
  115. data/test/sass/util/subset_map_test.rb +2 -2
  116. data/test/sass/util_test.rb +31 -1
  117. data/test/sass/value_helpers_test.rb +5 -7
  118. data/test/test_helper.rb +2 -2
  119. data/vendor/listen/CHANGELOG.md +1 -228
  120. data/vendor/listen/Gemfile +5 -15
  121. data/vendor/listen/README.md +111 -77
  122. data/vendor/listen/Rakefile +0 -42
  123. data/vendor/listen/lib/listen/adapter.rb +195 -82
  124. data/vendor/listen/lib/listen/adapters/bsd.rb +27 -64
  125. data/vendor/listen/lib/listen/adapters/darwin.rb +21 -58
  126. data/vendor/listen/lib/listen/adapters/linux.rb +23 -55
  127. data/vendor/listen/lib/listen/adapters/polling.rb +25 -34
  128. data/vendor/listen/lib/listen/adapters/windows.rb +50 -46
  129. data/vendor/listen/lib/listen/directory_record.rb +96 -61
  130. data/vendor/listen/lib/listen/listener.rb +135 -37
  131. data/vendor/listen/lib/listen/turnstile.rb +9 -5
  132. data/vendor/listen/lib/listen/version.rb +1 -1
  133. data/vendor/listen/lib/listen.rb +33 -19
  134. data/vendor/listen/listen.gemspec +6 -0
  135. data/vendor/listen/spec/listen/adapter_spec.rb +43 -77
  136. data/vendor/listen/spec/listen/adapters/polling_spec.rb +8 -8
  137. data/vendor/listen/spec/listen/directory_record_spec.rb +81 -56
  138. data/vendor/listen/spec/listen/listener_spec.rb +128 -39
  139. data/vendor/listen/spec/listen_spec.rb +15 -21
  140. data/vendor/listen/spec/spec_helper.rb +4 -0
  141. data/vendor/listen/spec/support/adapter_helper.rb +52 -15
  142. data/vendor/listen/spec/support/directory_record_helper.rb +7 -5
  143. data/vendor/listen/spec/support/listeners_helper.rb +30 -7
  144. metadata +25 -22
  145. data/ext/mkrf_conf.rb +0 -27
  146. data/lib/sass/importers/deprecated_path.rb +0 -51
  147. data/lib/sass/script/value/deprecated_false.rb +0 -55
  148. data/vendor/listen/lib/listen/dependency_manager.rb +0 -126
  149. data/vendor/listen/lib/listen/multi_listener.rb +0 -143
  150. data/vendor/listen/spec/listen/dependency_manager_spec.rb +0 -107
  151. data/vendor/listen/spec/listen/multi_listener_spec.rb +0 -174
@@ -121,8 +121,115 @@ module Sass::Script::Value
121
121
  end
122
122
  alias_method :identifier, :unquoted_string
123
123
 
124
+ # Parses a user-provided selector.
125
+ #
126
+ # @param value [Sass::Script::Value::String, Sass::Script::Value::List]
127
+ # The selector to parse. This can be either a string, a list of
128
+ # strings, or a list of lists of strings as returned by `&`.
129
+ # @param name [Symbol, nil]
130
+ # If provided, the name of the selector argument. This is used
131
+ # for error reporting.
132
+ # @param allow_parent_ref [Boolean]
133
+ # Whether the parsed selector should allow parent references.
134
+ # @return [Sass::Selector::CommaSequence] The parsed selector.
135
+ # @throw [ArgumentError] if the parse failed for any reason.
136
+ def parse_selector(value, name = nil, allow_parent_ref = false)
137
+ str = normalize_selector(value, name)
138
+ begin
139
+ Sass::SCSS::StaticParser.new(str, nil, nil, 1, 1, allow_parent_ref).parse_selector
140
+ rescue Sass::SyntaxError => e
141
+ err = "#{value.inspect} is not a valid selector: #{e}"
142
+ err = "$#{name.to_s.gsub('_', '-')}: #{err}" if name
143
+ raise ArgumentError.new(err)
144
+ end
145
+ end
146
+
147
+ # Parses a user-provided complex selector.
148
+ #
149
+ # A complex selector can contain combinators but cannot contain commas.
150
+ #
151
+ # @param value [Sass::Script::Value::String, Sass::Script::Value::List]
152
+ # The selector to parse. This can be either a string or a list of
153
+ # strings.
154
+ # @param name [Symbol, nil]
155
+ # If provided, the name of the selector argument. This is used
156
+ # for error reporting.
157
+ # @param allow_parent_ref [Boolean]
158
+ # Whether the parsed selector should allow parent references.
159
+ # @return [Sass::Selector::Sequence] The parsed selector.
160
+ # @throw [ArgumentError] if the parse failed for any reason.
161
+ def parse_complex_selector(value, name = nil, allow_parent_ref = false)
162
+ selector = parse_selector(value, name, allow_parent_ref)
163
+ return seq if selector.members.length == 1
164
+
165
+ err = "#{value.inspect} is not a complex selector"
166
+ err = "$#{name.to_s.gsub('_', '-')}: #{err}" if name
167
+ raise ArgumentError.new(err)
168
+ end
169
+
170
+ # Parses a user-provided compound selector.
171
+ #
172
+ # A compound selector cannot contain combinators or commas.
173
+ #
174
+ # @param value [Sass::Script::Value::String] The selector to parse.
175
+ # @param name [Symbol, nil]
176
+ # If provided, the name of the selector argument. This is used
177
+ # for error reporting.
178
+ # @param allow_parent_ref [Boolean]
179
+ # Whether the parsed selector should allow parent references.
180
+ # @return [Sass::Selector::SimpleSequence] The parsed selector.
181
+ # @throw [ArgumentError] if the parse failed for any reason.
182
+ def parse_compound_selector(value, name = nil, allow_parent_ref = false)
183
+ assert_type value, :String, name
184
+ selector = parse_selector(value, name, allow_parent_ref)
185
+ seq = selector.members.first
186
+ sseq = seq.members.first
187
+ if selector.members.length == 1 && seq.members.length == 1 &&
188
+ sseq.is_a?(Sass::Selector::SimpleSequence)
189
+ return sseq
190
+ end
191
+
192
+ err = "#{value.inspect} is not a compound selector"
193
+ err = "$#{name.to_s.gsub('_', '-')}: #{err}" if name
194
+ raise ArgumentError.new(err)
195
+ end
196
+
124
197
  private
125
198
 
199
+ # Converts a user-provided selector into string form or throws an
200
+ # ArgumentError if it's in an invalid format.
201
+ def normalize_selector(value, name)
202
+ if (str = selector_to_str(value))
203
+ return str
204
+ end
205
+
206
+ err = "#{value.inspect} is not a valid selector: it must be a string,\n" +
207
+ "a list of strings, or a list of lists of strings"
208
+ err = "$#{name.to_s.gsub('_', '-')}: #{err}" if name
209
+ raise ArgumentError.new(err)
210
+ end
211
+
212
+ # Converts a user-provided selector into string form or returns
213
+ # `nil` if it's in an invalid format.
214
+ def selector_to_str(value)
215
+ return value.value if value.is_a?(Sass::Script::String)
216
+ return unless value.is_a?(Sass::Script::List)
217
+
218
+ if value.separator == :comma
219
+ return value.to_a.map do |complex|
220
+ next complex.value if complex.is_a?(Sass::Script::String)
221
+ return unless complex.is_a?(Sass::Script::List) && complex.separator == :space
222
+ return unless (str = selector_to_str(complex))
223
+ str
224
+ end.join(', ')
225
+ end
226
+
227
+ value.to_a.map do |compound|
228
+ return unless compound.is_a?(Sass::Script::String)
229
+ compound.value
230
+ end.join(' ')
231
+ end
232
+
126
233
  # @private
127
234
  VALID_UNIT = /#{Sass::SCSS::RX::NMSTART}#{Sass::SCSS::RX::NMCHAR}|%*/
128
235
 
@@ -65,24 +65,9 @@ module Sass::Script::Value
65
65
  # @see Value#to_h
66
66
  def to_h
67
67
  return Sass::Util.ordered_hash if value.empty?
68
- return @map ||= Sass::Util.to_hash(value.map {|e| e.to_a}) if is_pseudo_map?
69
68
  super
70
69
  end
71
70
 
72
- # Returns whether a warning still needs to be printed for this list being used as a map.
73
- #
74
- # @return [Boolean]
75
- def needs_map_warning?
76
- !@value.empty? && !@map
77
- end
78
-
79
- # Returns whether this is a list of pairs that can be used as a map.
80
- #
81
- # @return [Boolean]
82
- def is_pseudo_map?
83
- @is_pseudo_map ||= value.all? {|e| e.is_a?(Sass::Script::Value::List) && e.to_a.length == 2}
84
- end
85
-
86
71
  # @see Value#inspect
87
72
  def inspect
88
73
  "(#{value.map {|e| e.inspect}.join(sep_str(nil))})"
@@ -25,11 +25,6 @@ module Sass::Script::Value
25
25
  true
26
26
  end
27
27
 
28
- def neq(other)
29
- return other.neq(self) if other.is_a?(DeprecatedFalse)
30
- super
31
- end
32
-
33
28
  # @return [String] '' (An empty string)
34
29
  def to_s(opts = {})
35
30
  ''
@@ -271,6 +271,8 @@ module Sass::Script::Value
271
271
  #
272
272
  # @return [String] The representation
273
273
  def inspect(opts = {})
274
+ return original if original
275
+
274
276
  value = self.class.round(self.value)
275
277
  str = value.to_s
276
278
 
@@ -445,25 +447,71 @@ module Sass::Script::Value
445
447
  end
446
448
  end
447
449
 
448
- # A hash of unit names to their index in the conversion table
449
- CONVERTABLE_UNITS = %w(in cm pc mm pt px).inject({}) {|m, v| m[v] = m.size; m}
450
-
451
- # in cm pc mm pt px
452
- CONVERSION_TABLE = [[1, 2.54, 6, 25.4, 72 , 96], # in
453
- [nil, 1, 2.36220473, 10, 28.3464567, 37.795275591], # cm
454
- [nil, nil, 1, 4.23333333, 12 , 16], # pc
455
- [nil, nil, nil, 1, 2.83464567, 3.7795275591], # mm
456
- [nil, nil, nil, nil, 1 , 1.3333333333], # pt
457
- [nil, nil, nil, nil, nil , 1]] # px
450
+ # This is the source data for all the unit logic. It's pre-processed to make
451
+ # it efficient to figure out whether a set of units is mutually compatible
452
+ # and what the conversion ratio is between two units.
453
+ #
454
+ # These come from http://www.w3.org/TR/2012/WD-css3-values-20120308/.
455
+ relative_sizes = [
456
+ {
457
+ 'in' => Rational(1),
458
+ 'cm' => Rational(1, 2.54),
459
+ 'pc' => Rational(1, 6),
460
+ 'mm' => Rational(1, 25.4),
461
+ 'pt' => Rational(1, 72),
462
+ 'px' => Rational(1, 96)
463
+ },
464
+ {
465
+ 'deg' => Rational(1, 360),
466
+ 'grad' => Rational(1, 400),
467
+ 'rad' => Rational(1, 2 * Math::PI),
468
+ 'turn' => Rational(1)
469
+ },
470
+ {
471
+ 's' => Rational(1),
472
+ 'ms' => Rational(1, 1000)
473
+ },
474
+ {
475
+ 'Hz' => Rational(1),
476
+ 'kHz' => Rational(1000)
477
+ },
478
+ {
479
+ 'dpi' => Rational(1),
480
+ 'dpcm' => Rational(1, 2.54),
481
+ 'dppx' => Rational(1, 96)
482
+ }
483
+ ]
484
+
485
+ # A hash from each known unit to the set of units that it's mutually
486
+ # convertible with.
487
+ MUTUALLY_CONVERTIBLE = {}
488
+ relative_sizes.map do |values|
489
+ set = values.keys.to_set
490
+ values.keys.each {|name| MUTUALLY_CONVERTIBLE[name] = set}
491
+ end
492
+
493
+ # A two-dimensional hash from two units to the conversion ratio between
494
+ # them. Multiply `X` by `CONVERSION_TABLE[X][Y]` to convert it to `Y`.
495
+ CONVERSION_TABLE = {}
496
+ relative_sizes.each do |values|
497
+ values.each do |(name1, value1)|
498
+ CONVERSION_TABLE[name1] ||= {}
499
+ values.each do |(name2, value2)|
500
+ value = value1 / value2
501
+ CONVERSION_TABLE[name1][name2] = value.denominator == 1 ? value.to_i : value.to_f
502
+ end
503
+ end
504
+ end
458
505
 
459
506
  def conversion_factor(from_unit, to_unit)
460
- res = CONVERSION_TABLE[CONVERTABLE_UNITS[from_unit]][CONVERTABLE_UNITS[to_unit]]
461
- return 1.0 / conversion_factor(to_unit, from_unit) if res.nil?
462
- res
507
+ CONVERSION_TABLE[from_unit][to_unit]
463
508
  end
464
509
 
465
510
  def convertable?(units)
466
- Array(units).all? {|u| CONVERTABLE_UNITS.include?(u)}
511
+ units = Array(units).to_set
512
+ return true if units.empty?
513
+ return false unless (mutually_convertible = MUTUALLY_CONVERTIBLE[units.first])
514
+ units.subset?(mutually_convertible)
467
515
  end
468
516
 
469
517
  def sans_common_units(units1, units2)
@@ -1,3 +1,4 @@
1
+ # -*- coding: utf-8 -*-
1
2
  module Sass::Script::Value
2
3
  # A SassScript object representing a CSS string *or* a CSS identifier.
3
4
  class String < Base
@@ -13,6 +14,52 @@ module Sass::Script::Value
13
14
  # @return [Symbol] `:string` or `:identifier`
14
15
  attr_reader :type
15
16
 
17
+ def self.value(contents)
18
+ contents.gsub("\\\n", "").gsub(/\\(?:([0-9a-fA-F]{1,6})\s?|(.))/) do
19
+ next $2 if $2
20
+ # Handle unicode escapes as per CSS Syntax Level 3 section 4.3.8.
21
+ code_point = $1.to_i(16)
22
+ if code_point == 0 || code_point > 0x10FFFF ||
23
+ (code_point >= 0xD800 && code_point <= 0xDFFF)
24
+ '�'
25
+ else
26
+ [code_point].pack("U")
27
+ end
28
+ end
29
+ end
30
+
31
+ def self.quote(contents, quote = nil)
32
+ # Short-circuit if there are no characters that need quoting.
33
+ unless contents =~ /[\n\\"']/
34
+ quote ||= '"'
35
+ return "#{quote}#{contents}#{quote}"
36
+ end
37
+
38
+ if quote.nil?
39
+ if contents.include?('"')
40
+ if contents.include?("'")
41
+ quote = '"'
42
+ else
43
+ quote = "'"
44
+ end
45
+ else
46
+ quote = '"'
47
+ end
48
+ end
49
+
50
+ # Replace single backslashes with multiples.
51
+ contents = contents.gsub("\\", "\\\\\\\\")
52
+
53
+ if quote == '"'
54
+ contents = contents.gsub('"', "\\\"")
55
+ else
56
+ contents = contents.gsub("'", "\\'")
57
+ end
58
+
59
+ contents = contents.gsub(/\n(?![a-fA-F0-9\s])/, "\\a").gsub("\n", "\\a ")
60
+ "#{quote}#{contents}#{quote}"
61
+ end
62
+
16
63
  # Creates a new string.
17
64
  #
18
65
  # @param value [String] See \{#value}
@@ -24,26 +71,27 @@ module Sass::Script::Value
24
71
 
25
72
  # @see Value#plus
26
73
  def plus(other)
27
- other_str = other.is_a?(Sass::Script::Value::String) ? other.value : other.to_s
28
- Sass::Script::Value::String.new(value + other_str, type)
74
+ other_value = if other.is_a?(Sass::Script::Value::String)
75
+ other.value
76
+ else
77
+ other.to_s(:quote => :none)
78
+ end
79
+ Sass::Script::Value::String.new(value + other_value, type)
29
80
  end
30
81
 
31
82
  # @see Value#to_s
32
83
  def to_s(opts = {})
33
- if @type == :identifier
34
- return @value.gsub(/\n\s*/, " ")
35
- end
36
-
37
- return "\"#{value.gsub('"', "\\\"")}\"" if opts[:quote] == %q{"}
38
- return "'#{value.gsub("'", "\\'")}'" if opts[:quote] == %q{'}
39
- return "\"#{value}\"" unless value.include?('"')
40
- return "'#{value}'" unless value.include?("'")
41
- "\"#{value.gsub('"', "\\\"")}\"" # '
84
+ return @value.gsub(/\n\s*/, ' ') if opts[:quote] == :none || @type == :identifier
85
+ Sass::Script::Value::String.quote(value, opts[:quote])
42
86
  end
43
87
 
44
88
  # @see Value#to_sass
45
89
  def to_sass(opts = {})
46
90
  to_s
47
91
  end
92
+
93
+ def inspect
94
+ String.quote(value)
95
+ end
48
96
  end
49
97
  end
@@ -5,7 +5,6 @@ require 'sass/script/value/string'
5
5
  require 'sass/script/value/number'
6
6
  require 'sass/script/value/color'
7
7
  require 'sass/script/value/bool'
8
- require 'sass/script/value/deprecated_false'
9
8
  require 'sass/script/value/null'
10
9
  require 'sass/script/value/list'
11
10
  require 'sass/script/value/arg_list'
@@ -11,7 +11,7 @@ module Sass
11
11
 
12
12
  def placeholder_selector; nil; end
13
13
  def parent_selector; nil; end
14
- def interpolation; nil; end
14
+ def interpolation(warn_for_color = false); nil; end
15
15
  def use_css_import?; true; end
16
16
 
17
17
  def block_child(context)
@@ -25,10 +25,16 @@ module Sass
25
25
  end
26
26
  end
27
27
 
28
- def nested_properties!(node, space)
28
+ def nested_properties!(node)
29
29
  expected('expression (e.g. 1px, bold)')
30
30
  end
31
31
 
32
+ def ruleset
33
+ start_pos = source_position
34
+ return unless (selector = selector_comma_sequence)
35
+ block(node(Sass::Tree::RuleNode.new(selector, range(start_pos)), start_pos), :ruleset)
36
+ end
37
+
32
38
  @sass_script_parser = Class.new(Sass::Script::CssParser)
33
39
  @sass_script_parser.send(:include, ScriptParser)
34
40
  end