sass 3.3.0 → 3.4.25

Sign up to get free protection for your applications and to get access to all the features.
Files changed (208) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +3 -1
  3. data/CODE_OF_CONDUCT.md +10 -0
  4. data/CONTRIBUTING.md +148 -0
  5. data/MIT-LICENSE +1 -1
  6. data/README.md +76 -62
  7. data/Rakefile +104 -24
  8. data/VERSION +1 -1
  9. data/VERSION_DATE +1 -1
  10. data/VERSION_NAME +1 -1
  11. data/bin/sass +1 -1
  12. data/bin/scss +1 -1
  13. data/extra/sass-spec-ref.sh +32 -0
  14. data/extra/update_watch.rb +1 -1
  15. data/lib/sass/cache_stores/filesystem.rb +9 -5
  16. data/lib/sass/cache_stores/memory.rb +4 -5
  17. data/lib/sass/callbacks.rb +2 -2
  18. data/lib/sass/css.rb +12 -13
  19. data/lib/sass/deprecation.rb +55 -0
  20. data/lib/sass/engine.rb +106 -70
  21. data/lib/sass/environment.rb +39 -19
  22. data/lib/sass/error.rb +17 -20
  23. data/lib/sass/exec/base.rb +199 -0
  24. data/lib/sass/exec/sass_convert.rb +283 -0
  25. data/lib/sass/exec/sass_scss.rb +440 -0
  26. data/lib/sass/exec.rb +5 -771
  27. data/lib/sass/features.rb +9 -2
  28. data/lib/sass/importers/base.rb +8 -3
  29. data/lib/sass/importers/filesystem.rb +30 -38
  30. data/lib/sass/logger/base.rb +8 -2
  31. data/lib/sass/logger/delayed.rb +50 -0
  32. data/lib/sass/logger.rb +8 -3
  33. data/lib/sass/media.rb +1 -4
  34. data/lib/sass/plugin/compiler.rb +224 -90
  35. data/lib/sass/plugin/configuration.rb +38 -22
  36. data/lib/sass/plugin/merb.rb +2 -2
  37. data/lib/sass/plugin/rack.rb +3 -3
  38. data/lib/sass/plugin/rails.rb +1 -1
  39. data/lib/sass/plugin/staleness_checker.rb +4 -4
  40. data/lib/sass/plugin.rb +6 -5
  41. data/lib/sass/script/css_lexer.rb +1 -1
  42. data/lib/sass/script/css_parser.rb +2 -3
  43. data/lib/sass/script/css_variable_warning.rb +52 -0
  44. data/lib/sass/script/functions.rb +739 -318
  45. data/lib/sass/script/lexer.rb +134 -54
  46. data/lib/sass/script/parser.rb +252 -56
  47. data/lib/sass/script/tree/funcall.rb +13 -6
  48. data/lib/sass/script/tree/interpolation.rb +127 -4
  49. data/lib/sass/script/tree/list_literal.rb +31 -4
  50. data/lib/sass/script/tree/literal.rb +4 -0
  51. data/lib/sass/script/tree/node.rb +21 -3
  52. data/lib/sass/script/tree/operation.rb +54 -1
  53. data/lib/sass/script/tree/selector.rb +26 -0
  54. data/lib/sass/script/tree/string_interpolation.rb +59 -38
  55. data/lib/sass/script/tree/variable.rb +1 -1
  56. data/lib/sass/script/tree.rb +1 -0
  57. data/lib/sass/script/value/base.rb +17 -14
  58. data/lib/sass/script/value/bool.rb +0 -5
  59. data/lib/sass/script/value/color.rb +78 -42
  60. data/lib/sass/script/value/helpers.rb +119 -2
  61. data/lib/sass/script/value/list.rb +0 -15
  62. data/lib/sass/script/value/map.rb +1 -1
  63. data/lib/sass/script/value/null.rb +0 -5
  64. data/lib/sass/script/value/number.rb +112 -31
  65. data/lib/sass/script/value/string.rb +102 -13
  66. data/lib/sass/script/value.rb +0 -1
  67. data/lib/sass/script.rb +3 -3
  68. data/lib/sass/scss/css_parser.rb +24 -4
  69. data/lib/sass/scss/parser.rb +290 -383
  70. data/lib/sass/scss/rx.rb +17 -9
  71. data/lib/sass/scss/static_parser.rb +306 -4
  72. data/lib/sass/scss.rb +0 -2
  73. data/lib/sass/selector/abstract_sequence.rb +35 -18
  74. data/lib/sass/selector/comma_sequence.rb +114 -19
  75. data/lib/sass/selector/pseudo.rb +266 -0
  76. data/lib/sass/selector/sequence.rb +146 -40
  77. data/lib/sass/selector/simple.rb +22 -33
  78. data/lib/sass/selector/simple_sequence.rb +122 -39
  79. data/lib/sass/selector.rb +57 -197
  80. data/lib/sass/shared.rb +2 -2
  81. data/lib/sass/source/map.rb +31 -14
  82. data/lib/sass/source/position.rb +4 -4
  83. data/lib/sass/stack.rb +2 -8
  84. data/lib/sass/supports.rb +10 -13
  85. data/lib/sass/tree/at_root_node.rb +1 -0
  86. data/lib/sass/tree/charset_node.rb +1 -1
  87. data/lib/sass/tree/comment_node.rb +1 -1
  88. data/lib/sass/tree/css_import_node.rb +9 -1
  89. data/lib/sass/tree/directive_node.rb +8 -2
  90. data/lib/sass/tree/error_node.rb +18 -0
  91. data/lib/sass/tree/extend_node.rb +1 -1
  92. data/lib/sass/tree/function_node.rb +9 -0
  93. data/lib/sass/tree/import_node.rb +6 -5
  94. data/lib/sass/tree/keyframe_rule_node.rb +15 -0
  95. data/lib/sass/tree/node.rb +5 -3
  96. data/lib/sass/tree/prop_node.rb +6 -7
  97. data/lib/sass/tree/rule_node.rb +26 -11
  98. data/lib/sass/tree/visitors/check_nesting.rb +56 -32
  99. data/lib/sass/tree/visitors/convert.rb +59 -44
  100. data/lib/sass/tree/visitors/cssize.rb +34 -30
  101. data/lib/sass/tree/visitors/deep_copy.rb +6 -1
  102. data/lib/sass/tree/visitors/extend.rb +15 -13
  103. data/lib/sass/tree/visitors/perform.rb +87 -50
  104. data/lib/sass/tree/visitors/set_options.rb +15 -1
  105. data/lib/sass/tree/visitors/to_css.rb +72 -43
  106. data/lib/sass/util/multibyte_string_scanner.rb +0 -2
  107. data/lib/sass/util/normalized_map.rb +0 -1
  108. data/lib/sass/util/subset_map.rb +2 -3
  109. data/lib/sass/util.rb +334 -154
  110. data/lib/sass/version.rb +7 -7
  111. data/lib/sass.rb +10 -8
  112. data/test/sass/cache_test.rb +62 -20
  113. data/test/sass/callbacks_test.rb +1 -1
  114. data/test/sass/compiler_test.rb +24 -11
  115. data/test/sass/conversion_test.rb +241 -50
  116. data/test/sass/css2sass_test.rb +73 -5
  117. data/test/sass/css_variable_test.rb +132 -0
  118. data/test/sass/encoding_test.rb +219 -0
  119. data/test/sass/engine_test.rb +343 -260
  120. data/test/sass/exec_test.rb +12 -2
  121. data/test/sass/extend_test.rb +333 -44
  122. data/test/sass/functions_test.rb +353 -260
  123. data/test/sass/importer_test.rb +40 -21
  124. data/test/sass/logger_test.rb +1 -1
  125. data/test/sass/more_results/more_import.css +1 -1
  126. data/test/sass/more_templates/more1.sass +10 -10
  127. data/test/sass/more_templates/more_import.sass +2 -2
  128. data/test/sass/plugin_test.rb +24 -21
  129. data/test/sass/results/compact.css +1 -1
  130. data/test/sass/results/complex.css +4 -4
  131. data/test/sass/results/expanded.css +1 -1
  132. data/test/sass/results/import.css +1 -1
  133. data/test/sass/results/import_charset_ibm866.css +2 -2
  134. data/test/sass/results/mixins.css +17 -17
  135. data/test/sass/results/nested.css +1 -1
  136. data/test/sass/results/parent_ref.css +2 -2
  137. data/test/sass/results/script.css +5 -5
  138. data/test/sass/results/scss_import.css +1 -1
  139. data/test/sass/script_conversion_test.rb +71 -39
  140. data/test/sass/script_test.rb +714 -123
  141. data/test/sass/scss/css_test.rb +213 -30
  142. data/test/sass/scss/rx_test.rb +8 -4
  143. data/test/sass/scss/scss_test.rb +766 -22
  144. data/test/sass/source_map_test.rb +263 -95
  145. data/test/sass/superselector_test.rb +210 -0
  146. data/test/sass/templates/_partial.sass +1 -1
  147. data/test/sass/templates/basic.sass +10 -10
  148. data/test/sass/templates/bork1.sass +1 -1
  149. data/test/sass/templates/bork5.sass +1 -1
  150. data/test/sass/templates/compact.sass +10 -10
  151. data/test/sass/templates/complex.sass +187 -187
  152. data/test/sass/templates/compressed.sass +10 -10
  153. data/test/sass/templates/expanded.sass +10 -10
  154. data/test/sass/templates/import.sass +2 -2
  155. data/test/sass/templates/importee.sass +3 -3
  156. data/test/sass/templates/mixins.sass +22 -22
  157. data/test/sass/templates/multiline.sass +4 -4
  158. data/test/sass/templates/nested.sass +13 -13
  159. data/test/sass/templates/parent_ref.sass +12 -12
  160. data/test/sass/templates/script.sass +70 -70
  161. data/test/sass/templates/scss_import.scss +2 -1
  162. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +1 -1
  163. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +2 -2
  164. data/test/sass/templates/subdir/subdir.sass +3 -3
  165. data/test/sass/templates/units.sass +10 -10
  166. data/test/sass/test_helper.rb +1 -1
  167. data/test/sass/util/multibyte_string_scanner_test.rb +11 -3
  168. data/test/sass/util/normalized_map_test.rb +1 -1
  169. data/test/sass/util/subset_map_test.rb +2 -2
  170. data/test/sass/util_test.rb +46 -45
  171. data/test/sass/value_helpers_test.rb +5 -7
  172. data/test/sass-spec.yml +3 -0
  173. data/test/test_helper.rb +7 -6
  174. data/vendor/listen/CHANGELOG.md +1 -228
  175. data/vendor/listen/Gemfile +5 -15
  176. data/vendor/listen/README.md +111 -77
  177. data/vendor/listen/Rakefile +0 -42
  178. data/vendor/listen/lib/listen/adapter.rb +195 -82
  179. data/vendor/listen/lib/listen/adapters/bsd.rb +27 -64
  180. data/vendor/listen/lib/listen/adapters/darwin.rb +21 -58
  181. data/vendor/listen/lib/listen/adapters/linux.rb +23 -55
  182. data/vendor/listen/lib/listen/adapters/polling.rb +25 -34
  183. data/vendor/listen/lib/listen/adapters/windows.rb +50 -46
  184. data/vendor/listen/lib/listen/directory_record.rb +96 -61
  185. data/vendor/listen/lib/listen/listener.rb +135 -37
  186. data/vendor/listen/lib/listen/turnstile.rb +9 -5
  187. data/vendor/listen/lib/listen/version.rb +1 -1
  188. data/vendor/listen/lib/listen.rb +33 -19
  189. data/vendor/listen/listen.gemspec +6 -0
  190. data/vendor/listen/spec/listen/adapter_spec.rb +43 -77
  191. data/vendor/listen/spec/listen/adapters/polling_spec.rb +8 -8
  192. data/vendor/listen/spec/listen/directory_record_spec.rb +81 -56
  193. data/vendor/listen/spec/listen/listener_spec.rb +128 -39
  194. data/vendor/listen/spec/listen_spec.rb +15 -21
  195. data/vendor/listen/spec/spec_helper.rb +4 -0
  196. data/vendor/listen/spec/support/adapter_helper.rb +52 -15
  197. data/vendor/listen/spec/support/directory_record_helper.rb +7 -5
  198. data/vendor/listen/spec/support/listeners_helper.rb +30 -7
  199. metadata +310 -300
  200. data/CONTRIBUTING +0 -3
  201. data/ext/mkrf_conf.rb +0 -27
  202. data/lib/sass/script/value/deprecated_false.rb +0 -55
  203. data/lib/sass/scss/script_lexer.rb +0 -15
  204. data/lib/sass/scss/script_parser.rb +0 -25
  205. data/vendor/listen/lib/listen/dependency_manager.rb +0 -126
  206. data/vendor/listen/lib/listen/multi_listener.rb +0 -143
  207. data/vendor/listen/spec/listen/dependency_manager_spec.rb +0 -107
  208. data/vendor/listen/spec/listen/multi_listener_spec.rb +0 -174
