sass 3.3.0 → 3.4.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
  ''