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
@@ -1,6 +1,9 @@
1
1
  require 'sass/script/value/helpers'
2
2
 
3
3
  module Sass::Script
4
+ # @comment
5
+ # YARD can't handle some multiline tags, and we need really long tags for function declarations.
6
+ # rubocop:disable LineLength
4
7
  # Methods in this module are accessible from the SassScript context.
5
8
  # For example, you can write
6
9
  #
@@ -93,16 +96,13 @@ module Sass::Script
93
96
  #
94
97
  # ## Other Color Functions
95
98
  #
96
- # \{#adjust_color adjust-color($color, \[$red\], \[$green\], \[$blue\],
97
- # \[$hue\], \[$saturation\], \[$lightness\], \[$alpha\])}
99
+ # \{#adjust_color adjust-color($color, \[$red\], \[$green\], \[$blue\], \[$hue\], \[$saturation\], \[$lightness\], \[$alpha\])}
98
100
  # : Increases or decreases one or more components of a color.
99
101
  #
100
- # \{#scale_color scale-color($color, \[$red\], \[$green\], \[$blue\],
101
- # \[$saturation\], \[$lightness\], \[$alpha\])}
102
+ # \{#scale_color scale-color($color, \[$red\], \[$green\], \[$blue\], \[$saturation\], \[$lightness\], \[$alpha\])}
102
103
  # : Fluidly scales one or more properties of a color.
103
104
  #
104
- # \{#change_color change-color($color, \[$red\], \[$green\], \[$blue\],
105
- # \[$hue\], \[$saturation\], \[$lightness\], \[$alpha\])}
105
+ # \{#change_color change-color($color, \[$red\], \[$green\], \[$blue\], \[$hue\], \[$saturation\], \[$lightness\], \[$alpha\])}
106
106
  # : Changes one or more properties of a color.
107
107
  #
108
108
  # \{#ie_hex_str ie-hex-str($color)}
@@ -123,7 +123,7 @@ module Sass::Script
123
123
  # : Inserts `$insert` into `$string` at `$index`.
124
124
  #
125
125
  # \{#str_index str-index($string, $substring)}
126
- # : Returns the index of the first occurance of `$substring` in `$string`.
126
+ # : Returns the index of the first occurrence of `$substring` in `$string`.
127
127
  #
128
128
  # \{#str_slice str-slice($string, $start-at, [$end-at])}
129
129
  # : Extracts a substring from `$string`.
@@ -162,6 +162,9 @@ module Sass::Script
162
162
  #
163
163
  # ## List Functions {#list-functions}
164
164
  #
165
+ # Lists in Sass are immutable; all list functions return a new list rather
166
+ # than updating the existing list in-place.
167
+ #
165
168
  # All list functions work for maps as well, treating them as lists of pairs.
166
169
  #
167
170
  # \{#length length($list)}
@@ -170,6 +173,9 @@ module Sass::Script
170
173
  # \{#nth nth($list, $n)}
171
174
  # : Returns a specific item in a list.
172
175
  #
176
+ # \{#set-nth set-nth($list, $n, $value)}
177
+ # : Replaces the nth item in a list.
178
+ #
173
179
  # \{#join join($list1, $list2, \[$separator\])}
174
180
  # : Joins together two lists into one.
175
181
  #
@@ -182,19 +188,22 @@ module Sass::Script
182
188
  # \{#index index($list, $value)}
183
189
  # : Returns the position of a value within a list.
184
190
  #
185
- # \{#list_separator list-separator(#list)}
191
+ # \{#list_separator list-separator($list)}
186
192
  # : Returns the separator of a list.
187
193
  #
188
194
  # ## Map Functions {#map-functions}
189
195
  #
196
+ # Maps in Sass are immutable; all map functions return a new map rather than
197
+ # updating the existing map in-place.
198
+ #
190
199
  # \{#map_get map-get($map, $key)}
191
200
  # : Returns the value in a map associated with a given key.
192
201
  #
193
202
  # \{#map_merge map-merge($map1, $map2)}
194
203
  # : Merges two maps together into a new map.
195
204
  #
196
- # \{#map_remove map-remove($map, $key)}
197
- # : Returns a new map with a key removed.
205
+ # \{#map_remove map-remove($map, $keys...)}
206
+ # : Returns a new map with keys removed.
198
207
  #
199
208
  # \{#map_keys map-keys($map)}
200
209
  # : Returns a list of all keys in a map.
@@ -202,12 +211,54 @@ module Sass::Script
202
211
  # \{#map_values map-values($map)}
203
212
  # : Returns a list of all values in a map.
204
213
  #
205
- # \{#map_has_key map-has-key($key)}
214
+ # \{#map_has_key map-has-key($map, $key)}
206
215
  # : Returns whether a map has a value associated with a given key.
207
216
  #
208
217
  # \{#keywords keywords($args)}
209
218
  # : Returns the keywords passed to a function that takes variable arguments.
210
219
  #
220
+ # ## Selector Functions
221
+ #
222
+ # Selector functions are very liberal in the formats they support
223
+ # for selector arguments. They can take a plain string, a list of
224
+ # lists as returned by `&` or anything in between:
225
+ #
226
+ # * A plain string, such as `".foo .bar, .baz .bang"`.
227
+ # * A space-separated list of strings such as `(".foo" ".bar")`.
228
+ # * A comma-separated list of strings such as `(".foo .bar", ".baz .bang")`.
229
+ # * A comma-separated list of space-separated lists of strings such
230
+ # as `((".foo" ".bar"), (".baz" ".bang"))`.
231
+ #
232
+ # In general, selector functions allow placeholder selectors
233
+ # (`%foo`) but disallow parent-reference selectors (`&`).
234
+ #
235
+ # \{#selector_nest selector-nest($selectors...)}
236
+ # : Nests selector beneath one another like they would be nested in the
237
+ # stylesheet.
238
+ #
239
+ # \{#selector_append selector-append($selectors...)}
240
+ # : Appends selectors to one another without spaces in between.
241
+ #
242
+ # \{#selector_extend selector-extend($selector, $extendee, $extender)}
243
+ # : Extends `$extendee` with `$extender` within `$selector`.
244
+ #
245
+ # \{#selector_replace selector-replace($selector, $original, $replacement)}
246
+ # : Replaces `$original` with `$replacement` within `$selector`.
247
+ #
248
+ # \{#selector_unify selector-unify($selector1, $selector2)}
249
+ # : Unifies two selectors to produce a selector that matches
250
+ # elements matched by both.
251
+ #
252
+ # \{#is_superselector is-superselector($super, $sub)}
253
+ # : Returns whether `$super` matches all the elements `$sub` does, and
254
+ # possibly more.
255
+ #
256
+ # \{#simple_selectors simple-selectors($selector)}
257
+ # : Returns the simple selectors that comprise a compound selector.
258
+ #
259
+ # \{#selector_parse selector-parse($selector)}
260
+ # : Parses a selector into the format returned by `&`.
261
+ #
211
262
  # ## Introspection Functions
212
263
  #
213
264
  # \{#feature_exists feature-exists($feature)}
@@ -302,6 +353,10 @@ module Sass::Script
302
353
  # safe to call {Value::Base#to_s #to_s} (or other methods that use the string
303
354
  # representation) on those objects without first setting {Tree::Node#options=
304
355
  # the #options attribute}.
356
+ #
357
+ # @comment
358
+ # rubocop:enable LineLength
359
+ # rubocop:disable ModuleLength
305
360
  module Functions
306
361
  @signatures = {}
307
362
 
@@ -376,8 +431,8 @@ module Sass::Script
376
431
  # If no signatures match, the first signature is returned for error messaging.
377
432
  #
378
433
  # @param method_name [Symbol] The name of the Ruby function to be called.
379
- # @param arg_arity [Fixnum] The number of unnamed arguments the function was passed.
380
- # @param kwarg_arity [Fixnum] The number of keyword arguments the function was passed.
434
+ # @param arg_arity [Integer] The number of unnamed arguments the function was passed.
435
+ # @param kwarg_arity [Integer] The number of keyword arguments the function was passed.
381
436
  #
382
437
  # @return [{Symbol => Object}, nil]
383
438
  # The signature options for the matching signature,
@@ -400,8 +455,8 @@ module Sass::Script
400
455
  t_arg_arity = sig_arity
401
456
  end
402
457
 
403
- if (t_arg_arity == sig_arity || t_arg_arity > sig_arity && signature.var_args) &&
404
- (t_kwarg_arity == 0 || t_kwarg_arity > 0 && signature.var_kwargs)
458
+ if (t_arg_arity == sig_arity || t_arg_arity > sig_arity && signature.var_args) &&
459
+ (t_kwarg_arity == 0 || t_kwarg_arity > 0 && signature.var_kwargs)
405
460
  return signature
406
461
  end
407
462
  end
@@ -434,8 +489,7 @@ module Sass::Script
434
489
  include Value::Helpers
435
490
 
436
491
  # The human-readable names for [Sass::Script::Value::Base]. The default is
437
- # just the downcased name of the type. The default is the downcased type
438
- # name.
492
+ # just the downcased name of the type.
439
493
  TYPE_NAMES = {:ArgList => 'variable argument list'}
440
494
 
441
495
  # The environment for this function. This environment's
@@ -473,10 +527,14 @@ module Sass::Script
473
527
  # @raise [ArgumentError] if value is not of the correct type.
474
528
  def assert_type(value, type, name = nil)
475
529
  klass = Sass::Script::Value.const_get(type)
476
- return if value.is_a?(klass)
477
- return if value.is_a?(Sass::Script::Value::List) && type == :Map && value.is_pseudo_map?
530
+ if value.is_a?(klass)
531
+ value.check_deprecated_interp if type == :String
532
+ return
533
+ end
534
+
535
+ return if value.is_a?(Sass::Script::Value::List) && type == :Map && value.value.empty?
478
536
  err = "#{value.inspect} is not a #{TYPE_NAMES[type] || type.to_s.downcase}"
479
- err = "$#{name.to_s.gsub('_', '-')}: " + err if name
537
+ err = "$#{name.to_s.tr('_', '-')}: " + err if name
480
538
  raise ArgumentError.new(err)
481
539
  end
482
540
 
@@ -565,32 +623,38 @@ module Sass::Script
565
623
  #
566
624
  # @see #rgba
567
625
  # @overload rgb($red, $green, $blue)
568
- # @param $red [Sass::Script::Value::Number] The amount of red in the color.
569
- # Must be between 0 and 255 inclusive, or between `0%` and `100%`
570
- # inclusive
571
- # @param $green [Sass::Script::Value::Number] The amount of green in the
572
- # color. Must be between 0 and 255 inclusive, or between `0%` and `100%`
573
- # inclusive
574
- # @param $blue [Sass::Script::Value::Number] The amount of blue in the
575
- # color. Must be between 0 and 255 inclusive, or between `0%` and `100%`
576
- # inclusive
626
+ # @param $red [Sass::Script::Value::Number] The amount of red in the color.
627
+ # Must be between 0 and 255 inclusive, or between `0%` and `100%`
628
+ # inclusive
629
+ # @param $green [Sass::Script::Value::Number] The amount of green in the
630
+ # color. Must be between 0 and 255 inclusive, or between `0%` and `100%`
631
+ # inclusive
632
+ # @param $blue [Sass::Script::Value::Number] The amount of blue in the
633
+ # color. Must be between 0 and 255 inclusive, or between `0%` and `100%`
634
+ # inclusive
577
635
  # @return [Sass::Script::Value::Color]
578
636
  # @raise [ArgumentError] if any parameter is the wrong type or out of bounds
579
637
  def rgb(red, green, blue)
638
+ if calc?(red) || calc?(green) || calc?(blue)
639
+ return unquoted_string("rgb(#{red}, #{green}, #{blue})")
640
+ end
580
641
  assert_type red, :Number, :red
581
642
  assert_type green, :Number, :green
582
643
  assert_type blue, :Number, :blue
583
644
 
584
- color_attrs = [[red, :red], [green, :green], [blue, :blue]].map do |(c, name)|
645
+ color_attrs = [red, green, blue].map do |c|
585
646
  if c.is_unit?("%")
586
- v = Sass::Util.check_range("$#{name}: Color value", 0..100, c, '%')
587
- v * 255 / 100.0
647
+ c.value * 255 / 100.0
588
648
  elsif c.unitless?
589
- Sass::Util.check_range("$#{name}: Color value", 0..255, c)
649
+ c.value
590
650
  else
591
651
  raise ArgumentError.new("Expected #{c} to be unitless or have a unit of % but got #{c}")
592
652
  end
593
653
  end
654
+
655
+ # Don't store the string representation for function-created colors, both
656
+ # because it's not very useful and because some functions aren't supported
657
+ # on older browsers.
594
658
  Sass::Script::Value::Color.new(color_attrs)
595
659
  end
596
660
  declare :rgb, [:red, :green, :blue]
@@ -601,11 +665,11 @@ module Sass::Script
601
665
  #
602
666
  # @overload rgba($red, $green, $blue, $alpha)
603
667
  # @param $red [Sass::Script::Value::Number] The amount of red in the
604
- # color. Must be between 0 and 255 inclusive
668
+ # color. Must be between 0 and 255 inclusive or 0% and 100% inclusive
605
669
  # @param $green [Sass::Script::Value::Number] The amount of green in the