@@ -17,15 +17,16 @@ module Sass::Script::Value
17
17
  # @private
18
18
  #
19
19
  # Convert a ruby integer to a rgba components
20
- # @param color [Fixnum]
21
- # @return [Array<Fixnum>] Array of 4 numbers representing r,g,b and alpha
20
+ # @param color [Integer]
21
+ # @return [Array<Integer>] Array of 4 numbers representing r,g,b and alpha
22
22
  def self.int_to_rgba(color)
23
23
  rgba = (0..3).map {|n| color >> (n << 3) & 0xff}.reverse
24
24
  rgba[-1] = rgba[-1] / 255.0
25
25
  rgba
26
26
  end
27
27
 
28
- ALTERNATE_COLOR_NAMES = Sass::Util.map_vals({
28
+ ALTERNATE_COLOR_NAMES = Sass::Util.map_vals(
29
+ {
29
30
  'aqua' => 0x00FFFFFF,
30
31
  'darkgrey' => 0xA9A9A9FF,
31
32
  'darkslategrey' => 0x2F4F4FFF,
@@ -35,10 +36,11 @@ module Sass::Script::Value
35
36
  'lightgrey' => 0xD3D3D3FF,
36
37
  'lightslategrey' => 0x778899FF,
37
38
  'slategrey' => 0x708090FF,
38
- }, &method(:int_to_rgba))
39
+ }, &method(:int_to_rgba))
39
40
 
