sass 3.3.0.alpha.256 → 3.3.0.alpha.353

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. data/REVISION +1 -1
  2. data/Rakefile +21 -1
  3. data/VERSION +1 -1
  4. data/VERSION_DATE +1 -1
  5. data/lib/sass.rb +6 -3
  6. data/lib/sass/cache_stores/base.rb +1 -1
  7. data/lib/sass/cache_stores/chain.rb +2 -1
  8. data/lib/sass/cache_stores/filesystem.rb +2 -6
  9. data/lib/sass/cache_stores/memory.rb +1 -1
  10. data/lib/sass/cache_stores/null.rb +2 -2
  11. data/lib/sass/callbacks.rb +1 -0
  12. data/lib/sass/css.rb +6 -6
  13. data/lib/sass/engine.rb +60 -34
  14. data/lib/sass/environment.rb +3 -1
  15. data/lib/sass/error.rb +5 -5
  16. data/lib/sass/exec.rb +52 -25
  17. data/lib/sass/features.rb +0 -2
  18. data/lib/sass/importers/deprecated_path.rb +1 -1
  19. data/lib/sass/importers/filesystem.rb +8 -6
  20. data/lib/sass/logger/base.rb +3 -3
  21. data/lib/sass/logger/log_level.rb +4 -6
  22. data/lib/sass/media.rb +2 -2
  23. data/lib/sass/plugin.rb +4 -2
  24. data/lib/sass/plugin/compiler.rb +28 -15
  25. data/lib/sass/plugin/configuration.rb +15 -7
  26. data/lib/sass/plugin/merb.rb +1 -1
  27. data/lib/sass/plugin/staleness_checker.rb +24 -8
  28. data/lib/sass/repl.rb +3 -3
  29. data/lib/sass/script.rb +2 -1
  30. data/lib/sass/script/css_lexer.rb +8 -3
  31. data/lib/sass/script/css_parser.rb +6 -2
  32. data/lib/sass/script/functions.rb +164 -109
  33. data/lib/sass/script/lexer.rb +30 -20
  34. data/lib/sass/script/parser.rb +66 -37
  35. data/lib/sass/script/tree/funcall.rb +23 -14
  36. data/lib/sass/script/tree/interpolation.rb +5 -1
  37. data/lib/sass/script/tree/list_literal.rb +5 -4
  38. data/lib/sass/script/tree/map_literal.rb +1 -1
  39. data/lib/sass/script/tree/node.rb +2 -2
  40. data/lib/sass/script/tree/operation.rb +2 -1
  41. data/lib/sass/script/tree/selector.rb +3 -2
  42. data/lib/sass/script/tree/string_interpolation.rb +2 -1
  43. data/lib/sass/script/tree/variable.rb +4 -3
  44. data/lib/sass/script/value/base.rb +12 -14
  45. data/lib/sass/script/value/color.rb +35 -16
  46. data/lib/sass/script/value/helpers.rb +146 -0
  47. data/lib/sass/script/value/list.rb +24 -5
  48. data/lib/sass/script/value/map.rb +1 -1
  49. data/lib/sass/script/value/null.rb +13 -3
  50. data/lib/sass/script/value/number.rb +44 -35
  51. data/lib/sass/script/value/string.rb +2 -2
  52. data/lib/sass/scss/css_parser.rb +2 -1
  53. data/lib/sass/scss/parser.rb +143 -93
  54. data/lib/sass/scss/rx.rb +4 -4
  55. data/lib/sass/scss/script_lexer.rb +1 -0
  56. data/lib/sass/scss/script_parser.rb +1 -0
  57. data/lib/sass/scss/static_parser.rb +5 -5
  58. data/lib/sass/selector.rb +5 -2
  59. data/lib/sass/selector/abstract_sequence.rb +1 -1
  60. data/lib/sass/selector/comma_sequence.rb +16 -14
  61. data/lib/sass/selector/sequence.rb +38 -24
  62. data/lib/sass/selector/simple.rb +4 -4
  63. data/lib/sass/selector/simple_sequence.rb +21 -11
  64. data/lib/sass/source/map.rb +7 -2
  65. data/lib/sass/source/range.rb +1 -1
  66. data/lib/sass/supports.rb +3 -3
  67. data/lib/sass/tree/debug_node.rb +1 -1
  68. data/lib/sass/tree/function_node.rb +2 -1
  69. data/lib/sass/tree/if_node.rb +1 -1
  70. data/lib/sass/tree/import_node.rb +3 -4
  71. data/lib/sass/tree/prop_node.rb +4 -2
  72. data/lib/sass/tree/rule_node.rb +5 -2
  73. data/lib/sass/tree/visitors/base.rb +6 -6
  74. data/lib/sass/tree/visitors/check_nesting.rb +12 -9
  75. data/lib/sass/tree/visitors/convert.rb +34 -28
  76. data/lib/sass/tree/visitors/cssize.rb +4 -3
  77. data/lib/sass/tree/visitors/deep_copy.rb +1 -0
  78. data/lib/sass/tree/visitors/perform.rb +31 -16
  79. data/lib/sass/tree/visitors/to_css.rb +34 -16
  80. data/lib/sass/util.rb +88 -37
  81. data/lib/sass/util/multibyte_string_scanner.rb +2 -0
  82. data/lib/sass/util/ordered_hash.rb +20 -18
  83. data/lib/sass/util/subset_map.rb +3 -2
  84. data/lib/sass/util/test.rb +0 -1
  85. data/lib/sass/version.rb +9 -5
  86. data/test/rubocop_extensions.rb +70 -0
  87. data/test/sass/functions_test.rb +20 -1
  88. data/test/sass/importer_test.rb +2 -1
  89. data/test/sass/script_test.rb +4 -0
  90. data/test/sass/source_map_test.rb +1 -1
  91. data/test/sass/util_test.rb +49 -0
  92. data/test/sass/value_helpers_test.rb +181 -0
  93. metadata +13 -9