606
- # color. Must be between 0 and 255 inclusive
670
+ # color. Must be between 0 and 255 inclusive or 0% and 100% inclusive
607
671
  # @param $blue [Sass::Script::Value::Number] The amount of blue in the
608
- # color. Must be between 0 and 255 inclusive
672
+ # color. Must be between 0 and 255 inclusive or 0% and 100% inclusive
609
673
  # @param $alpha [Sass::Script::Value::Number] The opacity of the color.
610
674
  # Must be between 0 and 1 inclusive
611
675
  # @return [Sass::Script::Value::Color]
@@ -632,13 +696,20 @@ module Sass::Script
632
696
  color, alpha = args
633
697
 
634
698
  assert_type color, :Color, :color
635
- assert_type alpha, :Number, :alpha
636
-
637
- Sass::Util.check_range('Alpha channel', 0..1, alpha)
638
- color.with(:alpha => alpha.value)
699
+ if calc?(alpha)
700
+ unquoted_string("rgba(#{color.red}, #{color.green}, #{color.blue}, #{alpha})")
701
+ else
702
+ assert_type alpha, :Number, :alpha
703
+ check_alpha_unit alpha, 'rgba'
704
+ color.with(:alpha => alpha.value)
705
+ end
639
706
  when 4
640
707
  red, green, blue, alpha = args
641
- rgba(rgb(red, green, blue), alpha)
708
+ if calc?(red) || calc?(green) || calc?(blue) || calc?(alpha)
709
+ unquoted_string("rgba(#{red}, #{green}, #{blue}, #{alpha})")
710
+ else
711
+ rgba(rgb(red, green, blue), alpha)
712
+ end
642
713
  else
643
714
  raise ArgumentError.new("wrong number of arguments (#{args.size} for 4)")
644
715
  end
@@ -653,17 +724,21 @@ module Sass::Script
653
724
  #
654
725
  # @see #hsla
655
726
  # @overload hsl($hue, $saturation, $lightness)
656
- # @param $hue [Sass::Script::Value::Number] The hue of the color. Should be
657
- # between 0 and 360 degrees, inclusive
658
- # @param $saturation [Sass::Script::Value::Number] The saturation of the
659
- # color. Must be between `0%` and `100%`, inclusive
660
- # @param $lightness [Sass::Script::Value::Number] The lightness of the
661
- # color. Must be between `0%` and `100%`, inclusive
727
+ # @param $hue [Sass::Script::Value::Number] The hue of the color. Should be
728
+ # between 0 and 360 degrees, inclusive
729
+ # @param $saturation [Sass::Script::Value::Number] The saturation of the
730
+ # color. Must be between `0%` and `100%`, inclusive
731
+ # @param $lightness [Sass::Script::Value::Number] The lightness of the
732
+ # color. Must be between `0%` and `100%`, inclusive
662
733
  # @return [Sass::Script::Value::Color]
663
734
  # @raise [ArgumentError] if `$saturation` or `$lightness` are out of bounds
664
735
  # or any parameter is the wrong type
665
736
  def hsl(hue, saturation, lightness)
666
- hsla(hue, saturation, lightness, number(1))
737
+ if calc?(hue) || calc?(saturation) || calc?(lightness)
738
+ unquoted_string("hsl(#{hue}, #{saturation}, #{lightness})")
739
+ else
740
+ hsla(hue, saturation, lightness, number(1))
741
+ end
667
742
  end
668
743
  declare :hsl, [:hue, :saturation, :lightness]
669
744
 
@@ -675,29 +750,34 @@ module Sass::Script
675
750
  #
676
751
  # @see #hsl
677
752
  # @overload hsla($hue, $saturation, $lightness, $alpha)
678
- # @param $hue [Sass::Script::Value::Number] The hue of the color. Should be
679
- # between 0 and 360 degrees, inclusive
680
- # @param $saturation [Sass::Script::Value::Number] The saturation of the
681
- # color. Must be between `0%` and `100%`, inclusive
682
- # @param $lightness [Sass::Script::Value::Number] The lightness of the
683
- # color. Must be between `0%` and `100%`, inclusive
684
- # @param $alpha [Sass::Script::Value::Number] The opacity of the color. Must
685
- # be between 0 and 1, inclusive
753
+ # @param $hue [Sass::Script::Value::Number] The hue of the color. Should be
754
+ # between 0 and 360 degrees, inclusive
755
+ # @param $saturation [Sass::Script::Value::Number] The saturation of the
756
+ # color. Must be between `0%` and `100%`, inclusive
757
+ # @param $lightness [Sass::Script::Value::Number] The lightness of the
758
+ # color. Must be between `0%` and `100%`, inclusive
759
+ # @param $alpha [Sass::Script::Value::Number] The opacity of the color. Must
760
+ # be between 0 and 1, inclusive
686
761
  # @return [Sass::Script::Value::Color]
687
762
  # @raise [ArgumentError] if `$saturation`, `$lightness`, or `$alpha` are out
688
763
  # of bounds or any parameter is the wrong type
689
764
  def hsla(hue, saturation, lightness, alpha)
765
+ if calc?(hue) || calc?(saturation) || calc?(lightness) || calc?(alpha)
766
+ return unquoted_string("hsla(#{hue}, #{saturation}, #{lightness}, #{alpha})")
767
+ end
690
768
  assert_type hue, :Number, :hue
691
769
  assert_type saturation, :Number, :saturation
692
770
  assert_type lightness, :Number, :lightness
693
771
  assert_type alpha, :Number, :alpha
694
-
695
- Sass::Util.check_range('Alpha channel', 0..1, alpha)
772
+ check_alpha_unit alpha, 'hsla'
696
773
 
697
774
  h = hue.value
698
- s = Sass::Util.check_range('Saturation', 0..100, saturation, '%')
699
- l = Sass::Util.check_range('Lightness', 0..100, lightness, '%')
775
+ s = saturation.value
776
+ l = lightness.value
700
777
 
778
+ # Don't store the string representation for function-created colors, both
779
+ # because it's not very useful and because some functions aren't supported
780
+ # on older browsers.
701
781
  Sass::Script::Value::Color.new(
702
782
  :hue => h, :saturation => s, :lightness => l, :alpha => alpha.value)
703
783
  end
@@ -709,7 +789,7 @@ module Sass::Script
709
789
  # [hsl-to-rgb]: http://www.w3.org/TR/css3-color/#hsl-color
710
790
  #
711
791
  # @overload red($color)
712
- # @param $color [Sass::Script::Value::Color]
792
+ # @param $color [Sass::Script::Value::Color]
713
793
  # @return [Sass::Script::Value::Number] The red component, between 0 and 255
714
794
  # inclusive
715
795
  # @raise [ArgumentError] if `$color` isn't a color
@@ -725,7 +805,7 @@ module Sass::Script
725
805
  # [hsl-to-rgb]: http://www.w3.org/TR/css3-color/#hsl-color
726
806
  #
727
807
  # @overload green($color)
728
- # @param $color [Sass::Script::Value::Color]
808
+ # @param $color [Sass::Script::Value::Color]
729
809
  # @return [Sass::Script::Value::Number] The green component, between 0 and
730
810
  # 255 inclusive
731
811
  # @raise [ArgumentError] if `$color` isn't a color
@@ -741,7 +821,7 @@ module Sass::Script
741
821
  # [hsl-to-rgb]: http://www.w3.org/TR/css3-color/#hsl-color
742
822
  #
743
823
  # @overload blue($color)
744
- # @param $color [Sass::Script::Value::Color]
824
+ # @param $color [Sass::Script::Value::Color]
745
825
  # @return [Sass::Script::Value::Number] The blue component, between 0 and
746
826
  # 255 inclusive
747
827
  # @raise [ArgumentError] if `$color` isn't a color
@@ -759,7 +839,7 @@ module Sass::Script
759
839
  # [rgb-to-hsl]: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
760
840
  #
761
841
  # @overload hue($color)
762
- # @param $color [Sass::Script::Value::Color]
842
+ # @param $color [Sass::Script::Value::Color]
763
843
  # @return [Sass::Script::Value::Number] The hue component, between 0deg and
764
844
  # 360deg
765
845
  # @raise [ArgumentError] if `$color` isn't a color
@@ -777,7 +857,7 @@ module Sass::Script
777
857
  # [rgb-to-hsl]: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
778
858
  #
779
859
  # @overload saturation($color)
780
- # @param $color [Sass::Script::Value::Color]
860
+ # @param $color [Sass::Script::Value::Color]
781
861
  # @return [Sass::Script::Value::Number] The saturation component, between 0%
782
862
  # and 100%
783
863
  # @raise [ArgumentError] if `$color` isn't a color
@@ -795,7 +875,7 @@ module Sass::Script
795
875
  # [rgb-to-hsl]: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
796
876
  #
797
877
  # @overload lightness($color)
798
- # @param $color [Sass::Script::Value::Color]
878
+ # @param $color [Sass::Script::Value::Color]
799
879
  # @return [Sass::Script::Value::Number] The lightness component, between 0%
800
880
  # and 100%
801
881
  # @raise [ArgumentError] if `$color` isn't a color
@@ -812,7 +892,7 @@ module Sass::Script
812
892
  # syntax as a special case.
813
893
  #
814
894
  # @overload alpha($color)
815
- # @param $color [Sass::Script::Value::Color]
895
+ # @param $color [Sass::Script::Value::Color]
816
896
  # @return [Sass::Script::Value::Number] The alpha component, between 0 and 1
817
897
  # @raise [ArgumentError] if `$color` isn't a color
818
898
  def alpha(*args)
@@ -821,7 +901,7 @@ module Sass::Script
821
901
  a.value =~ /^[a-zA-Z]+\s*=/
822
902
  end
823
903
  # Support the proprietary MS alpha() function
824
- return identifier("alpha(#{args.map {|a| a.to_s}.join(", ")})")
904
+ return identifier("alpha(#{args.map {|a| a.to_s}.join(', ')})")
825
905
  end
826
906
 
827
907
  raise ArgumentError.new("wrong number of arguments (#{args.size} for 1)") if args.size != 1
@@ -835,7 +915,7 @@ module Sass::Script
835
915
  # otherwise specified.
836
916
  #
837
917
  # @overload opacity($color)
838
- # @param $color [Sass::Script::Value::Color]
918
+ # @param $color [Sass::Script::Value::Color]
839
919
  # @return [Sass::Script::Value::Number] The alpha component, between 0 and 1
840
920
  # @raise [ArgumentError] if `$color` isn't a color
841
921
  def opacity(color)
@@ -855,9 +935,9 @@ module Sass::Script
855
935
  # opacify(rgba(0, 0, 0, 0.5), 0.1) => rgba(0, 0, 0, 0.6)
856
936
  # opacify(rgba(0, 0, 17, 0.8), 0.2) => #001
857
937
  # @overload opacify($color, $amount)
858
- # @param $color [Sass::Script::Value::Color]
859
- # @param $amount [Sass::Script::Value::Number] The amount to increase the
860
- # opacity by, between 0 and 1
938
+ # @param $color [Sass::Script::Value::Color]
939
+ # @param $amount [Sass::Script::Value::Number] The amount to increase the
940
+ # opacity by, between 0 and 1
861
941
  # @return [Sass::Script::Value::Color]
862
942
  # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
863
943
  # is the wrong type
@@ -877,9 +957,9 @@ module Sass::Script
877
957
  # transparentize(rgba(0, 0, 0, 0.5), 0.1) => rgba(0, 0, 0, 0.4)
878
958
  # transparentize(rgba(0, 0, 0, 0.8), 0.2) => rgba(0, 0, 0, 0.6)
879
959
  # @overload transparentize($color, $amount)
880
- # @param $color [Sass::Script::Value::Color]
881
- # @param $amount [Sass::Script::Value::Number] The amount to decrease the
882
- # opacity by, between 0 and 1
960
+ # @param $color [Sass::Script::Value::Color]
961
+ # @param $amount [Sass::Script::Value::Number] The amount to decrease the
962
+ # opacity by, between 0 and 1
883
963
  # @return [Sass::Script::Value::Color]
884
964
  # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
885
965
  # is the wrong type
@@ -899,9 +979,9 @@ module Sass::Script
899
979
  # lighten(hsl(0, 0%, 0%), 30%) => hsl(0, 0, 30)
900
980
  # lighten(#800, 20%) => #e00
901
981
  # @overload lighten($color, $amount)
902
- # @param $color [Sass::Script::Value::Color]
903
- # @param $amount [Sass::Script::Value::Number] The amount to increase the
904
- # lightness by, between `0%` and `100%`
982
+ # @param $color [Sass::Script::Value::Color]
983
+ # @param $amount [Sass::Script::Value::Number] The amount to increase the
984
+ # lightness by, between `0%` and `100%`
905
985
  # @return [Sass::Script::Value::Color]
906
986
  # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
907
987
  # is the wrong type
@@ -918,9 +998,9 @@ module Sass::Script
918
998
  # darken(hsl(25, 100%, 80%), 30%) => hsl(25, 100%, 50%)
919
999
  # darken(#800, 20%) => #200
920
1000
  # @overload darken($color, $amount)