40
41
  # A hash from color names to `[red, green, blue]` value arrays.
41
- COLOR_NAMES = Sass::Util.map_vals({
42
+ COLOR_NAMES = Sass::Util.map_vals(
43
+ {
42
44
  'aliceblue' => 0xF0F8FFFF,
43
45
  'antiquewhite' => 0xFAEBD7FF,
44
46
  'aquamarine' => 0x7FFFD4FF,
@@ -151,6 +153,7 @@ module Sass::Script::Value
151
153
  'powderblue' => 0xB0E0E6FF,
152
154
  'purple' => 0x800080FF,
153
155
  'red' => 0xFF0000FF,
156
+ 'rebeccapurple' => 0x663399FF,
154
157
  'rosybrown' => 0xBC8F8FFF,
155
158
  'royalblue' => 0x4169E1FF,
156
159
  'saddlebrown' => 0x8B4513FF,
@@ -178,7 +181,7 @@ module Sass::Script::Value
178
181
  'whitesmoke' => 0xF5F5F5FF,
179
182
  'yellow' => 0xFFFF00FF,
180
183
  'yellowgreen' => 0x9ACD32FF
181
- }, &method(:int_to_rgba))
184
+ }, &method(:int_to_rgba))
182
185
 
183
186
  # A hash from `[red, green, blue, alpha]` value arrays to color names.