@@ -32,8 +32,8 @@ module Sass::Script::Value
32
32
  # @see Value#eq
33
33
  def eq(other)
34
34
  Sass::Script::Value::Bool.new(
35
- other.is_a?(List) && self.value == other.value &&
36
- self.separator == other.separator)
35
+ other.is_a?(List) && value == other.value &&
36
+ separator == other.separator)
37
37
  end
38
38
 
39
39
  def hash
@@ -43,7 +43,9 @@ module Sass::Script::Value
43
43
  # @see Value#to_s
44
44
  def to_s(opts = {})
45
45
  raise Sass::SyntaxError.new("() isn't a valid CSS value.") if value.empty?
46
- return value.reject {|e| e.is_a?(Null) || e.is_a?(List) && e.value.empty?}.map {|e| e.to_s(opts)}.join(sep_str)
46
+ value.
47
+ reject {|e| e.is_a?(Null) || e.is_a?(List) && e.value.empty?}.
48
+ map {|e| e.to_s(opts)}.join(sep_str)
47
49
  end
48
50
 
49
51
  # @see Value#to_sass
@@ -87,12 +89,29 @@ module Sass::Script::Value
87
89
  "(#{value.map {|e| e.inspect}.join(sep_str(nil))})"
88
90
  end
89
91
 
92
+ # Asserts an index is within the list.
93
+ #
94
+ # @private
95
+ #
96
+ # @param list [Sass::Script::Value::List] The list for which the index should be checked.
97
+ # @param n [Sass::Script::Value::Number] The index being checked.
98
+ def self.assert_valid_index(list, n)
99
+ if !n.int? || n.to_i == 0
100
+ raise ArgumentError.new("List index #{n} must be a non-zero integer")
101
+ elsif list.to_a.size == 0
102
+ raise ArgumentError.new("List index is #{n} but list has no items")
103
+ elsif n.to_i.abs > (size = list.to_a.size)
104
+ raise ArgumentError.new(
105
+ "List index is #{n} but list is only #{size} item#{'s' if size != 1} long")
106
+ end
107
+ end
108
+
90
109
  private
91
110
 
92
- def sep_str(opts = self.options)
111
+ def sep_str(opts = options)
93
112
  return ' ' if separator == :space
94
113
  return ',' if opts && opts[:style] == :compressed
95
- return ', '
114
+ ', '
96
115
  end
97
116
  end
98
117
  end
@@ -40,7 +40,7 @@ module Sass::Script::Value
40
40
 
41
41
  # @see Value#eq
42
42
  def eq(other)
43
- Bool.new(other.is_a?(Map) && self.value == other.value)
43
+ Bool.new(other.is_a?(Map) && value == other.value)
44
44
  end
45
45
 
46
46
  def hash
@@ -1,9 +1,19 @@
1
1
  module Sass::Script::Value
2
2
  # A SassScript object representing a null value.
3
3
  class Null < Base
4
- # Creates a new null value.
5
- def initialize
6
- super nil
4
+
5
+ # The null value in SassScript.
6
+ #
7
+ # This is assigned before new is overridden below so that we use the default implementation.
8
+ NULL = new(nil)
9
+
10
+ # We override object creation so that users of the core API
11
+ # will not need to know that null is a specific constant.
12
+ #
13
+ # @private
14
+ # @return [Null] the {NULL} constant.
15
+ def self.new
16
+ NULL
7
17
  end
8
18
 
9
19
  # @return [Boolean] `false` (the Ruby boolean value)
@@ -15,7 +15,7 @@ module Sass::Script::Value
15
15
 
16
16
  # A list of units in the numerator of the number.
17
17
  # For example, `1px*em/in*cm` would return `["px", "em"]`
18
- # @return [Array<String>]
18
+ # @return [Array<String>]
19
19
  attr_reader :numerator_units
20
20
 
21
21
  # A list of units in the denominator of the number.
@@ -161,8 +161,8 @@ module Sass::Script::Value
161
161
  def div(other)
162
162
  if other.is_a? Number
163
163
  res = operate(other, :/)
164
- if self.original && other.original
165
- res.original = "#{self.original}/#{other.original}"
164
+ if original && other.original
165
+ res.original = "#{original}/#{other.original}"
166
166
  end
167
167
  res
168
168
  else
@@ -179,7 +179,8 @@ module Sass::Script::Value
179
179
  def mod(other)
180
180
  if other.is_a?(Number)
181
181
  unless other.unitless?
182
- raise Sass::UnitConversionError.new("Cannot modulo by a number with units: #{other.inspect}.")
182
+ raise Sass::UnitConversionError.new(
183
+ "Cannot modulo by a number with units: #{other.inspect}.")
183
184
  end
184
185
  operate(other, :%)
185
186
  else
@@ -214,8 +215,8 @@ module Sass::Script::Value
214
215
  # Hash-equality must be transitive, so it just compares the exact value,
215
216
  # numerator units, and denominator units.
216
217
  def eql?(other)