921
- # @param $color [Sass::Script::Value::Color]
922
- # @param $amount [Sass::Script::Value::Number] The amount to dencrease the
923
- # lightness by, between `0%` and `100%`
1001
+ # @param $color [Sass::Script::Value::Color]
1002
+ # @param $amount [Sass::Script::Value::Number] The amount to decrease the
1003
+ # lightness by, between `0%` and `100%`
924
1004
  # @return [Sass::Script::Value::Color]
925
1005
  # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
926
1006
  # is the wrong type
@@ -937,9 +1017,9 @@ module Sass::Script
937
1017
  # saturate(hsl(120, 30%, 90%), 20%) => hsl(120, 50%, 90%)
938
1018
  # saturate(#855, 20%) => #9e3f3f
939
1019
  # @overload saturate($color, $amount)
940
- # @param $color [Sass::Script::Value::Color]
941
- # @param $amount [Sass::Script::Value::Number] The amount to increase the
942
- # saturation by, between `0%` and `100%`
1020
+ # @param $color [Sass::Script::Value::Color]
1021
+ # @param $amount [Sass::Script::Value::Number] The amount to increase the
1022
+ # saturation by, between `0%` and `100%`
943
1023
  # @return [Sass::Script::Value::Color]
944
1024
  # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
945
1025
  # is the wrong type
@@ -960,9 +1040,9 @@ module Sass::Script
960
1040
  # desaturate(hsl(120, 30%, 90%), 20%) => hsl(120, 10%, 90%)
961
1041
  # desaturate(#855, 20%) => #726b6b
962
1042
  # @overload desaturate($color, $amount)
963
- # @param $color [Sass::Script::Value::Color]
964
- # @param $amount [Sass::Script::Value::Number] The amount to decrease the
965
- # saturation by, between `0%` and `100%`
1043
+ # @param $color [Sass::Script::Value::Color]
1044
+ # @param $amount [Sass::Script::Value::Number] The amount to decrease the
1045
+ # saturation by, between `0%` and `100%`
966
1046
  # @return [Sass::Script::Value::Color]
967
1047
  # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
968
1048
  # is the wrong type
@@ -977,12 +1057,12 @@ module Sass::Script
977
1057
  #
978
1058
  # @example
979
1059
  # adjust-hue(hsl(120, 30%, 90%), 60deg) => hsl(180, 30%, 90%)
980
- # adjust-hue(hsl(120, 30%, 90%), 060deg) => hsl(60, 30%, 90%)
1060
+ # adjust-hue(hsl(120, 30%, 90%), -60deg) => hsl(60, 30%, 90%)
981
1061
  # adjust-hue(#811, 45deg) => #886a11
982
1062
  # @overload adjust_hue($color, $degrees)
983
- # @param $color [Sass::Script::Value::Color]
984
- # @param $degrees [Sass::Script::Value::Number] The number of degrees to
985
- # rotate the hue
1063
+ # @param $color [Sass::Script::Value::Color]
1064
+ # @param $degrees [Sass::Script::Value::Number] The number of degrees to
1065
+ # rotate the hue
986
1066
  # @return [Sass::Script::Value::Color]
987
1067
  # @raise [ArgumentError] if either parameter is the wrong type
988
1068
  def adjust_hue(color, degrees)
@@ -999,13 +1079,13 @@ module Sass::Script
999
1079
  # ie-hex-str(#3322BB) => #FF3322BB
1000
1080
  # ie-hex-str(rgba(0, 255, 0, 0.5)) => #8000FF00
1001
1081
  # @overload ie_hex_str($color)
1002
- # @param $color [Sass::Script::Value::Color]
1082
+ # @param $color [Sass::Script::Value::Color]
1003
1083
  # @return [Sass::Script::Value::String] The IE-formatted string
1004
1084
  # representation of the color
1005
1085
  # @raise [ArgumentError] if `$color` isn't a color
1006
1086
  def ie_hex_str(color)
1007
1087
  assert_type color, :Color, :color
1008
- alpha = (color.alpha * 255).round.to_s(16).rjust(2, '0')
1088
+ alpha = Sass::Util.round(color.alpha * 255).to_s(16).rjust(2, '0')
1009
1089
  identifier("##{alpha}#{color.send(:hex_str)[1..-1]}".upcase)
1010
1090
  end
1011
1091
  declare :ie_hex_str, [:color]
@@ -1023,23 +1103,22 @@ module Sass::Script
1023
1103
  # adjust-color(#102030, $blue: 5) => #102035
1024
1104
  # adjust-color(#102030, $red: -5, $blue: 5) => #0b2035
1025
1105
  # adjust-color(hsl(25, 100%, 80%), $lightness: -30%, $alpha: -0.4) => hsla(25, 100%, 50%, 0.6)
1026
- # @overload adjust_color($color, [$red], [$green], [$blue],
1027
- # [$hue], [$saturation], [$lightness], [$alpha])
1028
- # @param $color [Sass::Script::Value::Color]
1029
- # @param $red [Sass::Script::Value::Number] The adjustment to make on the
1030
- # red component, between -255 and 255 inclusive
1031
- # @param $green [Sass::Script::Value::Number] The adjustment to make on the
1032
- # green component, between -255 and 255 inclusive
1033
- # @param $blue [Sass::Script::Value::Number] The adjustment to make on the
1034
- # blue component, between -255 and 255 inclusive
1035
- # @param $hue [Sass::Script::Value::Number] The adjustment to make on the
1036
- # hue component, in degrees
1037
- # @param $saturation [Sass::Script::Value::Number] The adjustment to make on
1038
- # the saturation component, between `-100%` and `100%` inclusive
1039
- # @param $lightness [Sass::Script::Value::Number] The adjustment to make on
1040
- # the lightness component, between `-100%` and `100%` inclusive
1041
- # @param $alpha [Sass::Script::Value::Number] The adjustment to make on the
1042
- # alpha component, between -1 and 1 inclusive
1106
+ # @overload adjust_color($color, [$red], [$green], [$blue], [$hue], [$saturation], [$lightness], [$alpha])
1107
+ # @param $color [Sass::Script::Value::Color]
1108
+ # @param $red [Sass::Script::Value::Number] The adjustment to make on the
1109
+ # red component, between -255 and 255 inclusive
1110
+ # @param $green [Sass::Script::Value::Number] The adjustment to make on the
1111
+ # green component, between -255 and 255 inclusive
1112
+ # @param $blue [Sass::Script::Value::Number] The adjustment to make on the
1113
+ # blue component, between -255 and 255 inclusive
1114
+ # @param $hue [Sass::Script::Value::Number] The adjustment to make on the
1115
+ # hue component, in degrees
1116
+ # @param $saturation [Sass::Script::Value::Number] The adjustment to make on
1117
+ # the saturation component, between `-100%` and `100%` inclusive
1118
+ # @param $lightness [Sass::Script::Value::Number] The adjustment to make on
1119
+ # the lightness component, between `-100%` and `100%` inclusive
1120
+ # @param $alpha [Sass::Script::Value::Number] The adjustment to make on the
1121
+ # alpha component, between -1 and 1 inclusive
1043
1122
  # @return [Sass::Script::Value::Color]
1044
1123
  # @raise [ArgumentError] if any parameter is the wrong type or out-of
1045
1124
  # bounds, or if RGB properties and HSL properties are adjusted at the
@@ -1047,15 +1126,14 @@ module Sass::Script
1047
1126
  def adjust_color(color, kwargs)
1048
1127
  assert_type color, :Color, :color
1049
1128
  with = Sass::Util.map_hash(
1050
- "red" => [-255..255, ""],
1051
- "green" => [-255..255, ""],
1052
- "blue" => [-255..255, ""],
1053
- "hue" => nil,
1054
- "saturation" => [-100..100, "%"],
1055
- "lightness" => [-100..100, "%"],
1056
- "alpha" => [-1..1, ""]
1057
- ) do |name, (range, units)|
1058
-
1129
+ "red" => [-255..255, ""],
1130
+ "green" => [-255..255, ""],
1131
+ "blue" => [-255..255, ""],
1132
+ "hue" => nil,
1133
+ "saturation" => [-100..100, "%"],
1134
+ "lightness" => [-100..100, "%"],
1135
+ "alpha" => [-1..1, ""]
1136
+ ) do |name, (range, units)|
1059
1137
  val = kwargs.delete(name)
1060
1138
  next unless val
1061
1139
  assert_type val, :Number, name
@@ -1101,15 +1179,14 @@ module Sass::Script
1101
1179
  # scale-color(hsl(120, 70%, 80%), $lightness: 50%) => hsl(120, 70%, 90%)
1102
1180
  # scale-color(rgb(200, 150%, 170%), $green: -40%, $blue: 70%) => rgb(200, 90, 229)
1103
1181
  # scale-color(hsl(200, 70%, 80%), $saturation: -90%, $alpha: -30%) => hsla(200, 7%, 80%, 0.7)
1104
- # @overload scale_color($color, [$red], [$green], [$blue],
1105
- # [$saturation], [$lightness], [$alpha])
1106
- # @param $color [Sass::Script::Value::Color]
1107
- # @param $red [Sass::Script::Value::Number]
1108
- # @param $green [Sass::Script::Value::Number]
1109
- # @param $blue [Sass::Script::Value::Number]
1110
- # @param $saturation [Sass::Script::Value::Number]
1111
- # @param $lightness [Sass::Script::Value::Number]
1112
- # @param $alpha [Sass::Script::Value::Number]
1182
+ # @overload scale_color($color, [$red], [$green], [$blue], [$saturation], [$lightness], [$alpha])
1183
+ # @param $color [Sass::Script::Value::Color]
1184
+ # @param $red [Sass::Script::Value::Number]
1185
+ # @param $green [Sass::Script::Value::Number]
1186
+ # @param $blue [Sass::Script::Value::Number]
1187
+ # @param $saturation [Sass::Script::Value::Number]
1188
+ # @param $lightness [Sass::Script::Value::Number]
1189
+ # @param $alpha [Sass::Script::Value::Number]
1113
1190
  # @return [Sass::Script::Value::Color]
1114
1191
  # @raise [ArgumentError] if any parameter is the wrong type or out-of
1115
1192
  # bounds, or if RGB properties and HSL properties are adjusted at the
@@ -1117,14 +1194,13 @@ module Sass::Script
1117
1194
  def scale_color(color, kwargs)
1118
1195
  assert_type color, :Color, :color
1119
1196
  with = Sass::Util.map_hash(
1120
- "red" => 255,
1121
- "green" => 255,
1122
- "blue" => 255,
1123
- "saturation" => 100,
1124
- "lightness" => 100,
1125
- "alpha" => 1
1126
- ) do |name, max|
1127
-
1197
+ "red" => 255,
1198
+ "green" => 255,
1199
+ "blue" => 255,
1200
+ "saturation" => 100,
1201
+ "lightness" => 100,
1202
+ "alpha" => 1
1203
+ ) do |name, max|
1128
1204
  val = kwargs.delete(name)
1129
1205
  next unless val
1130
1206
  assert_type val, :Number, name
@@ -1159,35 +1235,49 @@ module Sass::Script
1159
1235
  # change-color(#102030, $blue: 5) => #102005
1160
1236
  # change-color(#102030, $red: 120, $blue: 5) => #782005
1161
1237
  # change-color(hsl(25, 100%, 80%), $lightness: 40%, $alpha: 0.8) => hsla(25, 100%, 40%, 0.8)
1162
- # @overload change_color($color, [$red], [$green], [$blue], [$hue],
1163
- # [$saturation], [$lightness], [$alpha])
1164
- # @param $color [Sass::Script::Value::Color]
1165
- # @param $red [Sass::Script::Value::Number] The new red component for the
1166
- # color, within 0 and 255 inclusive
1167
- # @param $green [Sass::Script::Value::Number] The new green component for
1168
- # the color, within 0 and 255 inclusive
1169
- # @param $blue [Sass::Script::Value::Number] The new blue component for the
1170
- # color, within 0 and 255 inclusive
1171
- # @param $hue [Sass::Script::Value::Number] The new hue component for the
1172
- # color, in degrees
1173
- # @param $saturation [Sass::Script::Value::Number] The new saturation
1174
- # component for the color, between `0%` and `100%` inclusive
1175
- # @param $lightness [Sass::Script::Value::Number] The new lightness
1176
- # component for the color, within `0%` and `100%` inclusive
1177
- # @param $alpha [Sass::Script::Value::Number] The new alpha component for
1178
- # the color, within 0 and 1 inclusive
1238
+ # @overload change_color($color, [$red], [$green], [$blue], [$hue], [$saturation], [$lightness], [$alpha])
1239
+ # @param $color [Sass::Script::Value::Color]
1240
+ # @param $red [Sass::Script::Value::Number] The new red component for the
1241
+ # color, within 0 and 255 inclusive
1242
+ # @param $green [Sass::Script::Value::Number] The new green component for
1243
+ # the color, within 0 and 255 inclusive
1244
+ # @param $blue [Sass::Script::Value::Number] The new blue component for the
1245
+ # color, within 0 and 255 inclusive
1246
+ # @param $hue [Sass::Script::Value::Number] The new hue component for the
1247
+ # color, in degrees
1248
+ # @param $saturation [Sass::Script::Value::Number] The new saturation
1249
+ # component for the color, between `0%` and `100%` inclusive
1250
+ # @param $lightness [Sass::Script::Value::Number] The new lightness
1251
+ # component for the color, within `0%` and `100%` inclusive
1252
+ # @param $alpha [Sass::Script::Value::Number] The new alpha component for
1253
+ # the color, within 0 and 1 inclusive
1179
1254
  # @return [Sass::Script::Value::Color]