184
187
  COLOR_NAMES_REVERSE = COLOR_NAMES.invert.freeze
@@ -187,35 +190,43 @@ module Sass::Script::Value
187
190
  # different ruby implementations and versions vary on the ordering of the result of invert.
188
191
  COLOR_NAMES.update(ALTERNATE_COLOR_NAMES).freeze
189
192
 
193
+ # The user's original representation of the color.
194
+ #
195
+ # @return [String]
196
+ attr_reader :representation
197
+
190
198
  # Constructs an RGB or HSL color object,
191
199
  # optionally with an alpha channel.
192
200
  #
193
- # The RGB values must be between 0 and 255.
194
- # The saturation and lightness values must be between 0 and 100.
195
- # The alpha value must be between 0 and 1.
201
+ # RGB values are clipped within 0 and 255.
202
+ # Saturation and lightness values are clipped within 0 and 100.
203
+ # The alpha value is clipped within 0 and 1.
196
204
  #
197
205
  # @raise [Sass::SyntaxError] if any color value isn't in the specified range
198
206
  #
199
207
  # @overload initialize(attrs)
200
- # The attributes are specified as a hash.
201
- # This hash must contain either `:hue`, `:saturation`, and `:value` keys,
202
- # or `:red`, `:green`, and `:blue` keys.
203
- # It cannot contain both HSL and RGB keys.
204
- # It may also optionally contain an `:alpha` key.
208
+ # The attributes are specified as a hash. This hash must contain either
209
+ # `:hue`, `:saturation`, and `:lightness` keys, or `:red`, `:green`, and
210
+ # `:blue` keys. It cannot contain both HSL and RGB keys. It may also
211
+ # optionally contain an `:alpha` key, and a `:representation` key
212
+ # indicating the original representation of the color that the user wrote
213
+ # in their stylesheet.
205
214
  #
206
215
  # @param attrs [{Symbol => Numeric}] A hash of color attributes to values
207
216
  # @raise [ArgumentError] if not enough attributes are specified,
208
217
  # or both RGB and HSL attributes are specified
209
218
  #
210
- # @overload initialize(rgba)
219
+ # @overload initialize(rgba, [representation])
211
220
  # The attributes are specified as an array.
212
221
  # This overload only supports RGB or RGBA colors.
213
222
  #
214
223
  # @param rgba [Array<Numeric>] A three- or four-element array