217
- self.value == other.value && self.numerator_units == other.numerator_units &&
218
- self.denominator_units == other.denominator_units
218
+ value == other.value && numerator_units == other.numerator_units &&
219
+ denominator_units == other.denominator_units
219
220
  end
220
221
 
221
222
  # The SassScript `>` operation.
@@ -283,7 +284,7 @@ module Sass::Script::Value
283
284
  # @raise [Sass::SyntaxError] if the number isn't an integer
284
285
  def to_i
285
286
  super unless int?
286
- return value
287
+ value
287
288
  end
288
289
 
289
290
  # @return [Boolean] Whether or not this number is an integer.
@@ -303,7 +304,8 @@ module Sass::Script::Value
303
304
  # number.is_unit?("px") => true
304
305
  # number.is_unit?(nil) => false
305
306
  #
306
- # @param unit [::String, nil] The unit the number should have or nil if the number should be unitless.
307
+ # @param unit [::String, nil] The unit the number should have or nil if the number
308
+ # should be unitless.
307
309
  # @see Number#unitless? The unitless? method may be more readable.
308
310
  def is_unit?(unit)
309
311
  if unit
@@ -337,9 +339,9 @@ module Sass::Script::Value
337
339
  # current units
338
340
  def coerce(num_units, den_units)
339
341
  Number.new(if unitless?
340
- self.value
342
+ value
341
343
  else
342
- self.value * coercion_factor(@numerator_units, num_units) /
344
+ value * coercion_factor(@numerator_units, num_units) /
343
345
  coercion_factor(@denominator_units, den_units)
344
346
  end, num_units, den_units)
345
347
  end
@@ -347,12 +349,10 @@ module Sass::Script::Value
347
349
  # @param other [Number] A number to decide if it can be compared with this number.
348
350
  # @return [Boolean] Whether or not this number can be compared with the other.
349
351
  def comparable_to?(other)
350
- begin
351
- operate(other, :+)
352
- true
353
- rescue Sass::UnitConversionError
354
- false
355
- end
352
+ operate(other, :+)
353
+ true
354
+ rescue Sass::UnitConversionError
355
+ false
356
356
  end
357
357
 
358
358
  # Returns a human readable representation of the units in this number.
@@ -377,7 +377,7 @@ module Sass::Script::Value
377
377
  elsif num % 1 == 0.0
378
378
  num.to_i
379
379
  else
380
- ((num * self.precision_factor).round / self.precision_factor).to_f
380
+ ((num * precision_factor).round / precision_factor).to_f
381
381
  end
382
382
  end
383
383
 
@@ -393,7 +393,7 @@ module Sass::Script::Value
393
393
  end
394
394
  end
395
395
  # avoid integer division
396
- value = (:/ == operation) ? this.value.to_f : this.value
396
+ value = :/ == operation ? this.value.to_f : this.value
397
397
  result = value.send(operation, other.value)
398
398
 
399
399
  if result.is_a?(Numeric)
@@ -408,29 +408,33 @@ module Sass::Script::Value
408
408
  from_units, to_units = sans_common_units(from_units, to_units)
409
409
 
410
410
  if from_units.size != to_units.size || !convertable?(from_units | to_units)
411
- raise Sass::UnitConversionError.new("Incompatible units: '#{from_units.join('*')}' and '#{to_units.join('*')}'.")
411
+ raise Sass::UnitConversionError.new(
412
+ "Incompatible units: '#{from_units.join('*')}' and '#{to_units.join('*')}'.")
412
413
  end
413
414
 
414
- from_units.zip(to_units).inject(1) {|m,p| m * conversion_factor(p[0], p[1]) }
415
+ from_units.zip(to_units).inject(1) {|m, p| m * conversion_factor(p[0], p[1])}
415
416
  end
416
417
 
417
418
  def compute_units(this, other, operation)
418
419
  case operation
419
420
  when :*
420
- [this.numerator_units + other.numerator_units, this.denominator_units + other.denominator_units]
421
+ [this.numerator_units + other.numerator_units,
422
+ this.denominator_units + other.denominator_units]
421
423
  when :/
422
- [this.numerator_units + other.denominator_units, this.denominator_units + other.numerator_units]
423
- else
424
+ [this.numerator_units + other.denominator_units,
425
+ this.denominator_units + other.numerator_units]
426
+ else
424
427
  [this.numerator_units, this.denominator_units]
425
428
  end
426
429
  end
427
430
 
428
431
  def normalize!
429
432
  return if unitless?
430
- @numerator_units, @denominator_units = sans_common_units(@numerator_units, @denominator_units)
433
+ @numerator_units, @denominator_units =
434
+ sans_common_units(@numerator_units, @denominator_units)
431
435
 
432
436
  @denominator_units.each_with_index do |d, i|
433
- if convertable?(d) && (u = @numerator_units.detect(&method(:convertable?)))
437
+ if convertable?(d) && (u = @numerator_units.find(&method(:convertable?)))
434
438
  @value /= conversion_factor(d, u)
435
439
  @denominator_units.delete_at(i)
436
440
  @numerator_units.delete_at(@numerator_units.index(u))
@@ -439,13 +443,15 @@ module Sass::Script::Value
439
443
  end
440
444
 
441
445
  # A hash of unit names to their index in the conversion table