1180
1255
  # @raise [ArgumentError] if any parameter is the wrong type or out-of
1181
1256
  # bounds, or if RGB properties and HSL properties are adjusted at the
1182
1257
  # same time
1183
1258
  def change_color(color, kwargs)
1184
1259
  assert_type color, :Color, :color
1185
- with = Sass::Util.to_hash(%w[red green blue hue saturation lightness alpha].map do |name|
1260
+ with = Sass::Util.map_hash(
1261
+ 'red' => ['Red value', 0..255],
1262
+ 'green' => ['Green value', 0..255],
1263
+ 'blue' => ['Blue value', 0..255],
1264
+ 'hue' => [],
1265
+ 'saturation' => ['Saturation', 0..100, '%'],
1266
+ 'lightness' => ['Lightness', 0..100, '%'],
1267
+ 'alpha' => ['Alpha channel', 0..1]
1268
+ ) do |name, (desc, range, unit)|
1186
1269
  val = kwargs.delete(name)
1187
1270
  next unless val
1188
1271
  assert_type val, :Number, name
1189
- [name.to_sym, val.value]
1190
- end)
1272
+
1273
+ if range
1274
+ val = Sass::Util.check_range(desc, range, val, unit)
1275
+ else
1276
+ val = val.value
1277
+ end
1278
+
1279
+ [name.to_sym, val]
1280
+ end
1191
1281
 
1192
1282
  unless kwargs.empty?
1193
1283
  name, val = kwargs.to_a.first
@@ -1212,11 +1302,11 @@ module Sass::Script
1212
1302
  # mix(#f00, #00f, 25%) => #3f00bf
1213
1303
  # mix(rgba(255, 0, 0, 0.5), #00f) => rgba(63, 0, 191, 0.75)
1214
1304
  # @overload mix($color1, $color2, $weight: 50%)
1215
- # @param $color1 [Sass::Script::Value::Color]
1216
- # @param $color2 [Sass::Script::Value::Color]
1217
- # @param $weight [Sass::Script::Value::Number] The relative weight of each
1218
- # color. Closer to `0%` gives more weight to `$color`, closer to `100%`
1219
- # gives more weight to `$color2`
1305
+ # @param $color1 [Sass::Script::Value::Color]
1306
+ # @param $color2 [Sass::Script::Value::Color]
1307
+ # @param $weight [Sass::Script::Value::Number] The relative weight of each
1308
+ # color. Closer to `100%` gives more weight to `$color1`, closer to `0%`
1309
+ # gives more weight to `$color2`
1220
1310
  # @return [Sass::Script::Value::Color]
1221
1311
  # @raise [ArgumentError] if `$weight` is out of bounds or any parameter is
1222
1312
  # the wrong type
@@ -1257,15 +1347,15 @@ module Sass::Script
1257
1347
  rgba << color1.alpha * p + color2.alpha * (1 - p)
1258
1348
  rgb_color(*rgba)
1259
1349
  end
1260
- declare :mix, [:color1, :color2], :deprecated => [:color_1, :color_2]
1261
- declare :mix, [:color1, :color2, :weight], :deprecated => [:color_1, :color_2, :weight]
1350
+ declare :mix, [:color1, :color2]
1351
+ declare :mix, [:color1, :color2, :weight]
1262
1352
 
1263
1353
  # Converts a color to grayscale. This is identical to `desaturate(color,
1264
1354
  # 100%)`.
1265
1355
  #
1266
1356
  # @see #desaturate
1267
1357
  # @overload grayscale($color)
1268
- # @param $color [Sass::Script::Value::Color]
1358
+ # @param $color [Sass::Script::Value::Color]
1269
1359
  # @return [Sass::Script::Value::Color]
1270
1360
  # @raise [ArgumentError] if `$color` isn't a color
1271
1361
  def grayscale(color)
@@ -1281,7 +1371,7 @@ module Sass::Script
1281
1371
  #
1282
1372
  # @see #adjust_hue #adjust-hue
1283
1373
  # @overload complement($color)
1284
- # @param $color [Sass::Script::Value::Color]
1374
+ # @param $color [Sass::Script::Value::Color]
1285
1375
  # @return [Sass::Script::Value::Color]
1286
1376
  # @raise [ArgumentError] if `$color` isn't a color
1287
1377
  def complement(color)
@@ -1293,7 +1383,7 @@ module Sass::Script
1293
1383
  # are inverted, while the opacity is left alone.
1294
1384
  #
1295
1385
  # @overload invert($color)
1296
- # @param $color [Sass::Script::Value::Color]
1386
+ # @param $color [Sass::Script::Value::Color]
1297
1387
  # @return [Sass::Script::Value::Color]
1298
1388
  # @raise [ArgumentError] if `$color` isn't a color
1299
1389
  def invert(color)
@@ -1317,15 +1407,31 @@ module Sass::Script
1317
1407
  # unquote("foo") => foo
1318
1408
  # unquote(foo) => foo
1319
1409
  # @overload unquote($string)
1320
- # @param $string [Sass::Script::Value::String]
1410
+ # @param $string [Sass::Script::Value::String]
1321
1411
  # @return [Sass::Script::Value::String]
1322
1412
  # @raise [ArgumentError] if `$string` isn't a string
1323
1413
  def unquote(string)
1324
- if string.is_a?(Sass::Script::Value::String) && string.type != :identifier
1325
- identifier(string.value)
1326
- else
1327
- string
1414
+ unless string.is_a?(Sass::Script::Value::String)
1415
+ # Don't warn multiple times for the same source line.
1416
+ # rubocop:disable GlobalVars
1417
+ $_sass_warned_for_unquote ||= Set.new
1418
+ frame = environment.stack.frames.last
1419
+ key = [frame.filename, frame.line] if frame
1420
+ return string if frame && $_sass_warned_for_unquote.include?(key)
1421
+ $_sass_warned_for_unquote << key if frame
1422
+ # rubocop:enable GlobalVars
1423
+
1424
+ Sass::Util.sass_warn(<<MESSAGE.strip)
1425
+ DEPRECATION WARNING: Passing #{string.to_sass}, a non-string value, to unquote()
1426
+ will be an error in future versions of Sass.
1427
+ #{environment.stack.to_s.gsub(/^/, ' ' * 8)}
1428
+ MESSAGE
1429
+ return string
1328
1430
  end
1431
+
1432
+ string.check_deprecated_interp
1433
+ return string if string.type == :identifier
1434
+ identifier(string.value)
1329
1435
  end
1330
1436
  declare :unquote, [:string]
1331
1437
 
@@ -1337,7 +1443,7 @@ module Sass::Script
1337
1443
  # quote("foo") => "foo"
1338
1444
  # quote(foo) => "foo"
1339
1445
  # @overload quote($string)
1340
- # @param $string [Sass::Script::Value::String]
1446
+ # @param $string [Sass::Script::Value::String]
1341
1447
  # @return [Sass::Script::Value::String]
1342
1448
  # @raise [ArgumentError] if `$string` isn't a string
1343
1449
  def quote(string)
@@ -1355,7 +1461,7 @@ module Sass::Script
1355
1461
  # @example
1356
1462
  # str-length("foo") => 3
1357
1463
  # @overload str_length($string)
1358
- # @param $string [Sass::Script::Value::String]
1464
+ # @param $string [Sass::Script::Value::String]
1359
1465
  # @return [Sass::Script::Value::Number]
1360
1466
  # @raise [ArgumentError] if `$string` isn't a string
1361
1467
  def str_length(string)
@@ -1375,12 +1481,12 @@ module Sass::Script
1375
1481
  # str-insert("abcd", "X", 5) => "abcdX"
1376
1482
  #
1377
1483
  # @overload str_insert($string, $insert, $index)
1378
- # @param $string [Sass::Script::Value::String]
1379
- # @param $insert [Sass::Script::Value::String]
1380
- # @param $index [Sass::Script::Value::Number] The position at which
1381
- # `$insert` will be inserted. Negative indices count from the end of
1382
- # `$string`. An index that's outside the bounds of the string will insert
1383
- # `$insert` at the front or back of the string
1484
+ # @param $string [Sass::Script::Value::String]
1485
+ # @param $insert [Sass::Script::Value::String]
1486
+ # @param $index [Sass::Script::Value::Number] The position at which
1487
+ # `$insert` will be inserted. Negative indices count from the end of
1488
+ # `$string`. An index that's outside the bounds of the string will insert
1489
+ # `$insert` at the front or back of the string
1384
1490
  # @return [Sass::Script::Value::String] The result string. This will be
1385
1491
  # quoted if and only if `$string` was quoted
1386
1492
  # @raise [ArgumentError] if any parameter is the wrong type
@@ -1389,18 +1495,18 @@ module Sass::Script
1389
1495
  assert_type insert, :String, :insert
1390
1496
  assert_integer index, :index
1391
1497
  assert_unit index, nil, :index
1392
- insertion_point = if index.value > 0
1393
- [index.value - 1, original.value.size].min
1498
+ insertion_point = if index.to_i > 0
1499
+ [index.to_i - 1, original.value.size].min
1394
1500
  else
1395
- [index.value, -original.value.size - 1].max
1501
+ [index.to_i, -original.value.size - 1].max
1396
1502
  end
1397
1503
  result = original.value.dup.insert(insertion_point, insert.value)
1398
1504
  Sass::Script::Value::String.new(result, original.type)
1399
1505
  end
1400
1506
  declare :str_insert, [:string, :insert, :index]
1401
1507
 
1402
- # Returns the index of the first occurance of `$substring` in `$string`. If
1403
- # there is no such occurance, returns `null`.
1508
+ # Returns the index of the first occurrence of `$substring` in `$string`. If
1509
+ # there is no such occurrence, returns `null`.
1404
1510
  #
1405
1511
  # Note that unlike some languages, the first character in a Sass string is
1406
1512
  # number 1, the second number 2, and so forth.
@@ -1412,8 +1518,8 @@ module Sass::Script
1412
1518
  # str-index(abcd, c) => 3
1413
1519
  #
1414
1520
  # @overload str_index($string, $substring)
1415
- # @param $string [Sass::Script::Value::String]
1416
- # @param $substring [Sass::Script::Value::String]
1521
+ # @param $string [Sass::Script::Value::String]
1522
+ # @param $substring [Sass::Script::Value::String]
1417
1523
  # @return [Sass::Script::Value::Number, Sass::Script::Value::Null]
1418
1524
  # @raise [ArgumentError] if any parameter is the wrong type
1419
1525
  def str_index(string, substring)
@@ -1437,14 +1543,14 @@ module Sass::Script
1437
1543
  # str-slice("abcd", 2, -2) => "bc"
1438
1544
  #
1439
1545
  # @overload str_slice($string, $start-at, $end-at: -1)
1440
- # @param $start-at [Sass::Script::Value::Number] The index of the first
1441
- # character of the substring. If this is negative, it counts from the end
1442
- # of `$string`
1443
- # @param $end-before [Sass::Script::Value::Number] The index of the last
1444
- # character of the substring. If this is negative, it counts from the end
1445
- # of `$string`. Defaults to -1
1446
- # @return [Sass::Script::Value::String] The substring. This will be quoted
1447
- # if and only if `$string` was quoted
1546
+ # @param $start-at [Sass::Script::Value::Number] The index of the first
1547
+ # character of the substring. If this is negative, it counts from the end
1548
+ # of `$string`
1549
+ # @param $end-at [Sass::Script::Value::Number] The index of the last
1550
+ # character of the substring. If this is negative, it counts from the end
1551
+ # of `$string`. Defaults to -1
1552
+ # @return [Sass::Script::Value::String] The substring. This will be quoted
1553
+ # if and only if `$string` was quoted
1448
1554
  # @raise [ArgumentError] if any parameter is the wrong type
1449
1555
  def str_slice(string, start_at, end_at = nil)
1450
1556
  assert_type string, :String, :string
@@ -1453,12 +1559,13 @@ module Sass::Script
1453
1559
  end_at = number(-1) if end_at.nil?
1454
1560
  assert_unit end_at, nil, "end-at"
1455
1561
 
1562
+ return Sass::Script::Value::String.new("", string.type) if end_at.value == 0
1456
1563
  s = start_at.value > 0 ? start_at.value - 1 : start_at.value
1457
1564
  e = end_at.value > 0 ? end_at.value - 1 : end_at.value
1458
1565
  s = string.value.length + s if s < 0
1459
1566
  s = 0 if s < 0
1460
1567
  e = string.value.length + e if e < 0
1461
- e = 0 if s < 0
1568
+ return Sass::Script::Value::String.new("", string.type) if e < 0
1462
1569
  extracted = string.value.slice(s..e)
1463
1570
  Sass::Script::Value::String.new(extracted || "", string.type)
1464
1571
  end
@@ -1471,12 +1578,12 @@ module Sass::Script
1471
1578
  # to-upper-case(abcd) => ABCD
1472
1579
  #
1473
1580
  # @overload to_upper_case($string)