215
224
  # of the red, green, blue, and optionally alpha values (respectively)
216
225
  # of the color
226
+ # @param representation [String] The original representation of the color
227
+ # that the user wrote in their stylesheet.
217
228
  # @raise [ArgumentError] if not enough attributes are specified
218
- def initialize(attrs, allow_both_rgb_and_hsl = false)
229
+ def initialize(attrs, representation = nil, allow_both_rgb_and_hsl = false)
219
230
  super(nil)
220
231
 
221
232
  if attrs.is_a?(Array)
@@ -223,11 +234,12 @@ module Sass::Script::Value
223
234
  raise ArgumentError.new("Color.new(array) expects a three- or four-element array")
224
235
  end
225
236
 
226
- red, green, blue = attrs[0...3].map {|c| c.to_i}
237
+ red, green, blue = attrs[0...3].map {|c| Sass::Util.round(c)}
227
238
  @attrs = {:red => red, :green => green, :blue => blue}
228
239
  @attrs[:alpha] = attrs[3] ? attrs[3].to_f : 1
240
+ @representation = representation
229
241
  else
230
- attrs = attrs.reject {|k, v| v.nil?}
242
+ attrs = attrs.reject {|_k, v| v.nil?}
231
243
  hsl = [:hue, :saturation, :lightness] & attrs.keys
232
244
  rgb = [:red, :green, :blue] & attrs.keys
233
245
  if !allow_both_rgb_and_hsl && !hsl.empty? && !rgb.empty?
@@ -243,21 +255,20 @@ module Sass::Script::Value
243
255
  @attrs = attrs
244
256
  @attrs[:hue] %= 360 if @attrs[:hue]
245
257
  @attrs[:alpha] ||= 1
258
+ @representation = @attrs.delete(:representation)
246
259
  end
247
260
 
248
261
  [:red, :green, :blue].each do |k|
249
262
  next if @attrs[k].nil?
250
- @attrs[k] = @attrs[k].to_i
251
- Sass::Util.check_range("#{k.to_s.capitalize} value", 0..255, @attrs[k])
263
+ @attrs[k] = Sass::Util.restrict(Sass::Util.round(@attrs[k]), 0..255)
252
264
  end
253
265
 
254
266
  [:saturation, :lightness].each do |k|
255
267
  next if @attrs[k].nil?
256
- value = Number.new(@attrs[k], ['%']) # Get correct unit for error messages
257
- @attrs[k] = Sass::Util.check_range("#{k.to_s.capitalize}", 0..100, value, '%')
268
+ @attrs[k] = Sass::Util.restrict(@attrs[k], 0..100)
258
269
  end
259
270
 
260
- @attrs[:alpha] = Sass::Util.check_range("Alpha channel", 0..1, @attrs[:alpha])
271
+ @attrs[:alpha] = Sass::Util.restrict(@attrs[:alpha], 0..1)
261
272
  end
262
273
 
263
274
  # Create a new color from a valid CSS hex string.
@@ -273,14 +284,16 @@ module Sass::Script::Value
273
284
  red = $1.ljust(2, $1).to_i(16)
274
285
  green = $2.ljust(2, $2).to_i(16)
275
286
  blue = $3.ljust(2, $3).to_i(16)
276
- attrs = {:red => red, :green => green, :blue => blue}
287
+
288
+ hex_string = "##{hex_string}" unless hex_string[0] == ?#
289
+ attrs = {:red => red, :green => green, :blue => blue, :representation => hex_string}
277
290
  attrs[:alpha] = alpha if alpha
278
291
  new(attrs)
279
292
  end
280
293
 
281
294
  # The red component of the color.
282
295
  #
283
- # @return [Fixnum]
296
+ # @return [Integer]
284
297
  def red
285
298
  hsl_to_rgb!
286
299
  @attrs[:red]
@@ -288,7 +301,7 @@ module Sass::Script::Value
288
301
 
289
302
  # The green component of the color.
290
303
  #
291
- # @return [Fixnum]
304
+ # @return [Integer]
292
305
  def green
293
306
  hsl_to_rgb!
294
307
  @attrs[:green]
@@ -296,7 +309,7 @@ module Sass::Script::Value
296
309
 
297
310
  # The blue component of the color.
298
311
  #
299
- # @return [Fixnum]
312
+ # @return [Integer]
300
313
  def blue
301
314
  hsl_to_rgb!
302
315
  @attrs[:blue]
@@ -329,7 +342,7 @@ module Sass::Script::Value
329
342
  # The alpha channel (opacity) of the color.
330
343
  # This is 1 unless otherwise defined.
331
344
  #
332
- # @return [Fixnum]
345
+ # @return [Integer]
333
346
  def alpha