442
- CONVERTABLE_UNITS = {"in" => 0, "cm" => 1, "pc" => 2, "mm" => 3, "pt" => 4, "px" => 5 }
443
- CONVERSION_TABLE = [[ 1, 2.54, 6, 25.4, 72 , 96 ], # in
444
- [ nil, 1, 2.36220473, 10, 28.3464567, 37.795275591], # cm
445
- [ nil, nil, 1, 4.23333333, 12 , 16 ], # pc
446
- [ nil, nil, nil, 1, 2.83464567, 3.7795275591], # mm
447
- [ nil, nil, nil, nil, 1 , 1.3333333333], # pt
448
- [ nil, nil, nil, nil, nil , 1 ]] # px
446
+ CONVERTABLE_UNITS = %w(in cm pc mm pt px).inject({}) {|m, v| m[v] = m.size; m}
447
+
448
+ # in cm pc mm pt px
449
+ CONVERSION_TABLE = [[1, 2.54, 6, 25.4, 72 , 96], # in
450
+ [nil, 1, 2.36220473, 10, 28.3464567, 37.795275591], # cm
451
+ [nil, nil, 1, 4.23333333, 12 , 16], # pc
452
+ [nil, nil, nil, 1, 2.83464567, 3.7795275591], # mm
453
+ [nil, nil, nil, nil, 1 , 1.3333333333], # pt
454
+ [nil, nil, nil, nil, nil , 1]] # px
449
455
 
450
456
  def conversion_factor(from_unit, to_unit)
451
457
  res = CONVERSION_TABLE[CONVERTABLE_UNITS[from_unit]][CONVERTABLE_UNITS[to_unit]]
@@ -460,11 +466,14 @@ module Sass::Script::Value
460
466
  def sans_common_units(units1, units2)
461
467
  units2 = units2.dup
462
468
  # Can't just use -, because we want px*px to coerce properly to px*mm
463
- return units1.map do |u|
464
- next u unless j = units2.index(u)
469
+ units1 = units1.map do |u|
470
+ j = units2.index(u)
471
+ next u unless j
465
472
  units2.delete_at(j)
466
473
  nil
467
- end.compact, units2
474
+ end
475
+ units1.compact!
476
+ return units1, units2
468
477
  end
469
478
  end
470
479
  end
@@ -25,7 +25,7 @@ module Sass::Script::Value
25
25
  # @see Value#plus
26
26
  def plus(other)
27
27
  other_str = other.is_a?(Sass::Script::Value::String) ? other.value : other.to_s
28
- Sass::Script::Value::String.new(self.value + other_str, self.type)
28
+ Sass::Script::Value::String.new(value + other_str, type)
29
29
  end
30
30
 
31
31
  # @see Value#to_s