1474
- # @param $string [Sass::Script::Value::String]
1581
+ # @param $string [Sass::Script::Value::String]
1475
1582
  # @return [Sass::Script::Value::String]
1476
1583
  # @raise [ArgumentError] if `$string` isn't a string
1477
1584
  def to_upper_case(string)
1478
1585
  assert_type string, :String, :string
1479
- Sass::Script::Value::String.new(string.value.upcase, string.type)
1586
+ Sass::Script::Value::String.new(Sass::Util.upcase(string.value), string.type)
1480
1587
  end
1481
1588
  declare :to_upper_case, [:string]
1482
1589
 
@@ -1486,12 +1593,12 @@ module Sass::Script
1486
1593
  # to-lower-case(ABCD) => abcd
1487
1594
  #
1488
1595
  # @overload to_lower_case($string)
1489
- # @param $string [Sass::Script::Value::String]
1596
+ # @param $string [Sass::Script::Value::String]
1490
1597
  # @return [Sass::Script::Value::String]
1491
1598
  # @raise [ArgumentError] if `$string` isn't a string
1492
1599
  def to_lower_case(string)
1493
1600
  assert_type string, :String, :string
1494
- Sass::Script::Value::String.new(string.value.downcase, string.type)
1601
+ Sass::Script::Value::String.new(Sass::Util.downcase(string.value), string.type)
1495
1602
  end
1496
1603
  declare :to_lower_case, [:string]
1497
1604
 
@@ -1504,23 +1611,40 @@ module Sass::Script
1504
1611
  # type-of(true) => bool
1505
1612
  # type-of(#fff) => color
1506
1613
  # type-of(blue) => color
1614
+ # type-of(null) => null
1507
1615
  # @overload type_of($value)
1508
- # @param $value [Sass::Script::Value::Base] The value to inspect
1616
+ # @param $value [Sass::Script::Value::Base] The value to inspect
1509
1617
  # @return [Sass::Script::Value::String] The unquoted string name of the
1510
1618
  # value's type
1511
1619
  def type_of(value)
1620
+ value.check_deprecated_interp if value.is_a?(Sass::Script::Value::String)
1512
1621
  identifier(value.class.name.gsub(/Sass::Script::Value::/, '').downcase)
1513
1622
  end
1514
1623
  declare :type_of, [:value]
1515
1624
 
1516
1625
  # Returns whether a feature exists in the current Sass runtime.
1517
1626
  #
1627
+ # The following features are supported:
1628
+ #
1629
+ # * `global-variable-shadowing` indicates that a local variable will shadow
1630
+ # a global variable unless `!global` is used.
1631
+ #
1632
+ # * `extend-selector-pseudoclass` indicates that `@extend` will reach into
1633
+ # selector pseudoclasses like `:not`.
1634
+ #
1635
+ # * `units-level-3` indicates full support for unit arithmetic using units
1636
+ # defined in the [Values and Units Level 3][] spec.
1637
+ #
1638
+ # [Values and Units Level 3]: http://www.w3.org/TR/css3-values/
1639
+ #
1640
+ # * `at-error` indicates that the Sass `@error` directive is supported.
1641
+ #
1518
1642
  # @example
1519
1643
  # feature-exists(some-feature-that-exists) => true
1520
1644
  # feature-exists(what-is-this-i-dont-know) => false
1521
1645
  #
1522
1646
  # @overload feature_exists($feature)
1523
- # @param $feature [Sass::Script::Value::String] The name of the feature
1647
+ # @param $feature [Sass::Script::Value::String] The name of the feature
1524
1648
  # @return [Sass::Script::Value::Bool] Whether the feature is supported in this version of Sass
1525
1649
  # @raise [ArgumentError] if `$feature` isn't a string
1526
1650
  def feature_exists(feature)
@@ -1539,7 +1663,7 @@ module Sass::Script
1539
1663
  # unit(10px * 5em) => "em*px"
1540
1664
  # unit(10px * 5em / 30cm / 1rem) => "em*px/cm*rem"
1541
1665
  # @overload unit($number)
1542
- # @param $number [Sass::Script::Value::Number]
1666
+ # @param $number [Sass::Script::Value::Number]
1543
1667
  # @return [Sass::Script::Value::String] The unit(s) of the number, as a
1544
1668
  # quoted string
1545
1669
  # @raise [ArgumentError] if `$number` isn't a number
@@ -1555,7 +1679,7 @@ module Sass::Script
1555
1679
  # unitless(100) => true
1556
1680
  # unitless(100px) => false
1557
1681
  # @overload unitless($number)
1558
- # @param $number [Sass::Script::Value::Number]
1682
+ # @param $number [Sass::Script::Value::Number]
1559
1683
  # @return [Sass::Script::Value::Bool]
1560
1684
  # @raise [ArgumentError] if `$number` isn't a number
1561
1685
  def unitless(number)
@@ -1571,8 +1695,8 @@ module Sass::Script
1571
1695
  # comparable(100px, 3em) => false
1572
1696
  # comparable(10cm, 3mm) => true
1573
1697
  # @overload comparable($number1, $number2)
1574
- # @param $number1 [Sass::Script::Value::Number]
1575
- # @param $number2 [Sass::Script::Value::Number]
1698
+ # @param $number1 [Sass::Script::Value::Number]
1699
+ # @param $number2 [Sass::Script::Value::Number]
1576
1700
  # @return [Sass::Script::Value::Bool]
1577
1701
  # @raise [ArgumentError] if either parameter is the wrong type
1578
1702
  def comparable(number1, number2)
@@ -1580,7 +1704,7 @@ module Sass::Script
1580
1704
  assert_type number2, :Number, :number2
1581
1705
  bool(number1.comparable_to?(number2))
1582
1706
  end
1583
- declare :comparable, [:number1, :number2], :deprecated => [:number_1, :number_2]
1707
+ declare :comparable, [:number1, :number2]
1584
1708
 
1585
1709
  # Converts a unitless number to a percentage.
1586
1710
  #
@@ -1588,7 +1712,7 @@ module Sass::Script
1588
1712
  # percentage(0.2) => 20%
1589
1713
  # percentage(100px / 50px) => 200%
1590
1714
  # @overload percentage($number)
1591
- # @param $number [Sass::Script::Value::Number]
1715
+ # @param $number [Sass::Script::Value::Number]
1592
1716
  # @return [Sass::Script::Value::Number]
1593
1717
  # @raise [ArgumentError] if `$number` isn't a unitless number
1594
1718
  def percentage(number)
@@ -1597,7 +1721,7 @@ module Sass::Script
1597
1721
  end
1598
1722
  number(number.value * 100, '%')
1599
1723
  end
1600
- declare :percentage, [:number], :deprecated => [:value]
1724
+ declare :percentage, [:number]
1601
1725
 
1602
1726
  # Rounds a number to the nearest whole number.
1603
1727
  #
@@ -1605,13 +1729,13 @@ module Sass::Script
1605
1729
  # round(10.4px) => 10px
1606
1730
  # round(10.6px) => 11px
1607
1731
  # @overload round($number)
1608
- # @param $number [Sass::Script::Value::Number]
1732
+ # @param $number [Sass::Script::Value::Number]
1609
1733
  # @return [Sass::Script::Value::Number]
1610
1734
  # @raise [ArgumentError] if `$number` isn't a number
1611
1735
  def round(number)
1612
- numeric_transformation(number) {|n| n.round}
1736
+ numeric_transformation(number) {|n| Sass::Util.round(n)}
1613
1737
  end
1614
- declare :round, [:number], :deprecated => [:value]
1738
+ declare :round, [:number]
1615
1739
 
1616
1740
  # Rounds a number up to the next whole number.
1617
1741
  #
@@ -1619,13 +1743,13 @@ module Sass::Script
1619
1743
  # ceil(10.4px) => 11px
1620
1744
  # ceil(10.6px) => 11px
1621
1745
  # @overload ceil($number)
1622
- # @param $number [Sass::Script::Value::Number]
1746
+ # @param $number [Sass::Script::Value::Number]
1623
1747
  # @return [Sass::Script::Value::Number]
1624
1748
  # @raise [ArgumentError] if `$number` isn't a number
1625
1749
  def ceil(number)
1626
1750
  numeric_transformation(number) {|n| n.ceil}
1627
1751
  end
1628
- declare :ceil, [:number], :deprecated => [:value]
1752
+ declare :ceil, [:number]
1629
1753
 
1630
1754
  # Rounds a number down to the previous whole number.
1631
1755
  #
@@ -1633,13 +1757,13 @@ module Sass::Script
1633
1757
  # floor(10.4px) => 10px
1634
1758
  # floor(10.6px) => 10px
1635
1759
  # @overload floor($number)
1636
- # @param $number [Sass::Script::Value::Number]
1760
+ # @param $number [Sass::Script::Value::Number]
1637
1761
  # @return [Sass::Script::Value::Number]
1638
1762
  # @raise [ArgumentError] if `$number` isn't a number
1639
1763
  def floor(number)
1640
1764
  numeric_transformation(number) {|n| n.floor}
1641
1765
  end
1642
- declare :floor, [:number], :deprecated => [:value]
1766
+ declare :floor, [:number]
1643
1767
 
1644
1768
  # Returns the absolute value of a number.
1645
1769
  #
@@ -1647,13 +1771,13 @@ module Sass::Script
1647
1771
  # abs(10px) => 10px
1648
1772
  # abs(-10px) => 10px
1649
1773
  # @overload abs($number)
1650
- # @param $number [Sass::Script::Value::Number]
1774
+ # @param $number [Sass::Script::Value::Number]
1651
1775
  # @return [Sass::Script::Value::Number]
1652
1776
  # @raise [ArgumentError] if `$number` isn't a number
1653
1777
  def abs(number)
1654
1778
  numeric_transformation(number) {|n| n.abs}
1655
1779
  end
1656
- declare :abs, [:number], :deprecated => [:value]
1780
+ declare :abs, [:number]
1657
1781
 
1658
1782
  # Finds the minimum of several numbers. This function takes any number of
1659
1783
  # arguments.
@@ -1662,7 +1786,7 @@ module Sass::Script
1662
1786
  # min(1px, 4px) => 1px
1663
1787
  # min(5em, 3em, 4em) => 3em
1664
1788
  # @overload min($numbers...)
1665
- # @param $numbers [[Sass::Script::Value::Number]]
1789
+ # @param $numbers [[Sass::Script::Value::Number]]
1666
1790
  # @return [Sass::Script::Value::Number]
1667
1791
  # @raise [ArgumentError] if any argument isn't a number, or if not all of
1668
1792
  # the arguments have comparable units
@@ -1679,7 +1803,7 @@ module Sass::Script
1679
1803
  # max(1px, 4px) => 4px
1680
1804
  # max(5em, 3em, 4em) => 5em
1681
1805
  # @overload max($numbers...)
1682
- # @param $numbers [[Sass::Script::Value::Number]]
1806
+ # @param $numbers [[Sass::Script::Value::Number]]
1683
1807
  # @return [Sass::Script::Value::Number]
1684
1808
  # @raise [ArgumentError] if any argument isn't a number, or if not all of
1685
1809
  # the arguments have comparable units
@@ -1698,7 +1822,7 @@ module Sass::Script
1698
1822
  # length(10px 20px 30px) => 3
1699
1823
  # length((width: 10px, height: 20px)) => 2
1700
1824
  # @overload length($list)
1701
- # @param $list [Sass::Script::Value::Base]
1825
+ # @param $list [Sass::Script::Value::Base]
1702
1826
  # @return [Sass::Script::Value::Number]
1703
1827
  def length(list)
1704
1828
  number(list.to_a.size)
@@ -1717,11 +1841,11 @@ module Sass::Script
1717
1841
  # @example
1718
1842
  # set-nth($list: 10px 20px 30px, $n: 2, $value: -20px) => 10px -20px 30px
1719
1843
  # @overload set-nth($list, $n, $value)
1720
- # @param $list [Sass::Script::Value::Base] The list that will be copied, having the element
1721
- # at index `$n` changed.
1722
- # @param $n [Sass::Script::Value::Number] The index of the item to set.
1723
- # Negative indices count from the end of the list.
1724
- # @param $value [Sass::Script::Value::Base] The new value at index `$n`.
1844
+ # @param $list [Sass::Script::Value::Base] The list that will be copied, having the element
1845
+ # at index `$n` changed.
1846
+ # @param $n [Sass::Script::Value::Number] The index of the item to set.
1847
+ # Negative indices count from the end of the list.
1848
+ # @param $value [Sass::Script::Value::Base] The new value at index `$n`.
1725
1849
  # @return [Sass::Script::Value::List]
1726
1850
  # @raise [ArgumentError] if `$n` isn't an integer between 1 and the length
1727
1851
  # of `$list`
@@ -1750,9 +1874,9 @@ module Sass::Script
1750
1874
  # nth((Helvetica, Arial, sans-serif), 3) => sans-serif
1751
1875
  # nth((width: 10px, length: 20px), 2) => length, 20px
1752
1876
  # @overload nth($list, $n)
1753
- # @param $list [Sass::Script::Value::Base]
1754
- # @param $n [Sass::Script::Value::Number] The index of the item to get.
1755
- # Negative indices count from the end of the list.
1877
+ # @param $list [Sass::Script::Value::Base]
1878
+ # @param $n [Sass::Script::Value::Number] The index of the item to get.
1879
+ # Negative indices count from the end of the list.
1756
1880
  # @return [Sass::Script::Value::Base]