334
347
  @attrs[:alpha].to_f
335
348
  end
@@ -344,7 +357,7 @@ module Sass::Script::Value
344
357
 
345
358
  # Returns the red, green, and blue components of the color.
346
359
  #
347
- # @return [Array<Fixnum>] A frozen three-element array of the red, green, and blue
360
+ # @return [Array<Integer>] A frozen three-element array of the red, green, and blue
348
361
  # values (respectively) of the color
349
362
  def rgb
350
363
  [red, green, blue].freeze
@@ -352,7 +365,7 @@ module Sass::Script::Value
352
365
 
353
366
  # Returns the red, green, blue, and alpha components of the color.
354
367
  #
355
- # @return [Array<Fixnum>] A frozen four-element array of the red, green,
368
+ # @return [Array<Integer>] A frozen four-element array of the red, green,
356
369
  # blue, and alpha values (respectively) of the color
357
370
  def rgba
358
371
  [red, green, blue, alpha].freeze
@@ -360,7 +373,7 @@ module Sass::Script::Value
360
373
 
361
374
  # Returns the hue, saturation, and lightness components of the color.
362
375
  #
363
- # @return [Array<Fixnum>] A frozen three-element array of the
376
+ # @return [Array<Integer>] A frozen three-element array of the
364
377
  # hue, saturation, and lightness values (respectively) of the color
365
378
  def hsl
366
379
  [hue, saturation, lightness].freeze
@@ -368,10 +381,10 @@ module Sass::Script::Value
368
381
 
369
382
  # Returns the hue, saturation, lightness, and alpha components of the color.
370
383
  #
371
- # @return [Array<Fixnum>] A frozen four-element array of the hue,
384
+ # @return [Array<Integer>] A frozen four-element array of the hue,
372
385
  # saturation, lightness, and alpha values (respectively) of the color
373
386
  def hsla
374
- [hue, saturation, lightness].freeze
387
+ [hue, saturation, lightness, alpha].freeze
375
388
  end
376
389
 
377
390
  # The SassScript `==` operation.
@@ -410,7 +423,7 @@ module Sass::Script::Value
410
423
  # @return [Color] The new Color object
411
424
  # @raise [ArgumentError] if both RGB and HSL keys are specified
412
425
  def with(attrs)
413
- attrs = attrs.reject {|k, v| v.nil?}
426
+ attrs = attrs.reject {|_k, v| v.nil?}
414
427
  hsl = !([:hue, :saturation, :lightness] & attrs.keys).empty?
415
428
  rgb = !([:red, :green, :blue] & attrs.keys).empty?
416
429
  if hsl && rgb
@@ -428,7 +441,7 @@ module Sass::Script::Value
428
441
  end
429
442
  attrs[:alpha] ||= alpha
430
443
 
431
- Color.new(attrs, :allow_both_rgb_and_hsl)
444
+ Color.new(attrs, nil, :allow_both_rgb_and_hsl)
432
445
  end
433
446
 
434
447
  # The SassScript `+` operation.
@@ -549,7 +562,8 @@ module Sass::Script::Value
549
562
  # @return [String] The string representation
550
563
  def to_s(opts = {})
551
564
  return smallest if options[:style] == :compressed
552
- return COLOR_NAMES_REVERSE[rgba] if COLOR_NAMES_REVERSE[rgba]
565
+ return representation if representation
566
+ return name if name
553
567
  alpha? ? rgba_str : hex_str
554
568
  end
555
569
  alias_method :to_sass, :to_s
@@ -561,13 +575,19 @@ module Sass::Script::Value
561
575
  alpha? ? rgba_str : hex_str
562
576
  end
563
577
 
578
+ # Returns the color's name, if it has one.
579
+ #
580
+ # @return [String, nil]
581
+ def name
582
+ COLOR_NAMES_REVERSE[rgba]
583
+ end
584
+
564
585
  private
565
586
 
566
587
  def smallest