@@ -38,7 +38,7 @@ module Sass::Script::Value
38
38
  return "'#{value.gsub("'", "\\'")}'" if opts[:quote] == %q{'}
39
39
  return "\"#{value}\"" unless value.include?('"')
40
40
  return "'#{value}'" unless value.include?("'")
41
- "\"#{value.gsub('"', "\\\"")}\"" #'
41
+ "\"#{value.gsub('"', "\\\"")}\"" # '
42
42
  end
43
43
 
44
44
  # @see Value#to_sass
@@ -7,6 +7,7 @@ module Sass
7
7
  # parent references, nested selectors, and so forth.
8
8
  # It does support all the same CSS hacks as the SCSS parser, though.
9
9
  class CssParser < StaticParser
10
+
10
11
  private
11
12
 
12
13
  def placeholder_selector; nil; end
@@ -26,7 +27,7 @@ module Sass
26
27
  end
27
28
 
28
29
  def nested_properties!(node, space)
29
- expected('expression (e.g. 1px, bold)');
30
+ expected('expression (e.g. 1px, bold)')
30
31
  end
31
32
 
32
33
  @sass_script_parser = Class.new(Sass::Script::CssParser)
@@ -21,7 +21,10 @@ module Sass
21
21
  # @param offset [Fixnum] The 1-based character (not byte) offset in the line on
22
22
  # which the source string starts. Used for error reporting and sourcemap
23
23
  # building.
24
+ # @comment
25
+ # rubocop:disable ParameterLists
24
26
  def initialize(str, filename, importer, line = 1, offset = 1)
27
+ # rubocop:enable ParameterLists
25
28
  @template = str
26
29
  @filename = filename
27
30
  @importer = importer
@@ -84,7 +87,7 @@ module Sass
84
87
  Sass::Source::Position.new(@line, @offset)
85
88
  end
86
89
 
87
- def range(start_pos, end_pos=source_position)
90
+ def range(start_pos, end_pos = source_position)
88
91
  Sass::Source::Range.new(start_pos, end_pos, @filename, @importer)
89
92
  end
90
93
 
@@ -132,21 +135,28 @@ module Sass
132
135
  end
133
136
 
134
137
  def process_comment(text, node)
135
- silent = text =~ /^\/\//
138
+ silent = text =~ %r{^//}
136
139
  loud = !silent && text =~ %r{^/[/*]!}
137
140
  line = @line - text.count("\n")
138
141
 
139
142
  if silent
140
- value = [text.sub(/^\s*\/\//, '/*').gsub(/^\s*\/\//, ' *') + ' */']
143
+ value = [text.sub(%r{^\s*//}, '/*').gsub(%r{^\s*//}, ' *') + ' */']
141
144
  else
142
- value = Sass::Engine.parse_interp(text, line, @scanner.pos - text.size, :filename => @filename)
145
+ value = Sass::Engine.parse_interp(
146
+ text, line, @scanner.pos - text.size, :filename => @filename)
143
147
  value.unshift(@scanner.
144
148
  string[0...@scanner.pos].
145
149
  reverse[/.*?\*\/(.*?)($|\Z)/, 1].
146
150
  reverse.gsub(/[^\s]/, ' '))
147
151
  end
148
152
 
149
- type = if silent then :silent elsif loud then :loud else :normal end
153
+ type = if silent
154
+ :silent
155
+ elsif loud
156
+ :loud
157
+ else
158
+ :normal
159
+ end
150
160
  comment = Sass::Tree::CommentNode.new(value, type)
151
161
  comment.line = line
152
162
  node << comment
@@ -164,9 +174,9 @@ module Sass
164
174
  name = tok!(IDENT)
165
175
  ss
166
176
 
167
- if dir = special_directive(name, start_pos)
177
+ if (dir = special_directive(name, start_pos))
168
178
  return dir
169
- elsif dir = prefixed_directive(name, start_pos)
179
+ elsif (dir = prefixed_directive(name, start_pos))
170
180
  return dir
171
181
  end
172
182
 
@@ -211,7 +221,8 @@ module Sass
211
221
  name = tok! IDENT
212
222
  args, keywords, splat, kwarg_splat = sass_script(:parse_mixin_include_arglist)
213
223
  ss
214
- include_node = node(Sass::Tree::MixinNode.new(name, args, keywords, splat, kwarg_splat), start_pos)
224
+ include_node = node(
225
+ Sass::Tree::MixinNode.new(name, args, keywords, splat, kwarg_splat), start_pos)
215
226
  if tok?(/\{/)
216
227
  include_node.has_children = true
217
228
  block(include_node, :directive)
@@ -344,7 +355,7 @@ module Sass
344
355
  ss
345
356
  end
346
357
 
347
- return values
358
+ values
348
359
  end
349
360
 
350
361
  def import_arg
@@ -361,7 +372,7 @@ module Sass
361
372
  ss
362
373
 
363
374
  media = media_query_list
364
- if path =~ /^(https?:)?\/\// || media || use_css_import?
375
+ if path =~ %r{^(https?:)?//} || media || use_css_import?
365
376
  return node(Sass::Tree::CssImportNode.new(str, media.to_a), start_pos)
366
377
  end
367
378
 
@@ -376,7 +387,8 @@ module Sass
376
387
 
377
388
  # http://www.w3.org/TR/css3-mediaqueries/#syntax
378
389
  def media_query_list
379
- return unless query = media_query
390
+ query = media_query
391
+ return unless query
380
392
  queries = [query]
381
393
 
382
394
  ss
@@ -389,7 +401,7 @@ module Sass
389
401
  end
390
402
 
391
403
  def media_query
392
- if ident1 = interp_ident
404
+ if (ident1 = interp_ident)
393
405
  ss
394
406
  ident2 = interp_ident
395
407
  ss
@@ -409,7 +421,8 @@ module Sass
409
421
  if query
410
422
  expr = expr!(:media_expr)
411
423
  else
412
- return unless expr = media_expr
424
+ expr = media_expr
425
+ return unless expr
413
426
  end
414
427
  query ||= Sass::Media::Query.new([], [], [])
415
428
  query.expressions << expr
@@ -423,7 +436,8 @@ module Sass
423
436
  end
424
437
 
425
438
  def media_expr
426
- interp = interpolation and return interp
439
+ interp = interpolation
440
+ return interp if interp
427
441
  return unless tok(/\(/)
428
442
  res = ['(']
429
443
  ss
@@ -457,25 +471,30 @@ module Sass
457
471
  def _moz_document_directive(start_pos)
458
472
  res = ["@-moz-document "]
459
473
  loop do
460
- res << str{ss} << expr!(:moz_document_function)
461
- break unless c = tok(/,/)
462
- res << c
474
+ res << str {ss} << expr!(:moz_document_function)
475
+ if (c = tok(/,/))
476
+ res << c
477
+ else
478
+ break
479
+ end
463
480
  end
464
481
  directive_body(res.flatten, start_pos)
465
482
  end
466
483
 
467
484
  def moz_document_function
468
- return unless val = interp_uri || _interp_string(:url_prefix) ||
485
+ val = interp_uri || _interp_string(:url_prefix) ||
469
486
  _interp_string(:domain) || function(!:allow_var) || interpolation
487
+ return unless val
470
488
  ss
471
489
  val
472
490
  end
473
491
 
474
492
  def at_root_directive(start_pos)
475
493
  at_root_node = node(Sass::Tree::AtRootNode.new, start_pos)
476
- return block(at_root_node, :stylesheet) unless rule_node = ruleset
494
+ rule_node = ruleset
495
+ return block(at_root_node, :stylesheet) unless rule_node
477
496
  at_root_node << rule_node
478
- return at_root_node
497
+ at_root_node
479
498
  end
480
499
 
481
500
  # http://www.w3.org/TR/css3-conditional/
@@ -502,20 +521,21 @@ module Sass
502
521
  end
503
522
 
504
523
  def supports_operator
505
- return unless cond = supports_condition_in_parens
506
- return cond unless op = tok(/and|or/i)
507
- begin
524
+ cond = supports_condition_in_parens
525
+ return unless cond
526
+ while (op = tok(/and|or/i))
508
527
  ss
509
528
  cond = Sass::Supports::Operator.new(
510
529
  cond, expr!(:supports_condition_in_parens), op)
511
- end while op = tok(/and|or/i)
530
+ end
512
531
  cond
513
532
  end
514
533
 
515
534
  def supports_condition_in_parens
516
- interp = supports_interpolation and return interp
535
+ interp = supports_interpolation
536
+ return interp if interp
517
537
  return unless tok(/\(/); ss
518
- if cond = supports_condition
538
+ if (cond = supports_condition)
519
539
  tok!(/\)/); ss
520
540
  cond
521
541
  else
@@ -533,7 +553,8 @@ module Sass
533
553
  end
534
554
 
535
555
  def supports_interpolation
536
- return unless interp = interpolation
556
+ interp = interpolation
557
+ return unless interp
537
558
  ss
538
559
  Sass::Supports::Interpolation.new(interp)
539
560
  end
@@ -562,7 +583,8 @@ module Sass
562
583
  start_pos = source_position
563
584
  rules, source_range = selector_sequence
564
585
  return unless rules
565
- block(node(Sass::Tree::RuleNode.new(rules.flatten.compact, source_range), start_pos), :ruleset)
586
+ block(node(
587
+ Sass::Tree::RuleNode.new(rules.flatten.compact, source_range), start_pos), :ruleset)
566
588
  end
567
589
 
568
590
  def block(node, context)
@@ -593,7 +615,7 @@ module Sass
593
615
  def has_children?(child_or_array)
594
616
  return false unless child_or_array
595
617
  return child_or_array.last.has_children if child_or_array.is_a?(Array)
596
- return child_or_array.has_children
618
+ child_or_array.has_children
597
619
  end
598
620
 
599
621
  # This is a nasty hack, and the only place in the parser
@@ -632,18 +654,19 @@ module Sass
632
654
 
633
655
  def selector_sequence
634
656
  start_pos = source_position
635
- if sel = tok(STATIC_SELECTOR, true)
657
+ if (sel = tok(STATIC_SELECTOR, true))
636
658
  return [sel], range(start_pos)
637
659
  end
638
660
 
639
661
  rules = []
640
- return unless v = selector
662
+ v = selector
663
+ return unless v
641
664
  rules.concat v
642
665
 
643
666
  ws = ''
644
667
  while tok(/,/)
645
668
  ws << str {ss}
646
- if v = selector
669
+ if (v = selector)
647
670
  rules << ',' << ws
648
671
  rules.concat v
649
672
  ws = ''
@@ -653,19 +676,23 @@ module Sass
653
676
  end
654
677
 
655
678
  def selector
656
- return unless sel = _selector
679
+ sel = _selector
680
+ return unless sel
657
681
  sel.to_a
658
682
  end
659
683
 
660
684
  def selector_comma_sequence
661
- return unless sel = _selector
685
+ sel = _selector
686
+ return unless sel
662
687
  selectors = [sel]
663
688
  ws = ''
664
689
  while tok(/,/)
665
- ws << str{ss}
666
- if sel = _selector
690
+ ws << str {ss}
691
+ if (sel = _selector)
667
692
  selectors << sel
668
- selectors[-1] = Selector::Sequence.new(["\n"] + selectors.last.members) if ws.include?("\n")
693
+ if ws.include?("\n")
694
+ selectors[-1] = Selector::Sequence.new(["\n"] + selectors.last.members)
695
+ end
669
696
  ws = ''
670
697
  end
671
698
  end
@@ -674,15 +701,16 @@ module Sass
674
701
 
675
702
  def _selector
676
703
  # The combinator here allows the "> E" hack
677
- return unless val = combinator || simple_selector_sequence
678
- nl = str{ss}.include?("\n")
704
+ val = combinator || simple_selector_sequence
705
+ return unless val
706
+ nl = str {ss}.include?("\n")
679
707
  res = []
680
708
  res << val
681
709
  res << "\n" if nl
682
710
 
683
- while val = combinator || simple_selector_sequence
711
+ while (val = combinator || simple_selector_sequence)
684
712
  res << val
685
- res << "\n" if str{ss}.include?("\n")
713
+ res << "\n" if str {ss}.include?("\n")
686
714
  end
687
715
  Selector::Sequence.new(res.compact)
688
716
  end
@@ -707,21 +735,22 @@ module Sass
707
735
  # http://www.w3.org/TR/css3-animations/#keyframes-
708
736
 
709
737
  start_pos = source_position
710
- return expr(!:allow_var) unless e = element_name || id_selector ||
738
+ e = element_name || id_selector ||
711
739
  class_selector || placeholder_selector || attrib || pseudo ||
712
740
  parent_selector || interpolation_selector
741
+ return expr(!:allow_var) unless e
713
742
  res = [e]
714
743
 
715
744
  # The tok(/\*/) allows the "E*" hack
716
- while v = id_selector || class_selector || placeholder_selector || attrib ||
717
- pseudo || interpolation_selector ||
718
- (tok(/\*/) && Selector::Universal.new(nil))
745
+ while (v = id_selector || class_selector || placeholder_selector ||
746
+ attrib || pseudo || interpolation_selector ||
747
+ (tok(/\*/) && Selector::Universal.new(nil)))
719
748
  res << v
720
749
  end
721
750
 
722
751
  pos = @scanner.pos
723
752
  line = @line
724
- if sel = str? {simple_selector_sequence}
753
+ if (sel = str? {simple_selector_sequence})
725
754
  @scanner.pos = pos
726
755
  @line = line
727
756
  begin
@@ -772,8 +801,9 @@ module Sass
772
801
  end
773
802
  end
774
803
 
775
- def qualified_name(allow_star_name=false)
776
- return unless name = interp_ident || tok(/\*/) || (tok?(/\|/) && "")
804
+ def qualified_name(allow_star_name = false)
805
+ name = interp_ident || tok(/\*/) || (tok?(/\|/) && "")
806
+ return unless name
777
807
  return nil, name unless tok(/\|/)
778
808
 
779
809
  return name, expr!(:interp_ident) unless allow_star_name
@@ -782,8 +812,9 @@ module Sass
782
812
  end
783
813
 
784
814
  def interpolation_selector
785
- return unless script = interpolation
786
- Selector::Interpolation.new(script)
815
+ if (script = interpolation)
816
+ Selector::Interpolation.new(script)
817
+ end
787
818
  end
788
819
 
789
820
  def attrib
@@ -792,12 +823,13 @@ module Sass
792
823
  ns, name = attrib_name!
793
824
  ss
794
825
 
795
- if op = tok(/=/) ||
796
- tok(INCLUDES) ||
797
- tok(DASHMATCH) ||
798
- tok(PREFIXMATCH) ||
799
- tok(SUFFIXMATCH) ||
800
- tok(SUBSTRINGMATCH)
826
+ op = tok(/=/) ||
827
+ tok(INCLUDES) ||
828
+ tok(DASHMATCH) ||
829
+ tok(PREFIXMATCH) ||
830
+ tok(SUFFIXMATCH) ||
831
+ tok(SUBSTRINGMATCH)
832
+ if op
801
833
  @expected = "identifier or string"
802
834
  ss
803
835
  val = interp_ident || expr!(:interp_string)
@@ -810,7 +842,7 @@ module Sass
810
842
  end
811
843
 
812
844
  def attrib_name!
813
- if name_or_ns = interp_ident
845
+ if (name_or_ns = interp_ident)
814
846
  # E, E|E
815
847
  if tok(/\|(?!=)/)
816
848
  ns = name_or_ns
@@ -828,14 +860,15 @@ module Sass
828
860
  end
829
861
 
830
862
  def pseudo
831
- return unless s = tok(/::?/)
863
+ s = tok(/::?/)
864
+ return unless s
832
865
  @expected = "pseudoclass or pseudoelement"
833
866
  name = expr!(:interp_ident)
834
867
  if tok(/\(/)
835
868
  ss
836
869
  arg = expr!(:pseudo_arg)
837
870
  while tok(/,/)
838
- arg << ',' << str{ss}
871
+ arg << ',' << str {ss}
839
872
  arg.concat expr!(:pseudo_arg)
840
873
  end
841
874
  tok!(/\)/)
@@ -866,16 +899,19 @@ module Sass
866
899
  return sel if sel
867
900
  rethrow pseudo_err if pseudo_err
868
901
  rethrow sel_err if sel_err
869
- return
902
+ nil
903
+ end
904
+
905
+ def pseudo_expr_token
906
+ tok(PLUS) || tok(/[-*]/) || tok(NUMBER) || interp_string || tok(IDENT) || interpolation
870
907
  end
871
908
 
872
909
  def pseudo_expr
873
- return unless e = tok(PLUS) || tok(/[-*]/) || tok(NUMBER) ||
874
- interp_string || tok(IDENT) || interpolation
875
- res = [e, str{ss}]
876
- while e = tok(PLUS) || tok(/[-*]/) || tok(NUMBER) ||
877
- interp_string || tok(IDENT) || interpolation
878
- res << e << str{ss}
910
+ e = pseudo_expr_token
911
+ return unless e
912
+ res = [e, str {ss}]
913
+ while (e = pseudo_expr_token)
914
+ res << e << str {ss}
879
915
  end
880
916
  res
881
917
  end
@@ -883,14 +919,15 @@ module Sass
883
919
  def declaration
884
920
  # This allows the "*prop: val", ":prop: val", and ".prop: val" hacks
885
921
  name_start_pos = source_position
886
- if s = tok(/[:\*\.]|\#(?!\{)/)
922
+ if (s = tok(/[:\*\.]|\#(?!\{)/))
887
923
  @use_property_exception = s !~ /[\.\#]/
888
- name = [s, str{ss}, *expr!(:interp_ident)]
924
+ name = [s, str {ss}, *expr!(:interp_ident)]
889
925
  else
890
- return unless name = interp_ident
926
+ name = interp_ident
927
+ return unless name
891
928
  name = [name] if name.is_a?(String)
892
929
  end
893
- if comment = tok(COMMENT)
930
+ if (comment = tok(COMMENT))
894
931
  name << comment
895
932
  end
896
933
  name_end_pos = source_position
@@ -902,7 +939,8 @@ module Sass
902
939
  ss
903
940
  require_block = tok?(/\{/)
904
941
 
905
- node = node(Sass::Tree::PropNode.new(name.flatten.compact, value, :new), name_start_pos, value_end_pos)
942
+ node = node(Sass::Tree::PropNode.new(name.flatten.compact, value, :new),
943
+ name_start_pos, value_end_pos)
906
944
  node.name_source_range = range(name_start_pos, name_end_pos)
907
945
  node.value_source_range = range(value_start_pos, value_end_pos)
908
946
 
@@ -928,7 +966,7 @@ module Sass
928
966
  # we don't parse it at all, and instead return a plain old string
929
967
  # containing the value.
930
968
  # This results in a dramatic speed increase.
931
- if val = tok(STATIC_VALUE, true)
969
+ if (val = tok(STATIC_VALUE, true))
932
970
  str = Sass::Script::Tree::Literal.new(Sass::Script::Value::String.new(val.strip))
933
971
  str.line = start_pos.line
934
972
  str.source_range = range(start_pos)
@@ -949,18 +987,19 @@ MESSAGE
949
987
  end
950
988
 
951
989
  def expr(allow_var = true)
952
- return unless t = term(allow_var)
953
- res = [t, str{ss}]
990
+ t = term(allow_var)
991
+ return unless t
992
+ res = [t, str {ss}]
954
993
 
955
994
  while (o = operator) && (t = term(allow_var))
956
- res << o << t << str{ss}
995
+ res << o << t << str {ss}
957
996
  end
958
997
 
959
998
  res.flatten
960
999
  end
961
1000
 
962
1001
  def term(allow_var)
963
- if e = tok(NUMBER) ||
1002
+ e = tok(NUMBER) ||
964
1003
  interp_uri ||
965
1004
  function(allow_var) ||
966
1005
  interp_string ||
@@ -968,22 +1007,23 @@ MESSAGE
968
1007
  interp_ident ||
969
1008
  tok(HEXCOLOR) ||
970
1009
  (allow_var && var_expr)
971
- return e
972
- end
1010
+ return e if e
973
1011
 
974
- return unless op = tok(/[+-]/)
1012
+ op = tok(/[+-]/)
1013
+ return unless op
975
1014
  @expected = "number or function"
976
- return [op, tok(NUMBER) || function(allow_var) ||
977
- (allow_var && var_expr) || expr!(:interpolation)]
1015
+ [op,
1016
+ tok(NUMBER) || function(allow_var) || (allow_var && var_expr) || expr!(:interpolation)]
978
1017
  end
979
1018
 
980
1019
  def function(allow_var)
981
- return unless name = tok(FUNCTION)
1020
+ name = tok(FUNCTION)
1021
+ return unless name
982
1022
  if name == "expression(" || name == "calc("
983
1023
  str, _ = Sass::Shared.balance(@scanner, ?(, ?), 1)
984
1024
  [name, str]
985
1025
  else
986
- [name, str{ss}, expr(allow_var), tok!(/\)/)]
1026
+ [name, str {ss}, expr(allow_var), tok!(/\)/)]
987
1027
  end
988
1028
  end
989
1029
 
@@ -1009,7 +1049,8 @@ MESSAGE
1009
1049
  end
1010
1050
 
1011
1051
  def _interp_string(type)
1012
- return unless start = tok(Sass::Script::Lexer::STRING_REGULAR_EXPRESSIONS[[type, false]])
1052
+ start = tok(Sass::Script::Lexer::STRING_REGULAR_EXPRESSIONS[[type, false]])
1053
+ return unless start
1013
1054
  res = [start]
1014
1055
 
1015
1056
  mid_re = Sass::Script::Lexer::STRING_REGULAR_EXPRESSIONS[[type, true]]
@@ -1023,17 +1064,20 @@ MESSAGE
1023
1064
  end
1024
1065
 
1025
1066
  def interp_ident(start = IDENT)
1026
- return unless val = tok(start) || interpolation || tok(IDENT_HYPHEN_INTERP, true)
1067
+ val = tok(start) || interpolation || tok(IDENT_HYPHEN_INTERP, true)
1068
+ return unless val
1027
1069
  res = [val]
1028
- while val = tok(NAME) || interpolation
1070
+ while (val = tok(NAME) || interpolation)
1029
1071
  res << val
1030
1072
  end
1031
1073
  res
1032
1074
  end
1033
1075
 
1034
1076
  def interp_ident_or_var
1035
- (id = interp_ident) and return id
1036
- (var = var_expr) and return [var]
1077
+ id = interp_ident
1078
+ return id if id
1079
+ var = var_expr
1080
+ return [var] if var
1037
1081
  end
1038
1082
 
1039
1083
  def interp_name
@@ -1071,11 +1115,15 @@ MESSAGE
1071
1115
 
1072
1116
  @sass_script_parser = Class.new(Sass::Script::Parser)
1073
1117
  @sass_script_parser.send(:include, ScriptParser)
1074
- # @private
1075
- def self.sass_script_parser; @sass_script_parser; end
1118
+
1119
+ class << self
1120
+ # @private
1121
+ attr_accessor :sass_script_parser
1122
+ end
1076
1123
 
1077
1124
  def sass_script(*args)
1078
- parser = self.class.sass_script_parser.new(@scanner, @line, @offset, :filename => @filename, :importer => @importer)
1125
+ parser = self.class.sass_script_parser.new(@scanner, @line, @offset,
1126
+ :filename => @filename, :importer => @importer)
1079
1127
  result = parser.send(*args)
1080
1128
  unless @strs.empty?
1081
1129
  # Convert to CSS manually so that comments are ignored.
@@ -1121,12 +1169,14 @@ MESSAGE
1121
1169
  end
1122
1170
 
1123
1171
  def expr!(name)
1124
- (e = send(name)) && (return e)
1172
+ e = send(name)
1173
+ return e if e
1125
1174
  expected(EXPR_NAMES[name] || name.to_s)
1126
1175
  end
1127
1176
 
1128
1177
  def tok!(rx)
1129
- (t = tok(rx)) && (return t)
1178
+ t = tok(rx)
1179
+ return t if t
1130
1180
  name = TOK_NAMES[rx]
1131
1181
 
1132
1182
  unless name