1757
1881
  # @raise [ArgumentError] if `$n` isn't an integer between 1 and the length
1758
1882
  # of `$list`
@@ -1772,6 +1896,9 @@ module Sass::Script
1772
1896
  # list. If both lists have fewer than two items, spaces are used for the
1773
1897
  # resulting list.
1774
1898
  #
1899
+ # Like all list functions, `join()` returns a new list rather than modifying
1900
+ # its arguments in place.
1901
+ #
1775
1902
  # @example
1776
1903
  # join(10px 20px, 30px 40px) => 10px 20px 30px 40px
1777
1904
  # join((blue, red), (#abc, #def)) => blue, red, #abc, #def
@@ -1779,15 +1906,15 @@ module Sass::Script
1779
1906
  # join(10px, 20px, comma) => 10px, 20px
1780
1907
  # join((blue, red), (#abc, #def), space) => blue red #abc #def
1781
1908
  # @overload join($list1, $list2, $separator: auto)
1782
- # @param $list1 [Sass::Script::Value::Base]
1783
- # @param $list2 [Sass::Script::Value::Base]
1784
- # @param $separator [Sass::Script::Value::String] The list separator to use.
1785
- # If this is `comma` or `space`, that separator will be used. If this is
1786
- # `auto` (the default), the separator is determined as explained above.
1909
+ # @param $list1 [Sass::Script::Value::Base]
1910
+ # @param $list2 [Sass::Script::Value::Base]
1911
+ # @param $separator [Sass::Script::Value::String] The list separator to use.
1912
+ # If this is `comma` or `space`, that separator will be used. If this is
1913
+ # `auto` (the default), the separator is determined as explained above.
1787
1914
  # @return [Sass::Script::Value::List]
1788
1915
  def join(list1, list2, separator = identifier("auto"))
1789
1916
  assert_type separator, :String, :separator
1790
- unless %w[auto space comma].include?(separator.value)
1917
+ unless %w(auto space comma).include?(separator.value)
1791
1918
  raise ArgumentError.new("Separator name must be space, comma, or auto")
1792
1919
  end
1793
1920
  sep = if separator.value == 'auto'
@@ -1805,6 +1932,9 @@ module Sass::Script
1805
1932
  # Unless the `$separator` argument is passed, if the list had only one item,
1806
1933
  # the resulting list will be space-separated.
1807
1934
  #
1935
+ # Like all list functions, `append()` returns a new list rather than
1936
+ # modifying its argument in place.
1937
+ #
1808
1938
  # @example
1809
1939
  # append(10px 20px, 30px) => 10px 20px 30px
1810
1940
  # append((blue, red), green) => blue, red, green
@@ -1812,15 +1942,15 @@ module Sass::Script
1812
1942
  # append(10px, 20px, comma) => 10px, 20px
1813
1943
  # append((blue, red), green, space) => blue red green
1814
1944
  # @overload append($list, $val, $separator: auto)
1815
- # @param $list [Sass::Script::Value::Base]
1816
- # @param $val [Sass::Script::Value::Base]
1817
- # @param $separator [Sass::Script::Value::String] The list separator to use.
1818
- # If this is `comma` or `space`, that separator will be used. If this is
1819
- # `auto` (the default), the separator is determined as explained above.
1945
+ # @param $list [Sass::Script::Value::Base]
1946
+ # @param $val [Sass::Script::Value::Base]
1947
+ # @param $separator [Sass::Script::Value::String] The list separator to use.
1948
+ # If this is `comma` or `space`, that separator will be used. If this is
1949
+ # `auto` (the default), the separator is determined as explained above.
1820
1950
  # @return [Sass::Script::Value::List]
1821
1951
  def append(list, val, separator = identifier("auto"))
1822
1952
  assert_type separator, :String, :separator
1823
- unless %w[auto space comma].include?(separator.value)
1953
+ unless %w(auto space comma).include?(separator.value)
1824
1954
  raise ArgumentError.new("Separator name must be space, comma, or auto")
1825
1955
  end
1826
1956
  sep = if separator.value == 'auto'
@@ -1844,7 +1974,7 @@ module Sass::Script
1844
1974
  # zip(1px 1px 3px, solid dashed solid, red green blue)
1845
1975
  # => 1px solid red, 1px dashed green, 3px solid blue
1846
1976
  # @overload zip($lists...)
1847
- # @param $lists [[Sass::Script::Value::Base]]
1977
+ # @param $lists [[Sass::Script::Value::Base]]
1848
1978
  # @return [Sass::Script::Value::List]
1849
1979
  def zip(*lists)
1850
1980
  length = nil
@@ -1873,16 +2003,15 @@ module Sass::Script
1873
2003
  # @example
1874
2004
  # index(1px solid red, solid) => 2
1875
2005
  # index(1px solid red, dashed) => null
1876
- # index((width: 10px, height: 20px), (height, 20px)) => 2
2006
+ # index((width: 10px, height: 20px), (height 20px)) => 2
1877
2007
  # @overload index($list, $value)
1878
- # @param $list [Sass::Script::Value::Base]
1879
- # @param $value [Sass::Script::Value::Base]
2008
+ # @param $list [Sass::Script::Value::Base]
2009
+ # @param $value [Sass::Script::Value::Base]
1880
2010
  # @return [Sass::Script::Value::Number, Sass::Script::Value::Null] The
1881
2011
  # 1-based index of `$value` in `$list`, or `null`
1882
2012
  def index(list, value)
1883
2013
  index = list.to_a.index {|e| e.eq(value).to_bool}
1884
- return number(index + 1) if index
1885
- Sass::Script::Value::DeprecatedFalse.new(environment)
2014
+ index ? number(index + 1) : null
1886
2015
  end
1887
2016
  declare :index, [:list, :value]
1888
2017
 
@@ -1894,7 +2023,7 @@ module Sass::Script
1894
2023
  # list-separator(1px, 2px, 3px) => comma
1895
2024
  # list-separator('foo') => space
1896
2025
  # @overload list_separator($list)
1897
- # @param $list [Sass::Script::Value::Base]
2026
+ # @param $list [Sass::Script::Value::Base]
1898
2027
  # @return [Sass::Script::Value::String] `comma` or `space`
1899
2028
  def list_separator(list)
1900
2029
  identifier((list.separator || :space).to_s)
@@ -1909,14 +2038,14 @@ module Sass::Script
1909
2038
  # map-get(("foo": 1, "bar": 2), "bar") => 2
1910
2039
  # map-get(("foo": 1, "bar": 2), "baz") => null
1911
2040
  # @overload map_get($map, $key)
1912
- # @param $map [Sass::Script::Value::Map]
1913
- # @param $key [Sass::Script::Value::Base]
2041
+ # @param $map [Sass::Script::Value::Map]
2042
+ # @param $key [Sass::Script::Value::Base]
1914
2043
  # @return [Sass::Script::Value::Base] The value indexed by `$key`, or `null`
1915
2044
  # if the map doesn't contain the given key
1916
2045
  # @raise [ArgumentError] if `$map` is not a map
1917
2046
  def map_get(map, key)
1918
2047
  assert_type map, :Map, :map
1919
- to_h(map)[key] || null
2048
+ map.to_h[key] || null
1920
2049
  end
1921
2050
  declare :map_get, [:map, :key]
1922
2051
 
@@ -1929,50 +2058,57 @@ module Sass::Script
1929
2058
  # same order as in `$map1`. New keys from `$map2` will be placed at the end
1930
2059
  # of the map.
1931
2060
  #
2061
+ # Like all map functions, `map-merge()` returns a new map rather than
2062
+ # modifying its arguments in place.
2063
+ #
1932
2064
  # @example
1933
2065
  # map-merge(("foo": 1), ("bar": 2)) => ("foo": 1, "bar": 2)
1934
2066
  # map-merge(("foo": 1, "bar": 2), ("bar": 3)) => ("foo": 1, "bar": 3)
1935
2067
  # @overload map_merge($map1, $map2)
1936
- # @param $map1 [Sass::Script::Value::Map]
1937
- # @param $map2 [Sass::Script::Value::Map]
2068
+ # @param $map1 [Sass::Script::Value::Map]
2069
+ # @param $map2 [Sass::Script::Value::Map]
1938
2070
  # @return [Sass::Script::Value::Map]
1939
2071
  # @raise [ArgumentError] if either parameter is not a map
1940
2072
  def map_merge(map1, map2)
1941
2073
  assert_type map1, :Map, :map1
1942
2074
  assert_type map2, :Map, :map2
1943
- map(to_h(map1).merge(to_h(map2)))
2075
+ map(map1.to_h.merge(map2.to_h))
1944
2076
  end
1945
2077
  declare :map_merge, [:map1, :map2]
1946
2078
 
1947
- # Returns a new map with a key removed.
2079
+ # Returns a new map with keys removed.
2080
+ #
2081
+ # Like all map functions, `map-merge()` returns a new map rather than
2082
+ # modifying its arguments in place.
1948
2083
  #
1949
2084
  # @example
1950
2085
  # map-remove(("foo": 1, "bar": 2), "bar") => ("foo": 1)
2086
+ # map-remove(("foo": 1, "bar": 2, "baz": 3), "bar", "baz") => ("foo": 1)
1951
2087
  # map-remove(("foo": 1, "bar": 2), "baz") => ("foo": 1, "bar": 2)
1952
- # @overload map_remove($map, $key)
1953
- # @param $map [Sass::Script::Value::Map]
1954
- # @param $key [Sass::Script::Value::Base]
2088
+ # @overload map_remove($map, $keys...)
2089
+ # @param $map [Sass::Script::Value::Map]
2090
+ # @param $keys [[Sass::Script::Value::Base]]
1955
2091
  # @return [Sass::Script::Value::Map]
1956
2092
  # @raise [ArgumentError] if `$map` is not a map
1957
- def map_remove(map, key)
2093
+ def map_remove(map, *keys)
1958
2094
  assert_type map, :Map, :map
1959
- hash = to_h(map).dup
1960
- hash.delete key
2095
+ hash = map.to_h.dup
2096
+ hash.delete_if {|key, _| keys.include?(key)}
1961
2097
  map(hash)
1962
2098
  end
1963
- declare :map_remove, [:map, :key]
2099
+ declare :map_remove, [:map, :key], :var_args => true
1964
2100
 
1965
2101
  # Returns a list of all keys in a map.
1966
2102
  #
1967
2103
  # @example
1968
2104
  # map-keys(("foo": 1, "bar": 2)) => "foo", "bar"
1969
2105
  # @overload map_keys($map)
1970
- # @param $map [Map]
2106
+ # @param $map [Map]
1971
2107
  # @return [List] the list of keys, comma-separated
1972
2108
  # @raise [ArgumentError] if `$map` is not a map
1973
2109
  def map_keys(map)
1974
2110
  assert_type map, :Map, :map
1975
- list(to_h(map).keys, :comma)
2111
+ list(map.to_h.keys, :comma)
1976
2112
  end
1977
2113
  declare :map_keys, [:map]
1978
2114
 
@@ -1983,12 +2119,12 @@ module Sass::Script
1983
2119
  # map-values(("foo": 1, "bar": 2)) => 1, 2
1984
2120
  # map-values(("foo": 1, "bar": 2, "baz": 1)) => 1, 2, 1
1985
2121
  # @overload map_values($map)
1986
- # @param $map [Map]
2122
+ # @param $map [Map]
1987
2123
  # @return [List] the list of values, comma-separated
1988
2124
  # @raise [ArgumentError] if `$map` is not a map
1989
2125
  def map_values(map)
1990
2126
  assert_type map, :Map, :map
1991
- list(to_h(map).values, :comma)
2127
+ list(map.to_h.values, :comma)
1992
2128
  end
1993
2129
  declare :map_values, [:map]
1994
2130
 
@@ -1998,13 +2134,13 @@ module Sass::Script
1998
2134
  # map-has-key(("foo": 1, "bar": 2), "foo") => true
1999
2135
  # map-has-key(("foo": 1, "bar": 2), "baz") => false
2000
2136
  # @overload map_has_key($map, $key)
2001
- # @param $map [Sass::Script::Value::Map]
2002
- # @param $key [Sass::Script::Value::Base]
2137
+ # @param $map [Sass::Script::Value::Map]
2138
+ # @param $key [Sass::Script::Value::Base]
2003
2139
  # @return [Sass::Script::Value::Bool]
2004
2140
  # @raise [ArgumentError] if `$map` is not a map
2005
2141
  def map_has_key(map, key)
2006
2142
  assert_type map, :Map, :map
2007
- bool(to_h(map).has_key?(key))
2143
+ bool(map.to_h.has_key?(key))
2008
2144
  end
2009
2145
  declare :map_has_key, [:map, :key]
2010
2146
 
@@ -2019,12 +2155,12 @@ module Sass::Script
2019
2155
  #
2020
2156
  # @include foo($arg1: val, $arg2: val);
2021
2157
  # @overload keywords($args)
2022
- # @param $args [Sass::Script::Value::ArgList]
2158
+ # @param $args [Sass::Script::Value::ArgList]
2023
2159
  # @return [Sass::Script::Value::Map]