567
588
  small_explicit_str = alpha? ? rgba_str : hex_str.gsub(/^#(.)\1(.)\2(.)\3$/, '#\1\2\3')
568
- return small_explicit_str unless (color = COLOR_NAMES_REVERSE[rgba]) &&
569
- color.size <= small_explicit_str.size
570
- color
589
+ [representation, COLOR_NAMES_REVERSE[rgba], small_explicit_str].
590
+ compact.min_by {|str| str.size}
571
591
  end
572
592
 
573
593
  def rgba_str
@@ -580,16 +600,32 @@ module Sass::Script::Value
580
600
  "##{red}#{green}#{blue}"
581
601
  end
582
602
 
603
+ def operation_name(operation)
604
+ case operation
605
+ when :+
606
+ "add"
607
+ when :-
608
+ "subtract"
609
+ when :*
610
+ "multiply"
611
+ when :/
612
+ "divide"
613
+ when :%
614
+ "modulo"
615
+ end
616
+ end
617
+
583
618
  def piecewise(other, operation)
584
619
  other_num = other.is_a? Number
585
620
  if other_num && !other.unitless?
586
621
  raise Sass::SyntaxError.new(
587
- "Cannot add a number with units (#{other}) to a color (#{self}).")
622
+ "Cannot #{operation_name(operation)} a number with units (#{other}) to a color (#{self})."
623
+ )
588
624
  end
589
625
 
590
626
  result = []
591
627
  (0...3).each do |i|
592
- res = rgb[i].send(operation, other_num ? other.value : other.rgb[i])
628
+ res = rgb[i].to_f.send(operation, other_num ? other.value : other.rgb[i])
593
629
  result[i] = [[res, 255].min, 0].max
594
630
  end
595
631
 
@@ -614,7 +650,7 @@ module Sass::Script::Value
614
650
  hue_to_rgb(m1, m2, h + 1.0 / 3),
615
651
  hue_to_rgb(m1, m2, h),
616
652
  hue_to_rgb(m1, m2, h - 1.0 / 3)
617
- ].map {|c| (c * 0xff).round}
653
+ ].map {|c| Sass::Util.round(c * 0xff)}
618
654
  end
619
655
 
620
656
  def hue_to_rgb(m1, m2, h)
@@ -1,6 +1,8 @@
1
1
  module Sass::Script::Value
2
2
  # Provides helper functions for creating sass values from within ruby methods.
3
3
  # @since `3.3.0`
4
+ # @comment
5
+ # rubocop:disable ModuleLength
4
6
  module Helpers
5
7
  # Construct a Sass Boolean.
6
8
  #
@@ -121,8 +123,123 @@ module Sass::Script::Value
121
123
  end
122
124
  alias_method :identifier, :unquoted_string
123
125
 