2024
2160
  # @raise [ArgumentError] if `$args` isn't a variable argument list
2025
2161
  def keywords(args)
2026
2162
  assert_type args, :ArgList, :args
2027
- map(Sass::Util.map_keys(args.keywords.as_stored) {|k| Sass::Script::String.new(k)})
2163
+ map(Sass::Util.map_keys(args.keywords.as_stored) {|k| Sass::Script::Value::String.new(k)})
2028
2164
  end
2029
2165
  declare :keywords, [:args]
2030
2166
 
@@ -2036,10 +2172,10 @@ module Sass::Script
2036
2172
  # if(true, 1px, 2px) => 1px
2037
2173
  # if(false, 1px, 2px) => 2px
2038
2174
  # @overload if($condition, $if-true, $if-false)
2039
- # @param $condition [Sass::Script::Value::Base] Whether the `$if-true` or
2040
- # `$if-false` will be returned
2041
- # @param $if-true [Sass::Script::Tree::Node]
2042
- # @param $if-false [Sass::Script::Tree::Node]
2175
+ # @param $condition [Sass::Script::Value::Base] Whether the `$if-true` or
2176
+ # `$if-false` will be returned
2177
+ # @param $if-true [Sass::Script::Tree::Node]
2178
+ # @param $if-false [Sass::Script::Tree::Node]
2043
2179
  # @return [Sass::Script::Value::Base] `$if-true` or `$if-false`
2044
2180
  def if(condition, if_true, if_false)
2045
2181
  if condition.to_bool
@@ -2076,10 +2212,10 @@ module Sass::Script
2076
2212
  # call(scale-color, #0a64ff, $lightness: -10%) => #0058ef
2077
2213
  #
2078
2214
  # $fn: nth;
2079
- # call($fn, 2, (a b c)) => b
2215
+ # call($fn, (a b c), 2) => b
2080
2216
  #
2081
2217
  # @overload call($name, $args...)
2082
- # @param $name [String] The name of the function to call.
2218
+ # @param $name [String] The name of the function to call.
2083
2219
  def call(name, *args)
2084
2220
  assert_type name, :String, :name
2085
2221
  kwargs = args.last.is_a?(Hash) ? args.pop : {}
@@ -2094,31 +2230,29 @@ module Sass::Script
2094
2230
  end
2095
2231
  declare :call, [:name], :var_args => true, :var_kwargs => true
2096
2232
 
2097
- # This function only exists as a workaround for IE7's [`content: counter`
2098
- # bug][bug]. It works identically to any other plain-CSS function, except it
2233
+ # This function only exists as a workaround for IE7's [`content:
2234
+ # counter` bug](http://jes.st/2013/ie7s-css-breaking-content-counter-bug/).
2235
+ # It works identically to any other plain-CSS function, except it
2099
2236
  # avoids adding spaces between the argument commas.
2100
2237
  #
2101
- # [bug]: http://jes.st/2013/ie7s-css-breaking-content-counter-bug/
2102
- #
2103
2238
  # @example
2104
2239
  # counter(item, ".") => counter(item,".")
2105
2240
  # @overload counter($args...)
2106
- # @return [String]
2241
+ # @return [Sass::Script::Value::String]
2107
2242
  def counter(*args)
2108
2243
  identifier("counter(#{args.map {|a| a.to_s(options)}.join(',')})")
2109
2244
  end
2110
2245
  declare :counter, [], :var_args => true
2111
2246
 
2112
- # This function only exists as a workaround for IE7's [`content: counters`
2113
- # bug][bug]. It works identically to any other plain-CSS function, except it
2247
+ # This function only exists as a workaround for IE7's [`content:
2248
+ # counter` bug](http://jes.st/2013/ie7s-css-breaking-content-counter-bug/).
2249
+ # It works identically to any other plain-CSS function, except it
2114
2250
  # avoids adding spaces between the argument commas.
2115
2251
  #
2116
- # [bug]: http://jes.st/2013/ie7s-css-breaking-content-counter-bug/
2117
- #
2118
2252
  # @example
2119
2253
  # counters(item, ".") => counters(item,".")
2120
2254
  # @overload counters($args...)
2121
- # @return [String]
2255
+ # @return [Sass::Script::Value::String]
2122
2256
  def counters(*args)
2123
2257
  identifier("counters(#{args.map {|a| a.to_s(options)}.join(',')})")
2124
2258
  end
@@ -2130,11 +2264,14 @@ module Sass::Script
2130
2264
  # @example
2131
2265
  # $a-false-value: false;
2132
2266
  # variable-exists(a-false-value) => true
2267
+ # variable-exists(a-null-value) => true
2133
2268
  #
2134
2269
  # variable-exists(nonexistent) => false
2135
- # @param name [Sass::Script::String] The name of the variable to
2136
- # check. The name should not include the `$`.
2137
- # @return [Sass::Script::Bool] Whether the variable is defined in
2270
+ #
2271
+ # @overload variable_exists($name)
2272
+ # @param $name [Sass::Script::Value::String] The name of the variable to
2273
+ # check. The name should not include the `$`.
2274
+ # @return [Sass::Script::Value::Bool] Whether the variable is defined in
2138
2275
  # the current scope.
2139
2276
  def variable_exists(name)
2140
2277
  assert_type name, :String, :name
@@ -2148,14 +2285,17 @@ module Sass::Script
2148
2285
  # @example
2149
2286
  # $a-false-value: false;
2150
2287
  # global-variable-exists(a-false-value) => true
2288
+ # global-variable-exists(a-null-value) => true
2151
2289
  #
2152
2290
  # .foo {
2153
2291
  # $some-var: false;
2154
2292
  # @if global-variable-exists(some-var) { /* false, doesn't run */ }
2155
2293
  # }
2156
- # @param name [Sass::Script::String] The name of the variable to
2157
- # check. The name should not include the `$`.
2158
- # @return [Sass::Script::Bool] Whether the variable is defined in
2294
+ #
2295
+ # @overload global_variable_exists($name)
2296
+ # @param $name [Sass::Script::Value::String] The name of the variable to
2297
+ # check. The name should not include the `$`.
2298
+ # @return [Sass::Script::Value::Bool] Whether the variable is defined in
2159
2299
  # the global scope.
2160
2300
  def global_variable_exists(name)
2161
2301
  assert_type name, :String, :name
@@ -2170,9 +2310,11 @@ module Sass::Script
2170
2310
  #
2171
2311
  # @function myfunc { @return "something"; }
2172
2312
  # function-exists(myfunc) => true
2173
- # @param name [Sass::Script::String] The name of the function to
2174
- # check.
2175
- # @return [Sass::Script::Bool] Whether the function is defined.
2313
+ #
2314
+ # @overload function_exists($name)
2315
+ # @param name [Sass::Script::Value::String] The name of the function to
2316
+ # check.
2317
+ # @return [Sass::Script::Value::Bool] Whether the function is defined.
2176
2318
  def function_exists(name)
2177
2319
  assert_type name, :String, :name
2178
2320
  exists = Sass::Script::Functions.callable?(name.value.tr("-", "_"))
@@ -2188,9 +2330,11 @@ module Sass::Script
2188
2330
  #
2189
2331
  # @mixin red-text { color: red; }
2190
2332
  # mixin-exists(red-text) => true
2191
- # @param name [Sass::Script::String] The name of the mixin to
2192
- # check.
2193
- # @return [Sass::Script::Bool] Whether the mixin is defined.
2333
+ #
2334
+ # @overload mixin_exists($name)
2335
+ # @param name [Sass::Script::Value::String] The name of the mixin to
2336
+ # check.
2337
+ # @return [Sass::Script::Value::Bool] Whether the mixin is defined.
2194
2338
  def mixin_exists(name)
2195
2339
  assert_type name, :String, :name
2196
2340
  bool(environment.mixin(name.value))
@@ -2199,31 +2343,33 @@ module Sass::Script
2199
2343
 
2200
2344
  # Return a string containing the value as its Sass representation.
2201
2345
  #
2202
- # @param value [Sass::Script::Value::Base] The value to inspect.
2203
- # @return [Sass::Script::Value::String] A respresentation of the value as
2346
+ # @overload inspect($value)
2347
+ # @param $value [Sass::Script::Value::Base] The value to inspect.
2348
+ # @return [Sass::Script::Value::String] A representation of the value as
2204
2349
  # it would be written in Sass.
2205
2350
  def inspect(value)
2351
+ value.check_deprecated_interp if value.is_a?(Sass::Script::Value::String)
2206
2352
  unquoted_string(value.to_sass)
2207
2353
  end
2208
2354
  declare :inspect, [:value]
2209
2355
 
2210
2356
  # @overload random()
2211
2357
  # Return a decimal between 0 and 1, inclusive of 0 but not 1.
2212
- # @return [Sass::Script::Number] A decimal value.
2358
+ # @return [Sass::Script::Value::Number] A decimal value.
2213
2359
  # @overload random($limit)
2214
- # Return an integer between 1 and `$limit`, inclusive of 1 but not `$limit`.
2360
+ # Return an integer between 1 and `$limit`, inclusive of both 1 and `$limit`.
2215
2361
  # @param $limit [Sass::Script::Value::Number] The maximum of the random integer to be
2216
2362
  # returned, a positive integer.
2217
- # @return [Sass::Script::Number] An integer.
2363
+ # @return [Sass::Script::Value::Number] An integer.
2218
2364
  # @raise [ArgumentError] if the `$limit` is not 1 or greater
2219
2365
  def random(limit = nil)
2220
2366
  generator = Sass::Script::Functions.random_number_generator
2221
2367
  if limit
2222
2368
  assert_integer limit, "limit"
2223
- if limit.value < 1
2369
+ if limit.to_i < 1
2224
2370
  raise ArgumentError.new("$limit #{limit} must be greater than or equal to 1")
2225
2371
  end
2226
- number(1 + generator.rand(limit.value))
2372
+ number(1 + generator.rand(limit.to_i))
2227
2373
  else
2228
2374
  number(generator.rand)
2229
2375
  end
@@ -2231,6 +2377,281 @@ module Sass::Script
2231
2377
  declare :random, []
2232
2378
  declare :random, [:limit]
2233
2379
 