126
+ # Parses a user-provided selector.
127
+ #
128
+ # @param value [Sass::Script::Value::String, Sass::Script::Value::List]
129
+ # The selector to parse. This can be either a string, a list of
130
+ # strings, or a list of lists of strings as returned by `&`.
131
+ # @param name [Symbol, nil]
132
+ # If provided, the name of the selector argument. This is used
133
+ # for error reporting.
134
+ # @param allow_parent_ref [Boolean]
135
+ # Whether the parsed selector should allow parent references.
136
+ # @return [Sass::Selector::CommaSequence] The parsed selector.
137
+ # @throw [ArgumentError] if the parse failed for any reason.
138
+ def parse_selector(value, name = nil, allow_parent_ref = false)
139
+ str = normalize_selector(value, name)
140
+ begin
141
+ Sass::SCSS::StaticParser.new(str, nil, nil, 1, 1, allow_parent_ref).parse_selector
142
+ rescue Sass::SyntaxError => e
143
+ err = "#{value.inspect} is not a valid selector: #{e}"
144
+ err = "$#{name.to_s.tr('_', '-')}: #{err}" if name
145
+ raise ArgumentError.new(err)
146
+ end
147
+ end
148
+
149
+ # Parses a user-provided complex selector.
150
+ #
151
+ # A complex selector can contain combinators but cannot contain commas.
152
+ #
153
+ # @param value [Sass::Script::Value::String, Sass::Script::Value::List]
154
+ # The selector to parse. This can be either a string or a list of
155
+ # strings.
156
+ # @param name [Symbol, nil]
157
+ # If provided, the name of the selector argument. This is used
158
+ # for error reporting.
159
+ # @param allow_parent_ref [Boolean]
160
+ # Whether the parsed selector should allow parent references.
161
+ # @return [Sass::Selector::Sequence] The parsed selector.
162
+ # @throw [ArgumentError] if the parse failed for any reason.
163
+ def parse_complex_selector(value, name = nil, allow_parent_ref = false)
164
+ selector = parse_selector(value, name, allow_parent_ref)
165
+ return seq if selector.members.length == 1
166
+
167
+ err = "#{value.inspect} is not a complex selector"
168
+ err = "$#{name.to_s.tr('_', '-')}: #{err}" if name
169
+ raise ArgumentError.new(err)
170
+ end
171
+
172
+ # Parses a user-provided compound selector.
173
+ #
174
+ # A compound selector cannot contain combinators or commas.
175
+ #
176
+ # @param value [Sass::Script::Value::String] The selector to parse.
177
+ # @param name [Symbol, nil]
178
+ # If provided, the name of the selector argument. This is used
179
+ # for error reporting.
180
+ # @param allow_parent_ref [Boolean]
181
+ # Whether the parsed selector should allow parent references.
182
+ # @return [Sass::Selector::SimpleSequence] The parsed selector.
183
+ # @throw [ArgumentError] if the parse failed for any reason.
184
+ def parse_compound_selector(value, name = nil, allow_parent_ref = false)
185
+ assert_type value, :String, name
186
+ selector = parse_selector(value, name, allow_parent_ref)
187
+ seq = selector.members.first
188
+ sseq = seq.members.first
189
+ if selector.members.length == 1 && seq.members.length == 1 &&
190
+ sseq.is_a?(Sass::Selector::SimpleSequence)
191
+ return sseq
192
+ end
193
+
194
+ err = "#{value.inspect} is not a compound selector"
195
+ err = "$#{name.to_s.tr('_', '-')}: #{err}" if name
196
+ raise ArgumentError.new(err)
197
+ end
198
+
199
+ # Returns true when the literal is a string containing a calc()
200
+ #
201
+ # @param literal [Sass::Script::Value::Base] The value to check
202
+ # @return boolean
203
+ def calc?(literal)
204
+ literal.is_a?(Sass::Script::Value::String) && literal.value =~ /calc\(/
205
+ end
206
+
124
207
  private
125
208
 
209
+ # Converts a user-provided selector into string form or throws an
210
+ # ArgumentError if it's in an invalid format.
211
+ def normalize_selector(value, name)
212
+ if (str = selector_to_str(value))
213
+ return str
214
+ end
215
+
216
+ err = "#{value.inspect} is not a valid selector: it must be a string,\n" +
217
+ "a list of strings, or a list of lists of strings"
218
+ err = "$#{name.to_s.tr('_', '-')}: #{err}" if name
219
+ raise ArgumentError.new(err)
220
+ end
221
+
222
+ # Converts a user-provided selector into string form or returns
223
+ # `nil` if it's in an invalid format.
224
+ def selector_to_str(value)
225
+ return value.value if value.is_a?(Sass::Script::String)
226
+ return unless value.is_a?(Sass::Script::List)
227
+
228
+ if value.separator == :comma
229
+ return value.to_a.map do |complex|
230
+ next complex.value if complex.is_a?(Sass::Script::String)
231
+ return unless complex.is_a?(Sass::Script::List) && complex.separator == :space
232
+ return unless (str = selector_to_str(complex))
233
+ str
234
+ end.join(', ')
235
+ end
236
+
237
+ value.to_a.map do |compound|
238
+ return unless compound.is_a?(Sass::Script::String)
239
+ compound.value
240
+ end.join(' ')
241
+ end
242
+
126
243
  # @private
127
244
  VALID_UNIT = /#{Sass::SCSS::RX::NMSTART}#{Sass::SCSS::RX::NMCHAR}|%*/
128
245
 
@@ -135,14 +252,14 @@ module Sass::Script::Value
135
252
  def parse_unit_string(unit_string)
136
253
  denominator_units = numerator_units = Sass::Script::Value::Number::NO_UNITS
137
254
  return numerator_units, denominator_units unless unit_string && unit_string.length > 0
138
- num_over_denominator = unit_string.split(/ *\/ */)
255
+ num_over_denominator = unit_string.split(%r{ */ *})
139
256
  unless (1..2).include?(num_over_denominator.size)
140
257
  raise ArgumentError.new("Malformed unit string: #{unit_string}")
141
258
  end
142
259
  numerator_units = num_over_denominator[0].split(/ *\* */)
143
260
  denominator_units = (num_over_denominator[1] || "").split(/ *\* */)
144
261
  [[numerator_units, "numerator"], [denominator_units, "denominator"]].each do |units, name|
145
- if unit_string =~ /\// && units.size == 0
262
+ if unit_string =~ %r{/} && units.size == 0
146
263
  raise ArgumentError.new("Malformed unit string: #{unit_string}")
147
264
  end
148
265
  if units.any? {|unit| unit !~ VALID_UNIT}
@@ -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))})"
@@ -56,7 +56,7 @@ module Sass::Script::Value
56
56
  return "()" if value.empty?
57
57
 
58
58
  to_sass = lambda do |value|
59
- if value.is_a?(Map) || (value.is_a?(List) && value.separator == :comma)
59
+ if value.is_a?(List) && value.separator == :comma
60
60
  "(#{value.to_sass(opts)})"
61
61
  else
62
62
  value.to_sass(opts)
@@ -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
  ''