2380
+ # Parses a user-provided selector into a list of lists of strings
2381
+ # as returned by `&`.
2382
+ #
2383
+ # @example
2384
+ # selector-parse(".foo .bar, .baz .bang") => ('.foo' '.bar', '.baz' '.bang')
2385
+ #
2386
+ # @overload selector_parse($selector)
2387
+ # @param $selector [Sass::Script::Value::String, Sass::Script::Value::List]
2388
+ # The selector to parse. This can be either a string, a list of
2389
+ # strings, or a list of lists of strings as returned by `&`.
2390
+ # @return [Sass::Script::Value::List]
2391
+ # A list of lists of strings representing `$selector`. This is
2392
+ # in the same format as a selector returned by `&`.
2393
+ def selector_parse(selector)
2394
+ parse_selector(selector, :selector).to_sass_script
2395
+ end
2396
+ declare :selector_parse, [:selector]
2397
+
2398
+ # Return a new selector with all selectors in `$selectors` nested beneath
2399
+ # one another as though they had been nested in the stylesheet as
2400
+ # `$selector1 { $selector2 { ... } }`.
2401
+ #
2402
+ # Unlike most selector functions, `selector-nest` allows the
2403
+ # parent selector `&` to be used in any selector but the first.
2404
+ #
2405
+ # @example
2406
+ # selector-nest(".foo", ".bar", ".baz") => .foo .bar .baz
2407
+ # selector-nest(".a .foo", ".b .bar") => .a .foo .b .bar
2408
+ # selector-nest(".foo", "&.bar") => .foo.bar
2409
+ #
2410
+ # @overload selector_nest($selectors...)
2411
+ # @param $selectors [[Sass::Script::Value::String, Sass::Script::Value::List]]
2412
+ # The selectors to nest. At least one selector must be passed. Each of
2413
+ # these can be either a string, a list of strings, or a list of lists of
2414
+ # strings as returned by `&`.
2415
+ # @return [Sass::Script::Value::List]
2416
+ # A list of lists of strings representing the result of nesting
2417
+ # `$selectors`. This is in the same format as a selector returned by
2418
+ # `&`.
2419
+ def selector_nest(*selectors)
2420
+ if selectors.empty?
2421
+ raise ArgumentError.new("$selectors: At least one selector must be passed")
2422
+ end
2423
+
2424
+ parsed = [parse_selector(selectors.first, :selectors)]
2425
+ parsed += selectors[1..-1].map {|sel| parse_selector(sel, :selectors, true)}
2426
+ parsed.inject {|result, child| child.resolve_parent_refs(result)}.to_sass_script
2427
+ end
2428
+ declare :selector_nest, [], :var_args => true
2429
+
2430
+ # Return a new selector with all selectors in `$selectors` appended one
2431
+ # another as though they had been nested in the stylesheet as `$selector1 {
2432
+ # &$selector2 { ... } }`.
2433
+ #
2434
+ # @example
2435
+ # selector-append(".foo", ".bar", ".baz") => .foo.bar.baz
2436
+ # selector-append(".a .foo", ".b .bar") => "a .foo.b .bar"
2437
+ # selector-append(".foo", "-suffix") => ".foo-suffix"
2438
+ #
2439
+ # @overload selector_append($selectors...)
2440
+ # @param $selectors [[Sass::Script::Value::String, Sass::Script::Value::List]]
2441
+ # The selectors to append. At least one selector must be passed. Each of
2442
+ # these can be either a string, a list of strings, or a list of lists of
2443
+ # strings as returned by `&`.
2444
+ # @return [Sass::Script::Value::List]
2445
+ # A list of lists of strings representing the result of appending
2446
+ # `$selectors`. This is in the same format as a selector returned by
2447
+ # `&`.
2448
+ # @raise [ArgumentError] if a selector could not be appended.
2449
+ def selector_append(*selectors)
2450
+ if selectors.empty?
2451
+ raise ArgumentError.new("$selectors: At least one selector must be passed")
2452
+ end
2453
+
2454
+ selectors.map {|sel| parse_selector(sel, :selectors)}.inject do |parent, child|
2455
+ child.members.each do |seq|
2456
+ sseq = seq.members.first
2457
+ unless sseq.is_a?(Sass::Selector::SimpleSequence)
2458
+ raise ArgumentError.new("Can't append \"#{seq}\" to \"#{parent}\"")
2459
+ end
2460
+
2461
+ base = sseq.base
2462
+ case base
2463
+ when Sass::Selector::Universal
2464
+ raise ArgumentError.new("Can't append \"#{seq}\" to \"#{parent}\"")
2465
+ when Sass::Selector::Element
2466
+ unless base.namespace.nil?
2467
+ raise ArgumentError.new("Can't append \"#{seq}\" to \"#{parent}\"")
2468
+ end
2469
+ sseq.members[0] = Sass::Selector::Parent.new(base.name)
2470
+ else
2471
+ sseq.members.unshift Sass::Selector::Parent.new
2472
+ end
2473
+ end
2474
+ child.resolve_parent_refs(parent)
2475
+ end.to_sass_script
2476
+ end
2477
+ declare :selector_append, [], :var_args => true
2478
+
2479
+ # Returns a new version of `$selector` with `$extendee` extended
2480
+ # with `$extender`. This works just like the result of
2481
+ #
2482
+ # $selector { ... }
2483
+ # $extender { @extend $extendee }
2484
+ #
2485
+ # @example
2486
+ # selector-extend(".a .b", ".b", ".foo .bar") => .a .b, .a .foo .bar, .foo .a .bar
2487
+ #
2488
+ # @overload selector_extend($selector, $extendee, $extender)
2489
+ # @param $selector [Sass::Script::Value::String, Sass::Script::Value::List]
2490
+ # The selector within which `$extendee` is extended with
2491
+ # `$extender`. This can be either a string, a list of strings,
2492
+ # or a list of lists of strings as returned by `&`.
2493
+ # @param $extendee [Sass::Script::Value::String, Sass::Script::Value::List]
2494
+ # The selector being extended. This can be either a string, a
2495
+ # list of strings, or a list of lists of strings as returned
2496
+ # by `&`.
2497
+ # @param $extender [Sass::Script::Value::String, Sass::Script::Value::List]
2498
+ # The selector being injected into `$selector`. This can be
2499
+ # either a string, a list of strings, or a list of lists of
2500
+ # strings as returned by `&`.
2501
+ # @return [Sass::Script::Value::List]
2502
+ # A list of lists of strings representing the result of the
2503
+ # extension. This is in the same format as a selector returned
2504
+ # by `&`.
2505
+ # @raise [ArgumentError] if the extension fails
2506
+ def selector_extend(selector, extendee, extender)
2507
+ selector = parse_selector(selector, :selector)
2508
+ extendee = parse_selector(extendee, :extendee)
2509
+ extender = parse_selector(extender, :extender)
2510
+
2511
+ extends = Sass::Util::SubsetMap.new
2512
+ begin
2513
+ extender.populate_extends(extends, extendee, nil, [], true)
2514
+ selector.do_extend(extends).to_sass_script
2515
+ rescue Sass::SyntaxError => e
2516
+ raise ArgumentError.new(e.to_s)
2517
+ end
2518
+ end
2519
+ declare :selector_extend, [:selector, :extendee, :extender]
2520
+
2521
+ # Replaces all instances of `$original` with `$replacement` in `$selector`
2522
+ #
2523
+ # This works by using `@extend` and throwing away the original
2524
+ # selector. This means that it can be used to do very advanced
2525
+ # replacements; see the examples below.
2526
+ #
2527
+ # @example
2528
+ # selector-replace(".foo .bar", ".bar", ".baz") => ".foo .baz"
2529
+ # selector-replace(".foo.bar.baz", ".foo.baz", ".qux") => ".bar.qux"
2530
+ #
2531
+ # @overload selector_replace($selector, $original, $replacement)
2532
+ # @param $selector [Sass::Script::Value::String, Sass::Script::Value::List]
2533
+ # The selector within which `$original` is replaced with
2534
+ # `$replacement`. This can be either a string, a list of
2535
+ # strings, or a list of lists of strings as returned by `&`.
2536
+ # @param $original [Sass::Script::Value::String, Sass::Script::Value::List]
2537
+ # The selector being replaced. This can be either a string, a
2538
+ # list of strings, or a list of lists of strings as returned
2539
+ # by `&`.
2540
+ # @param $replacement [Sass::Script::Value::String, Sass::Script::Value::List]
2541
+ # The selector that `$original` is being replaced with. This
2542
+ # can be either a string, a list of strings, or a list of
2543
+ # lists of strings as returned by `&`.
2544
+ # @return [Sass::Script::Value::List]
2545
+ # A list of lists of strings representing the result of the
2546
+ # extension. This is in the same format as a selector returned
2547
+ # by `&`.
2548
+ # @raise [ArgumentError] if the replacement fails
2549
+ def selector_replace(selector, original, replacement)
2550
+ selector = parse_selector(selector, :selector)
2551
+ original = parse_selector(original, :original)
2552
+ replacement = parse_selector(replacement, :replacement)
2553
+
2554
+ extends = Sass::Util::SubsetMap.new
2555
+ begin
2556
+ replacement.populate_extends(extends, original, nil, [], true)
2557
+ selector.do_extend(extends, [], true).to_sass_script
2558
+ rescue Sass::SyntaxError => e
2559
+ raise ArgumentError.new(e.to_s)
2560
+ end
2561
+ end
2562
+ declare :selector_replace, [:selector, :original, :replacement]
2563
+
2564
+ # Unifies two selectors into a single selector that matches only
2565
+ # elements matched by both input selectors. Returns `null` if
2566
+ # there is no such selector.
2567
+ #
2568
+ # Like the selector unification done for `@extend`, this doesn't
2569
+ # guarantee that the output selector will match *all* elements
2570
+ # matched by both input selectors. For example, if `.a .b` is
2571
+ # unified with `.x .y`, `.a .x .b.y, .x .a .b.y` will be returned,
2572
+ # but `.a.x .b.y` will not. This avoids exponential output size
2573
+ # while matching all elements that are likely to exist in
2574
+ # practice.
2575
+ #
2576
+ # @example
2577
+ # selector-unify(".a", ".b") => .a.b
2578
+ # selector-unify(".a .b", ".x .y") => .a .x .b.y, .x .a .b.y
2579
+ # selector-unify(".a.b", ".b.c") => .a.b.c
2580
+ # selector-unify("#a", "#b") => null
2581
+ #
2582
+ # @overload selector_unify($selector1, $selector2)
2583
+ # @param $selector1 [Sass::Script::Value::String, Sass::Script::Value::List]
2584
+ # The first selector to be unified. This can be either a
2585
+ # string, a list of strings, or a list of lists of strings as
2586
+ # returned by `&`.
2587
+ # @param $selector2 [Sass::Script::Value::String, Sass::Script::Value::List]
2588
+ # The second selector to be unified. This can be either a
2589
+ # string, a list of strings, or a list of lists of strings as
2590
+ # returned by `&`.
2591
+ # @return [Sass::Script::Value::List, Sass::Script::Value::Null]
2592
+ # A list of lists of strings representing the result of the
2593
+ # unification, or null if no unification exists. This is in
2594
+ # the same format as a selector returned by `&`.
2595
+ def selector_unify(selector1, selector2)
2596
+ selector1 = parse_selector(selector1, :selector1)
2597
+ selector2 = parse_selector(selector2, :selector2)
2598
+ return null unless (unified = selector1.unify(selector2))
2599
+ unified.to_sass_script
2600
+ end
2601
+ declare :selector_unify, [:selector1, :selector2]
2602
+
2603
+ # Returns the [simple
2604
+ # selectors](http://dev.w3.org/csswg/selectors4/#simple) that
2605
+ # comprise the compound selector `$selector`.
2606
+ #
2607
+ # Note that `$selector` **must be** a [compound
2608
+ # selector](http://dev.w3.org/csswg/selectors4/#compound). That
2609
+ # means it cannot contain commas or spaces. It also means that
2610
+ # unlike other selector functions, this takes only strings, not
2611
+ # lists.
2612
+ #
2613
+ # @example
2614
+ # simple-selectors(".foo.bar") => ".foo", ".bar"
2615
+ # simple-selectors(".foo.bar.baz") => ".foo", ".bar", ".baz"
2616
+ #
2617
+ # @overload simple_selectors($selector)
2618
+ # @param $selector [Sass::Script::Value::String]
2619
+ # The compound selector whose simple selectors will be extracted.
2620
+ # @return [Sass::Script::Value::List]
2621
+ # A list of simple selectors in the compound selector.
2622
+ def simple_selectors(selector)
2623
+ selector = parse_compound_selector(selector, :selector)
2624
+ list(selector.members.map {|simple| unquoted_string(simple.to_s)}, :comma)
2625
+ end
2626
+ declare :simple_selectors, [:selector]
2627
+
2628
+ # Returns whether `$super` is a superselector of `$sub`. This means that
2629
+ # `$super` matches all the elements that `$sub` matches, as well as possibly
2630
+ # additional elements. In general, simpler selectors tend to be
2631
+ # superselectors of more complex oned.
2632
+ #
2633
+ # @example
2634
+ # is-superselector(".foo", ".foo.bar") => true
2635
+ # is-superselector(".foo.bar", ".foo") => false
2636
+ # is-superselector(".bar", ".foo .bar") => true
2637
+ # is-superselector(".foo .bar", ".bar") => false
2638
+ #
2639
+ # @overload is_superselector($super, $sub)
2640
+ # @param $super [Sass::Script::Value::String, Sass::Script::Value::List]
2641
+ # The potential superselector. This can be either a string, a list of
2642
+ # strings, or a list of lists of strings as returned by `&`.
2643
+ # @param $sub [Sass::Script::Value::String, Sass::Script::Value::List]
2644
+ # The potential subselector. This can be either a string, a list of
2645
+ # strings, or a list of lists of strings as returned by `&`.
2646
+ # @return [Sass::Script::Value::Bool]
2647
+ # Whether `$selector1` is a superselector of `$selector2`.
2648
+ def is_superselector(sup, sub)
2649
+ sup = parse_selector(sup, :super)
2650
+ sub = parse_selector(sub, :sub)
2651
+ bool(sup.superselector?(sub))
2652
+ end
2653
+ declare :is_superselector, [:super, :sub]
2654
+
2234
2655
  private
2235
2656
 
2236
2657
  # This method implements the pattern of transforming a numeric value into
@@ -2250,23 +2671,23 @@ module Sass::Script
2250
2671
  assert_type amount, :Number, :amount
2251
2672
  Sass::Util.check_range('Amount', range, amount, units)
2252
2673
 
2253
- # TODO: is it worth restricting here,
2254
- # or should we do so in the Color constructor itself,
2255
- # and allow clipping in rgb() et al?
2256
- color.with(attr => Sass::Util.restrict(
2257
- color.send(attr).send(op, amount.value), range))
2674
+ color.with(attr => color.send(attr).send(op, amount.value))
2258
2675
  end
2259
2676
 
2260
- def to_h(obj)
2261
- return obj.to_h unless obj.is_a?(Sass::Script::Value::List) && obj.needs_map_warning?
2677
+ def check_alpha_unit(alpha, function)
2678
+ return if alpha.unitless?
2262
2679
 
2263
- fn_name = Sass::Util.caller_info.last.gsub('_', '-')
2264
- Sass::Util.sass_warn <<WARNING + environment.stack.to_s.gsub(/^/, ' ')
2265
- DEPRECATION WARNING: Passing lists of pairs to #{fn_name} is deprecated and will
2266
- be removed in future versions of Sass. Use Sass maps instead. For details, see
2267
- http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#maps.
2680
+ if alpha.is_unit?("%")
2681
+ Sass::Util.sass_warn(<<WARNING)
2682
+ DEPRECATION WARNING: Passing a percentage as the alpha value to #{function}() will be
2683
+ interpreted differently in future versions of Sass. For now, use #{alpha.value} instead.
2268
2684
  WARNING
2269
- obj.to_h
2685
+ else
2686
+ Sass::Util.sass_warn(<<WARNING)
2687
+ DEPRECATION WARNING: Passing a number with units as the alpha value to #{function}() is
2688
+ deprecated and will be an error in future versions of Sass. Use #{alpha.value} instead.
2689
+ WARNING
2690
+ end
2270
2691
  end
2271
2692
  end
2272
2693
  end