sass 3.3.0 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +58 -50
  4. data/Rakefile +1 -4
  5. data/VERSION +1 -1
  6. data/VERSION_DATE +1 -1
  7. data/VERSION_NAME +1 -1
  8. data/bin/sass +1 -1
  9. data/bin/scss +1 -1
  10. data/lib/sass/cache_stores/filesystem.rb +6 -2
  11. data/lib/sass/css.rb +1 -3
  12. data/lib/sass/engine.rb +37 -46
  13. data/lib/sass/environment.rb +13 -17
  14. data/lib/sass/error.rb +6 -9
  15. data/lib/sass/exec/base.rb +187 -0
  16. data/lib/sass/exec/sass_convert.rb +264 -0
  17. data/lib/sass/exec/sass_scss.rb +424 -0
  18. data/lib/sass/exec.rb +5 -771
  19. data/lib/sass/features.rb +7 -0
  20. data/lib/sass/importers/base.rb +7 -2
  21. data/lib/sass/importers/filesystem.rb +9 -25
  22. data/lib/sass/importers.rb +0 -1
  23. data/lib/sass/media.rb +1 -4
  24. data/lib/sass/plugin/compiler.rb +200 -83
  25. data/lib/sass/plugin/staleness_checker.rb +1 -1
  26. data/lib/sass/plugin.rb +3 -3
  27. data/lib/sass/script/css_lexer.rb +1 -1
  28. data/lib/sass/script/functions.rb +622 -268
  29. data/lib/sass/script/lexer.rb +99 -34
  30. data/lib/sass/script/parser.rb +24 -23
  31. data/lib/sass/script/tree/funcall.rb +1 -1
  32. data/lib/sass/script/tree/interpolation.rb +20 -2
  33. data/lib/sass/script/tree/selector.rb +26 -0
  34. data/lib/sass/script/tree/string_interpolation.rb +1 -1
  35. data/lib/sass/script/tree.rb +1 -0
  36. data/lib/sass/script/value/base.rb +7 -5
  37. data/lib/sass/script/value/bool.rb +0 -5
  38. data/lib/sass/script/value/color.rb +39 -21
  39. data/lib/sass/script/value/helpers.rb +107 -0
  40. data/lib/sass/script/value/list.rb +0 -15
  41. data/lib/sass/script/value/null.rb +0 -5
  42. data/lib/sass/script/value/number.rb +62 -14
  43. data/lib/sass/script/value/string.rb +59 -11
  44. data/lib/sass/script/value.rb +0 -1
  45. data/lib/sass/scss/css_parser.rb +8 -2
  46. data/lib/sass/scss/parser.rb +190 -328
  47. data/lib/sass/scss/rx.rb +15 -6
  48. data/lib/sass/scss/static_parser.rb +298 -1
  49. data/lib/sass/selector/abstract_sequence.rb +28 -13
  50. data/lib/sass/selector/comma_sequence.rb +92 -13
  51. data/lib/sass/selector/pseudo.rb +256 -0
  52. data/lib/sass/selector/sequence.rb +94 -24
  53. data/lib/sass/selector/simple.rb +14 -25
  54. data/lib/sass/selector/simple_sequence.rb +97 -33
  55. data/lib/sass/selector.rb +57 -194
  56. data/lib/sass/shared.rb +1 -1
  57. data/lib/sass/source/map.rb +26 -12
  58. data/lib/sass/stack.rb +0 -6
  59. data/lib/sass/supports.rb +2 -3
  60. data/lib/sass/tree/at_root_node.rb +1 -0
  61. data/lib/sass/tree/charset_node.rb +1 -1
  62. data/lib/sass/tree/directive_node.rb +8 -2
  63. data/lib/sass/tree/error_node.rb +18 -0
  64. data/lib/sass/tree/extend_node.rb +1 -1
  65. data/lib/sass/tree/function_node.rb +4 -0
  66. data/lib/sass/tree/keyframe_rule_node.rb +15 -0
  67. data/lib/sass/tree/prop_node.rb +1 -1
  68. data/lib/sass/tree/rule_node.rb +12 -7
  69. data/lib/sass/tree/visitors/check_nesting.rb +38 -10
  70. data/lib/sass/tree/visitors/convert.rb +16 -18
  71. data/lib/sass/tree/visitors/cssize.rb +29 -29
  72. data/lib/sass/tree/visitors/deep_copy.rb +5 -0
  73. data/lib/sass/tree/visitors/perform.rb +45 -33
  74. data/lib/sass/tree/visitors/set_options.rb +14 -0
  75. data/lib/sass/tree/visitors/to_css.rb +15 -14
  76. data/lib/sass/util/subset_map.rb +1 -1
  77. data/lib/sass/util.rb +222 -99
  78. data/lib/sass/version.rb +5 -5
  79. data/lib/sass.rb +0 -5
  80. data/test/sass/cache_test.rb +62 -20
  81. data/test/sass/callbacks_test.rb +1 -1
  82. data/test/sass/compiler_test.rb +19 -10
  83. data/test/sass/conversion_test.rb +58 -1
  84. data/test/sass/css2sass_test.rb +23 -4
  85. data/test/sass/encoding_test.rb +219 -0
  86. data/test/sass/engine_test.rb +136 -199
  87. data/test/sass/exec_test.rb +2 -2
  88. data/test/sass/extend_test.rb +236 -19
  89. data/test/sass/functions_test.rb +295 -253
  90. data/test/sass/importer_test.rb +31 -21
  91. data/test/sass/logger_test.rb +1 -1
  92. data/test/sass/more_results/more_import.css +1 -1
  93. data/test/sass/plugin_test.rb +14 -13
  94. data/test/sass/results/compact.css +1 -1
  95. data/test/sass/results/complex.css +4 -4
  96. data/test/sass/results/expanded.css +1 -1
  97. data/test/sass/results/import.css +1 -1
  98. data/test/sass/results/import_charset_ibm866.css +2 -2
  99. data/test/sass/results/mixins.css +17 -17
  100. data/test/sass/results/nested.css +1 -1
  101. data/test/sass/results/parent_ref.css +2 -2
  102. data/test/sass/results/script.css +3 -3
  103. data/test/sass/results/scss_import.css +1 -1
  104. data/test/sass/script_conversion_test.rb +10 -7
  105. data/test/sass/script_test.rb +288 -74
  106. data/test/sass/scss/css_test.rb +141 -24
  107. data/test/sass/scss/rx_test.rb +4 -4
  108. data/test/sass/scss/scss_test.rb +457 -18
  109. data/test/sass/source_map_test.rb +115 -25
  110. data/test/sass/superselector_test.rb +191 -0
  111. data/test/sass/templates/scss_import.scss +2 -1
  112. data/test/sass/test_helper.rb +1 -1
  113. data/test/sass/util/multibyte_string_scanner_test.rb +1 -1
  114. data/test/sass/util/normalized_map_test.rb +1 -1
  115. data/test/sass/util/subset_map_test.rb +2 -2
  116. data/test/sass/util_test.rb +31 -1
  117. data/test/sass/value_helpers_test.rb +5 -7
  118. data/test/test_helper.rb +2 -2
  119. data/vendor/listen/CHANGELOG.md +1 -228
  120. data/vendor/listen/Gemfile +5 -15
  121. data/vendor/listen/README.md +111 -77
  122. data/vendor/listen/Rakefile +0 -42
  123. data/vendor/listen/lib/listen/adapter.rb +195 -82
  124. data/vendor/listen/lib/listen/adapters/bsd.rb +27 -64
  125. data/vendor/listen/lib/listen/adapters/darwin.rb +21 -58
  126. data/vendor/listen/lib/listen/adapters/linux.rb +23 -55
  127. data/vendor/listen/lib/listen/adapters/polling.rb +25 -34
  128. data/vendor/listen/lib/listen/adapters/windows.rb +50 -46
  129. data/vendor/listen/lib/listen/directory_record.rb +96 -61
  130. data/vendor/listen/lib/listen/listener.rb +135 -37
  131. data/vendor/listen/lib/listen/turnstile.rb +9 -5
  132. data/vendor/listen/lib/listen/version.rb +1 -1
  133. data/vendor/listen/lib/listen.rb +33 -19
  134. data/vendor/listen/listen.gemspec +6 -0
  135. data/vendor/listen/spec/listen/adapter_spec.rb +43 -77
  136. data/vendor/listen/spec/listen/adapters/polling_spec.rb +8 -8
  137. data/vendor/listen/spec/listen/directory_record_spec.rb +81 -56
  138. data/vendor/listen/spec/listen/listener_spec.rb +128 -39
  139. data/vendor/listen/spec/listen_spec.rb +15 -21
  140. data/vendor/listen/spec/spec_helper.rb +4 -0
  141. data/vendor/listen/spec/support/adapter_helper.rb +52 -15
  142. data/vendor/listen/spec/support/directory_record_helper.rb +7 -5
  143. data/vendor/listen/spec/support/listeners_helper.rb +30 -7
  144. metadata +25 -22
  145. data/ext/mkrf_conf.rb +0 -27
  146. data/lib/sass/importers/deprecated_path.rb +0 -51
  147. data/lib/sass/script/value/deprecated_false.rb +0 -55
  148. data/vendor/listen/lib/listen/dependency_manager.rb +0 -126
  149. data/vendor/listen/lib/listen/multi_listener.rb +0 -143
  150. data/vendor/listen/spec/listen/dependency_manager_spec.rb +0 -107
  151. data/vendor/listen/spec/listen/multi_listener_spec.rb +0 -174
@@ -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)}
@@ -193,8 +193,8 @@ module Sass::Script
193
193
  # \{#map_merge map-merge($map1, $map2)}
194
194
  # : Merges two maps together into a new map.
195
195
  #
196
- # \{#map_remove map-remove($map, $key)}
197
- # : Returns a new map with a key removed.
196
+ # \{#map_remove map-remove($map, $keys...)}
197
+ # : Returns a new map with keys removed.
198
198
  #
199
199
  # \{#map_keys map-keys($map)}
200
200
  # : Returns a list of all keys in a map.
@@ -202,12 +202,54 @@ module Sass::Script
202
202
  # \{#map_values map-values($map)}
203
203
  # : Returns a list of all values in a map.
204
204
  #
205
- # \{#map_has_key map-has-key($key)}
205
+ # \{#map_has_key map-has-key($map, $key)}
206
206
  # : Returns whether a map has a value associated with a given key.
207
207
  #
208
208
  # \{#keywords keywords($args)}
209
209
  # : Returns the keywords passed to a function that takes variable arguments.
210
210
  #
211
+ # ## Selector Functions
212
+ #
213
+ # Selector functions are very liberal in the formats they support
214
+ # for selector arguments. They can take a plain string, a list of
215
+ # lists as returned by `&` or anything in between:
216
+ #
217
+ # * A plain sring, such as `".foo .bar, .baz .bang"`.
218
+ # * A space-separated list of strings such as `(".foo" ".bar")`.
219
+ # * A comma-separated list of strings such as `(".foo .bar", ".baz .bang")`.
220
+ # * A comma-separated list of space-separated lists of strings such
221
+ # as `((".foo" ".bar"), (".baz" ".bang"))`.
222
+ #
223
+ # In general, selector functions allow placeholder selectors
224
+ # (`%foo`) but disallow parent-reference selectors (`&`).
225
+ #
226
+ # \{#selector_nest selector-nest($selectors...)}
227
+ # : Nests selector beneath one another like they would be nested in the
228
+ # stylesheet.
229
+ #
230
+ # \{#selector_append selector-append($selectors...)}
231
+ # : Appends selectors to one another without spaces in between.
232
+ #
233
+ # \{#selector_extend selector-extend($selector, $extendee, $extender)}
234
+ # : Extends `$extendee` with `$extender` within `$selector`.
235
+ #
236
+ # \{#selector_replace selector-replace($selector, $original, $replacement)}
237
+ # : Replaces `$original` with `$replacement` within `$selector`.
238
+ #
239
+ # \{#selector_unify selector-unify($selector1, $selector2)}
240
+ # : Unifies two selectors to produce a selector that matches
241
+ # elements matched by both.
242
+ #
243
+ # \{#is_superselector is-superselector($super, $sub)}
244
+ # : Returns whether `$super` matches all the elements `$sub` does, and
245
+ # possibly more.
246
+ #
247
+ # \{#simple_selectors simple-selectors($selector)}
248
+ # : Returns the simple selectors that comprise a compound selector.
249
+ #
250
+ # \{#selector_parse selector-parse($selector)}
251
+ # : Parses a selector into the format returned by `&`.
252
+ #
211
253
  # ## Introspection Functions
212
254
  #
213
255
  # \{#feature_exists feature-exists($feature)}
@@ -302,6 +344,9 @@ module Sass::Script
302
344
  # safe to call {Value::Base#to_s #to_s} (or other methods that use the string
303
345
  # representation) on those objects without first setting {Tree::Node#options=
304
346
  # the #options attribute}.
347
+ #
348
+ # @comment
349
+ # rubocop:enable LineLength
305
350
  module Functions
306
351
  @signatures = {}
307
352
 
@@ -474,7 +519,7 @@ module Sass::Script
474
519
  def assert_type(value, type, name = nil)
475
520
  klass = Sass::Script::Value.const_get(type)
476
521
  return if value.is_a?(klass)
477
- return if value.is_a?(Sass::Script::Value::List) && type == :Map && value.is_pseudo_map?
522
+ return if value.is_a?(Sass::Script::Value::List) && type == :Map && value.value.empty?
478
523
  err = "#{value.inspect} is not a #{TYPE_NAMES[type] || type.to_s.downcase}"
479
524
  err = "$#{name.to_s.gsub('_', '-')}: " + err if name
480
525
  raise ArgumentError.new(err)
@@ -565,15 +610,15 @@ module Sass::Script
565
610
  #
566
611
  # @see #rgba
567
612
  # @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
613
+ # @param $red [Sass::Script::Value::Number] The amount of red in the color.
614
+ # Must be between 0 and 255 inclusive, or between `0%` and `100%`
615
+ # inclusive
616
+ # @param $green [Sass::Script::Value::Number] The amount of green in the
617
+ # color. Must be between 0 and 255 inclusive, or between `0%` and `100%`
618
+ # inclusive
619
+ # @param $blue [Sass::Script::Value::Number] The amount of blue in the
620
+ # color. Must be between 0 and 255 inclusive, or between `0%` and `100%`
621
+ # inclusive
577
622
  # @return [Sass::Script::Value::Color]
578
623
  # @raise [ArgumentError] if any parameter is the wrong type or out of bounds
579
624
  def rgb(red, green, blue)
@@ -583,14 +628,17 @@ module Sass::Script
583
628
 
584
629
  color_attrs = [[red, :red], [green, :green], [blue, :blue]].map do |(c, name)|
585
630
  if c.is_unit?("%")
586
- v = Sass::Util.check_range("$#{name}: Color value", 0..100, c, '%')
587
- v * 255 / 100.0
631
+ c.value * 255 / 100.0
588
632
  elsif c.unitless?
589
- Sass::Util.check_range("$#{name}: Color value", 0..255, c)
633
+ c.value
590
634
  else
591
635
  raise ArgumentError.new("Expected #{c} to be unitless or have a unit of % but got #{c}")
592
636
  end
593
637
  end
638
+
639
+ # Don't store the string representation for function-created colors, both
640
+ # because it's not very useful and because some functions aren't supported
641
+ # on older browsers.
594
642
  Sass::Script::Value::Color.new(color_attrs)
595
643
  end
596
644
  declare :rgb, [:red, :green, :blue]
@@ -634,7 +682,6 @@ module Sass::Script
634
682
  assert_type color, :Color, :color
635
683
  assert_type alpha, :Number, :alpha
636
684
 
637
- Sass::Util.check_range('Alpha channel', 0..1, alpha)
638
685
  color.with(:alpha => alpha.value)
639
686
  when 4
640
687
  red, green, blue, alpha = args
@@ -653,12 +700,12 @@ module Sass::Script
653
700
  #
654
701
  # @see #hsla
655
702
  # @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
703
+ # @param $hue [Sass::Script::Value::Number] The hue of the color. Should be
704
+ # between 0 and 360 degrees, inclusive
705
+ # @param $saturation [Sass::Script::Value::Number] The saturation of the
706
+ # color. Must be between `0%` and `100%`, inclusive
707
+ # @param $lightness [Sass::Script::Value::Number] The lightness of the
708
+ # color. Must be between `0%` and `100%`, inclusive
662
709
  # @return [Sass::Script::Value::Color]
663
710
  # @raise [ArgumentError] if `$saturation` or `$lightness` are out of bounds
664
711
  # or any parameter is the wrong type
@@ -675,14 +722,14 @@ module Sass::Script
675
722
  #
676
723
  # @see #hsl
677
724
  # @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
725
+ # @param $hue [Sass::Script::Value::Number] The hue of the color. Should be
726
+ # between 0 and 360 degrees, inclusive
727
+ # @param $saturation [Sass::Script::Value::Number] The saturation of the
728
+ # color. Must be between `0%` and `100%`, inclusive
729
+ # @param $lightness [Sass::Script::Value::Number] The lightness of the
730
+ # color. Must be between `0%` and `100%`, inclusive
731
+ # @param $alpha [Sass::Script::Value::Number] The opacity of the color. Must
732
+ # be between 0 and 1, inclusive
686
733
  # @return [Sass::Script::Value::Color]
687
734
  # @raise [ArgumentError] if `$saturation`, `$lightness`, or `$alpha` are out
688
735
  # of bounds or any parameter is the wrong type
@@ -692,12 +739,13 @@ module Sass::Script
692
739
  assert_type lightness, :Number, :lightness
693
740
  assert_type alpha, :Number, :alpha
694
741
 
695
- Sass::Util.check_range('Alpha channel', 0..1, alpha)
696
-
697
742
  h = hue.value
698
- s = Sass::Util.check_range('Saturation', 0..100, saturation, '%')
699
- l = Sass::Util.check_range('Lightness', 0..100, lightness, '%')
743
+ s = saturation.value
744
+ l = lightness.value
700
745
 
746
+ # Don't store the string representation for function-created colors, both
747
+ # because it's not very useful and because some functions aren't supported
748
+ # on older browsers.
701
749
  Sass::Script::Value::Color.new(
702
750
  :hue => h, :saturation => s, :lightness => l, :alpha => alpha.value)
703
751
  end
@@ -709,7 +757,7 @@ module Sass::Script
709
757
  # [hsl-to-rgb]: http://www.w3.org/TR/css3-color/#hsl-color
710
758
  #
711
759
  # @overload red($color)
712
- # @param $color [Sass::Script::Value::Color]
760
+ # @param $color [Sass::Script::Value::Color]
713
761
  # @return [Sass::Script::Value::Number] The red component, between 0 and 255
714
762
  # inclusive
715
763
  # @raise [ArgumentError] if `$color` isn't a color
@@ -725,7 +773,7 @@ module Sass::Script
725
773
  # [hsl-to-rgb]: http://www.w3.org/TR/css3-color/#hsl-color
726
774
  #
727
775
  # @overload green($color)
728
- # @param $color [Sass::Script::Value::Color]
776
+ # @param $color [Sass::Script::Value::Color]
729
777
  # @return [Sass::Script::Value::Number] The green component, between 0 and
730
778
  # 255 inclusive
731
779
  # @raise [ArgumentError] if `$color` isn't a color
@@ -741,7 +789,7 @@ module Sass::Script
741
789
  # [hsl-to-rgb]: http://www.w3.org/TR/css3-color/#hsl-color
742
790
  #
743
791
  # @overload blue($color)
744
- # @param $color [Sass::Script::Value::Color]
792
+ # @param $color [Sass::Script::Value::Color]
745
793
  # @return [Sass::Script::Value::Number] The blue component, between 0 and
746
794
  # 255 inclusive
747
795
  # @raise [ArgumentError] if `$color` isn't a color
@@ -759,7 +807,7 @@ module Sass::Script
759
807
  # [rgb-to-hsl]: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
760
808
  #
761
809
  # @overload hue($color)
762
- # @param $color [Sass::Script::Value::Color]
810
+ # @param $color [Sass::Script::Value::Color]
763
811
  # @return [Sass::Script::Value::Number] The hue component, between 0deg and
764
812
  # 360deg
765
813
  # @raise [ArgumentError] if `$color` isn't a color
@@ -777,7 +825,7 @@ module Sass::Script
777
825
  # [rgb-to-hsl]: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
778
826
  #
779
827
  # @overload saturation($color)
780
- # @param $color [Sass::Script::Value::Color]
828
+ # @param $color [Sass::Script::Value::Color]
781
829
  # @return [Sass::Script::Value::Number] The saturation component, between 0%
782
830
  # and 100%
783
831
  # @raise [ArgumentError] if `$color` isn't a color
@@ -795,7 +843,7 @@ module Sass::Script
795
843
  # [rgb-to-hsl]: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
796
844
  #
797
845
  # @overload lightness($color)
798
- # @param $color [Sass::Script::Value::Color]
846
+ # @param $color [Sass::Script::Value::Color]
799
847
  # @return [Sass::Script::Value::Number] The lightness component, between 0%
800
848
  # and 100%
801
849
  # @raise [ArgumentError] if `$color` isn't a color
@@ -812,7 +860,7 @@ module Sass::Script
812
860
  # syntax as a special case.
813
861
  #
814
862
  # @overload alpha($color)
815
- # @param $color [Sass::Script::Value::Color]
863
+ # @param $color [Sass::Script::Value::Color]
816
864
  # @return [Sass::Script::Value::Number] The alpha component, between 0 and 1
817
865
  # @raise [ArgumentError] if `$color` isn't a color
818
866
  def alpha(*args)
@@ -835,7 +883,7 @@ module Sass::Script
835
883
  # otherwise specified.
836
884
  #
837
885
  # @overload opacity($color)
838
- # @param $color [Sass::Script::Value::Color]
886
+ # @param $color [Sass::Script::Value::Color]
839
887
  # @return [Sass::Script::Value::Number] The alpha component, between 0 and 1
840
888
  # @raise [ArgumentError] if `$color` isn't a color
841
889
  def opacity(color)
@@ -855,9 +903,9 @@ module Sass::Script
855
903
  # opacify(rgba(0, 0, 0, 0.5), 0.1) => rgba(0, 0, 0, 0.6)
856
904
  # opacify(rgba(0, 0, 17, 0.8), 0.2) => #001
857
905
  # @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
906
+ # @param $color [Sass::Script::Value::Color]
907
+ # @param $amount [Sass::Script::Value::Number] The amount to increase the
908
+ # opacity by, between 0 and 1
861
909
  # @return [Sass::Script::Value::Color]
862
910
  # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
863
911
  # is the wrong type
@@ -877,9 +925,9 @@ module Sass::Script
877
925
  # transparentize(rgba(0, 0, 0, 0.5), 0.1) => rgba(0, 0, 0, 0.4)
878
926
  # transparentize(rgba(0, 0, 0, 0.8), 0.2) => rgba(0, 0, 0, 0.6)
879
927
  # @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
928
+ # @param $color [Sass::Script::Value::Color]
929
+ # @param $amount [Sass::Script::Value::Number] The amount to decrease the
930
+ # opacity by, between 0 and 1
883
931
  # @return [Sass::Script::Value::Color]
884
932
  # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
885
933
  # is the wrong type
@@ -899,9 +947,9 @@ module Sass::Script
899
947
  # lighten(hsl(0, 0%, 0%), 30%) => hsl(0, 0, 30)
900
948
  # lighten(#800, 20%) => #e00
901
949
  # @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%`
950
+ # @param $color [Sass::Script::Value::Color]
951
+ # @param $amount [Sass::Script::Value::Number] The amount to increase the
952
+ # lightness by, between `0%` and `100%`
905
953
  # @return [Sass::Script::Value::Color]
906
954
  # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
907
955
  # is the wrong type
@@ -918,9 +966,9 @@ module Sass::Script
918
966
  # darken(hsl(25, 100%, 80%), 30%) => hsl(25, 100%, 50%)
919
967
  # darken(#800, 20%) => #200
920
968
  # @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%`
969
+ # @param $color [Sass::Script::Value::Color]
970
+ # @param $amount [Sass::Script::Value::Number] The amount to decrease the
971
+ # lightness by, between `0%` and `100%`
924
972
  # @return [Sass::Script::Value::Color]
925
973
  # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
926
974
  # is the wrong type
@@ -937,9 +985,9 @@ module Sass::Script
937
985
  # saturate(hsl(120, 30%, 90%), 20%) => hsl(120, 50%, 90%)
938
986
  # saturate(#855, 20%) => #9e3f3f
939
987
  # @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%`
988
+ # @param $color [Sass::Script::Value::Color]
989
+ # @param $amount [Sass::Script::Value::Number] The amount to increase the
990
+ # saturation by, between `0%` and `100%`
943
991
  # @return [Sass::Script::Value::Color]
944
992
  # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
945
993
  # is the wrong type
@@ -960,9 +1008,9 @@ module Sass::Script
960
1008
  # desaturate(hsl(120, 30%, 90%), 20%) => hsl(120, 10%, 90%)
961
1009
  # desaturate(#855, 20%) => #726b6b
962
1010
  # @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%`
1011
+ # @param $color [Sass::Script::Value::Color]
1012
+ # @param $amount [Sass::Script::Value::Number] The amount to decrease the
1013
+ # saturation by, between `0%` and `100%`
966
1014
  # @return [Sass::Script::Value::Color]
967
1015
  # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
968
1016
  # is the wrong type
@@ -977,12 +1025,12 @@ module Sass::Script
977
1025
  #
978
1026
  # @example
979
1027
  # adjust-hue(hsl(120, 30%, 90%), 60deg) => hsl(180, 30%, 90%)
980
- # adjust-hue(hsl(120, 30%, 90%), 060deg) => hsl(60, 30%, 90%)
1028
+ # adjust-hue(hsl(120, 30%, 90%), -60deg) => hsl(60, 30%, 90%)
981
1029
  # adjust-hue(#811, 45deg) => #886a11
982
1030
  # @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
1031
+ # @param $color [Sass::Script::Value::Color]
1032
+ # @param $degrees [Sass::Script::Value::Number] The number of degrees to
1033
+ # rotate the hue
986
1034
  # @return [Sass::Script::Value::Color]
987
1035
  # @raise [ArgumentError] if either parameter is the wrong type
988
1036
  def adjust_hue(color, degrees)
@@ -999,7 +1047,7 @@ module Sass::Script
999
1047
  # ie-hex-str(#3322BB) => #FF3322BB
1000
1048
  # ie-hex-str(rgba(0, 255, 0, 0.5)) => #8000FF00
1001
1049
  # @overload ie_hex_str($color)
1002
- # @param $color [Sass::Script::Value::Color]
1050
+ # @param $color [Sass::Script::Value::Color]
1003
1051
  # @return [Sass::Script::Value::String] The IE-formatted string
1004
1052
  # representation of the color
1005
1053
  # @raise [ArgumentError] if `$color` isn't a color
@@ -1023,23 +1071,26 @@ module Sass::Script
1023
1071
  # adjust-color(#102030, $blue: 5) => #102035
1024
1072
  # adjust-color(#102030, $red: -5, $blue: 5) => #0b2035
1025
1073
  # 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
1074
+ # @comment
1075
+ # rubocop:disable LineLength
1076
+ # @overload adjust_color($color, [$red], [$green], [$blue], [$hue], [$saturation], [$lightness], [$alpha])
1077
+ # @comment
1078
+ # rubocop:disable LineLength
1079
+ # @param $color [Sass::Script::Value::Color]
1080
+ # @param $red [Sass::Script::Value::Number] The adjustment to make on the
1081
+ # red component, between -255 and 255 inclusive
1082
+ # @param $green [Sass::Script::Value::Number] The adjustment to make on the
1083
+ # green component, between -255 and 255 inclusive
1084
+ # @param $blue [Sass::Script::Value::Number] The adjustment to make on the
1085
+ # blue component, between -255 and 255 inclusive
1086
+ # @param $hue [Sass::Script::Value::Number] The adjustment to make on the
1087
+ # hue component, in degrees
1088
+ # @param $saturation [Sass::Script::Value::Number] The adjustment to make on
1089
+ # the saturation component, between `-100%` and `100%` inclusive
1090
+ # @param $lightness [Sass::Script::Value::Number] The adjustment to make on
1091
+ # the lightness component, between `-100%` and `100%` inclusive
1092
+ # @param $alpha [Sass::Script::Value::Number] The adjustment to make on the
1093
+ # alpha component, between -1 and 1 inclusive
1043
1094
  # @return [Sass::Script::Value::Color]
1044
1095
  # @raise [ArgumentError] if any parameter is the wrong type or out-of
1045
1096
  # bounds, or if RGB properties and HSL properties are adjusted at the
@@ -1101,15 +1152,18 @@ module Sass::Script
1101
1152
  # scale-color(hsl(120, 70%, 80%), $lightness: 50%) => hsl(120, 70%, 90%)
1102
1153
  # scale-color(rgb(200, 150%, 170%), $green: -40%, $blue: 70%) => rgb(200, 90, 229)
1103
1154
  # 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]
1155
+ # @comment
1156
+ # rubocop:disable LineLength
1157
+ # @overload scale_color($color, [$red], [$green], [$blue], [$saturation], [$lightness], [$alpha])
1158
+ # @comment
1159
+ # rubocop:disable LineLength
1160
+ # @param $color [Sass::Script::Value::Color]
1161
+ # @param $red [Sass::Script::Value::Number]
1162
+ # @param $green [Sass::Script::Value::Number]
1163
+ # @param $blue [Sass::Script::Value::Number]
1164
+ # @param $saturation [Sass::Script::Value::Number]
1165
+ # @param $lightness [Sass::Script::Value::Number]
1166
+ # @param $alpha [Sass::Script::Value::Number]
1113
1167
  # @return [Sass::Script::Value::Color]
1114
1168
  # @raise [ArgumentError] if any parameter is the wrong type or out-of
1115
1169
  # bounds, or if RGB properties and HSL properties are adjusted at the
@@ -1159,35 +1213,53 @@ module Sass::Script
1159
1213
  # change-color(#102030, $blue: 5) => #102005
1160
1214
  # change-color(#102030, $red: 120, $blue: 5) => #782005
1161
1215
  # 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
1216
+ # @comment
1217
+ # rubocop:disable LineLength
1218
+ # @overload change_color($color, [$red], [$green], [$blue], [$hue], [$saturation], [$lightness], [$alpha])
1219
+ # @comment
1220
+ # rubocop:disable LineLength
1221
+ # @param $color [Sass::Script::Value::Color]
1222
+ # @param $red [Sass::Script::Value::Number] The new red component for the
1223
+ # color, within 0 and 255 inclusive
1224
+ # @param $green [Sass::Script::Value::Number] The new green component for
1225
+ # the color, within 0 and 255 inclusive
1226
+ # @param $blue [Sass::Script::Value::Number] The new blue component for the
1227
+ # color, within 0 and 255 inclusive
1228
+ # @param $hue [Sass::Script::Value::Number] The new hue component for the
1229
+ # color, in degrees
1230
+ # @param $saturation [Sass::Script::Value::Number] The new saturation
1231
+ # component for the color, between `0%` and `100%` inclusive
1232
+ # @param $lightness [Sass::Script::Value::Number] The new lightness
1233
+ # component for the color, within `0%` and `100%` inclusive
1234
+ # @param $alpha [Sass::Script::Value::Number] The new alpha component for
1235
+ # the color, within 0 and 1 inclusive
1179
1236
  # @return [Sass::Script::Value::Color]
1180
1237
  # @raise [ArgumentError] if any parameter is the wrong type or out-of
1181
1238
  # bounds, or if RGB properties and HSL properties are adjusted at the
1182
1239
  # same time
1183
1240
  def change_color(color, kwargs)
1184
1241
  assert_type color, :Color, :color
1185
- with = Sass::Util.to_hash(%w[red green blue hue saturation lightness alpha].map do |name|
1242
+ with = Sass::Util.map_hash(
1243
+ 'red' => ['Red value', 0..255],
1244
+ 'green' => ['Green value', 0..255],
1245
+ 'blue' => ['Blue value', 0..255],
1246
+ 'hue' => [],
1247
+ 'saturation' => ['Saturation', 0..100, '%'],
1248
+ 'lightness' => ['Lightness', 0..100, '%'],
1249
+ 'alpha' => ['Alpha channel', 0..1]
1250
+ ) do |name, (desc, range, unit)|
1186
1251
  val = kwargs.delete(name)
1187
1252
  next unless val
1188
1253
  assert_type val, :Number, name
1189
- [name.to_sym, val.value]
1190
- end)
1254
+
1255
+ if range
1256
+ val = Sass::Util.check_range(desc, range, val, unit)
1257
+ else
1258
+ val = val.value
1259
+ end
1260
+
1261
+ [name.to_sym, val]
1262
+ end
1191
1263
 
1192
1264
  unless kwargs.empty?
1193
1265
  name, val = kwargs.to_a.first
@@ -1212,11 +1284,11 @@ module Sass::Script
1212
1284
  # mix(#f00, #00f, 25%) => #3f00bf
1213
1285
  # mix(rgba(255, 0, 0, 0.5), #00f) => rgba(63, 0, 191, 0.75)
1214
1286
  # @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`
1287
+ # @param $color1 [Sass::Script::Value::Color]
1288
+ # @param $color2 [Sass::Script::Value::Color]
1289
+ # @param $weight [Sass::Script::Value::Number] The relative weight of each
1290
+ # color. Closer to `0%` gives more weight to `$color`, closer to `100%`
1291
+ # gives more weight to `$color2`
1220
1292
  # @return [Sass::Script::Value::Color]
1221
1293
  # @raise [ArgumentError] if `$weight` is out of bounds or any parameter is
1222
1294
  # the wrong type
@@ -1257,15 +1329,15 @@ module Sass::Script
1257
1329
  rgba << color1.alpha * p + color2.alpha * (1 - p)
1258
1330
  rgb_color(*rgba)
1259
1331
  end
1260
- declare :mix, [:color1, :color2], :deprecated => [:color_1, :color_2]
1261
- declare :mix, [:color1, :color2, :weight], :deprecated => [:color_1, :color_2, :weight]
1332
+ declare :mix, [:color1, :color2]
1333
+ declare :mix, [:color1, :color2, :weight]
1262
1334
 
1263
1335
  # Converts a color to grayscale. This is identical to `desaturate(color,
1264
1336
  # 100%)`.
1265
1337
  #
1266
1338
  # @see #desaturate
1267
1339
  # @overload grayscale($color)
1268
- # @param $color [Sass::Script::Value::Color]
1340
+ # @param $color [Sass::Script::Value::Color]
1269
1341
  # @return [Sass::Script::Value::Color]
1270
1342
  # @raise [ArgumentError] if `$color` isn't a color
1271
1343
  def grayscale(color)
@@ -1281,7 +1353,7 @@ module Sass::Script
1281
1353
  #
1282
1354
  # @see #adjust_hue #adjust-hue
1283
1355
  # @overload complement($color)
1284
- # @param $color [Sass::Script::Value::Color]
1356
+ # @param $color [Sass::Script::Value::Color]
1285
1357
  # @return [Sass::Script::Value::Color]
1286
1358
  # @raise [ArgumentError] if `$color` isn't a color
1287
1359
  def complement(color)
@@ -1293,7 +1365,7 @@ module Sass::Script
1293
1365
  # are inverted, while the opacity is left alone.
1294
1366
  #
1295
1367
  # @overload invert($color)
1296
- # @param $color [Sass::Script::Value::Color]
1368
+ # @param $color [Sass::Script::Value::Color]
1297
1369
  # @return [Sass::Script::Value::Color]
1298
1370
  # @raise [ArgumentError] if `$color` isn't a color
1299
1371
  def invert(color)
@@ -1317,7 +1389,7 @@ module Sass::Script
1317
1389
  # unquote("foo") => foo
1318
1390
  # unquote(foo) => foo
1319
1391
  # @overload unquote($string)
1320
- # @param $string [Sass::Script::Value::String]
1392
+ # @param $string [Sass::Script::Value::String]
1321
1393
  # @return [Sass::Script::Value::String]
1322
1394
  # @raise [ArgumentError] if `$string` isn't a string
1323
1395
  def unquote(string)
@@ -1337,7 +1409,7 @@ module Sass::Script
1337
1409
  # quote("foo") => "foo"
1338
1410
  # quote(foo) => "foo"
1339
1411
  # @overload quote($string)
1340
- # @param $string [Sass::Script::Value::String]
1412
+ # @param $string [Sass::Script::Value::String]
1341
1413
  # @return [Sass::Script::Value::String]
1342
1414
  # @raise [ArgumentError] if `$string` isn't a string
1343
1415
  def quote(string)
@@ -1355,7 +1427,7 @@ module Sass::Script
1355
1427
  # @example
1356
1428
  # str-length("foo") => 3
1357
1429
  # @overload str_length($string)
1358
- # @param $string [Sass::Script::Value::String]
1430
+ # @param $string [Sass::Script::Value::String]
1359
1431
  # @return [Sass::Script::Value::Number]
1360
1432
  # @raise [ArgumentError] if `$string` isn't a string
1361
1433
  def str_length(string)
@@ -1375,12 +1447,12 @@ module Sass::Script
1375
1447
  # str-insert("abcd", "X", 5) => "abcdX"
1376
1448
  #
1377
1449
  # @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
1450
+ # @param $string [Sass::Script::Value::String]
1451
+ # @param $insert [Sass::Script::Value::String]
1452
+ # @param $index [Sass::Script::Value::Number] The position at which
1453
+ # `$insert` will be inserted. Negative indices count from the end of
1454
+ # `$string`. An index that's outside the bounds of the string will insert
1455
+ # `$insert` at the front or back of the string
1384
1456
  # @return [Sass::Script::Value::String] The result string. This will be
1385
1457
  # quoted if and only if `$string` was quoted
1386
1458
  # @raise [ArgumentError] if any parameter is the wrong type
@@ -1399,8 +1471,8 @@ module Sass::Script
1399
1471
  end
1400
1472
  declare :str_insert, [:string, :insert, :index]
1401
1473
 
1402
- # Returns the index of the first occurance of `$substring` in `$string`. If
1403
- # there is no such occurance, returns `null`.
1474
+ # Returns the index of the first occurrence of `$substring` in `$string`. If
1475
+ # there is no such occurrence, returns `null`.
1404
1476
  #
1405
1477
  # Note that unlike some languages, the first character in a Sass string is
1406
1478
  # number 1, the second number 2, and so forth.
@@ -1412,8 +1484,8 @@ module Sass::Script
1412
1484
  # str-index(abcd, c) => 3
1413
1485
  #
1414
1486
  # @overload str_index($string, $substring)
1415
- # @param $string [Sass::Script::Value::String]
1416
- # @param $substring [Sass::Script::Value::String]
1487
+ # @param $string [Sass::Script::Value::String]
1488
+ # @param $substring [Sass::Script::Value::String]
1417
1489
  # @return [Sass::Script::Value::Number, Sass::Script::Value::Null]
1418
1490
  # @raise [ArgumentError] if any parameter is the wrong type
1419
1491
  def str_index(string, substring)
@@ -1437,14 +1509,14 @@ module Sass::Script
1437
1509
  # str-slice("abcd", 2, -2) => "bc"
1438
1510
  #
1439
1511
  # @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
1512
+ # @param $start-at [Sass::Script::Value::Number] The index of the first
1513
+ # character of the substring. If this is negative, it counts from the end
1514
+ # of `$string`
1515
+ # @param $end-before [Sass::Script::Value::Number] The index of the last
1516
+ # character of the substring. If this is negative, it counts from the end
1517
+ # of `$string`. Defaults to -1
1518
+ # @return [Sass::Script::Value::String] The substring. This will be quoted
1519
+ # if and only if `$string` was quoted
1448
1520
  # @raise [ArgumentError] if any parameter is the wrong type
1449
1521
  def str_slice(string, start_at, end_at = nil)
1450
1522
  assert_type string, :String, :string
@@ -1453,6 +1525,7 @@ module Sass::Script
1453
1525
  end_at = number(-1) if end_at.nil?
1454
1526
  assert_unit end_at, nil, "end-at"
1455
1527
 
1528
+ return Sass::Script::Value::String.new("", string.type) if end_at.value == 0
1456
1529
  s = start_at.value > 0 ? start_at.value - 1 : start_at.value
1457
1530
  e = end_at.value > 0 ? end_at.value - 1 : end_at.value
1458
1531
  s = string.value.length + s if s < 0
@@ -1471,7 +1544,7 @@ module Sass::Script
1471
1544
  # to-upper-case(abcd) => ABCD
1472
1545
  #
1473
1546
  # @overload to_upper_case($string)
1474
- # @param $string [Sass::Script::Value::String]
1547
+ # @param $string [Sass::Script::Value::String]
1475
1548
  # @return [Sass::Script::Value::String]
1476
1549
  # @raise [ArgumentError] if `$string` isn't a string
1477
1550
  def to_upper_case(string)
@@ -1486,7 +1559,7 @@ module Sass::Script
1486
1559
  # to-lower-case(ABCD) => abcd
1487
1560
  #
1488
1561
  # @overload to_lower_case($string)
1489
- # @param $string [Sass::Script::Value::String]
1562
+ # @param $string [Sass::Script::Value::String]
1490
1563
  # @return [Sass::Script::Value::String]
1491
1564
  # @raise [ArgumentError] if `$string` isn't a string
1492
1565
  def to_lower_case(string)
@@ -1505,7 +1578,7 @@ module Sass::Script
1505
1578
  # type-of(#fff) => color
1506
1579
  # type-of(blue) => color
1507
1580
  # @overload type_of($value)
1508
- # @param $value [Sass::Script::Value::Base] The value to inspect
1581
+ # @param $value [Sass::Script::Value::Base] The value to inspect
1509
1582
  # @return [Sass::Script::Value::String] The unquoted string name of the
1510
1583
  # value's type
1511
1584
  def type_of(value)
@@ -1515,12 +1588,27 @@ module Sass::Script
1515
1588
 
1516
1589
  # Returns whether a feature exists in the current Sass runtime.
1517
1590
  #
1591
+ # The following features are supported:
1592
+ #
1593
+ # * `global-variable-shadowing` indicates that a local variable will shadow
1594
+ # a global variable unless `!global` is used.
1595
+ #
1596
+ # * `extend-selector-pseudoclass` indicates that `@extend` will reach into
1597
+ # selector pseudoclasses like `:not`.
1598
+ #
1599
+ # * `units-level-3` indicates full support for unit arithmetic using units
1600
+ # defined in the [Values and Units Level 3][] spec.
1601
+ #
1602
+ # [Values and Units Level 3]: http://www.w3.org/TR/css3-values/
1603
+ #
1604
+ # * `at-error` indicates that the Sass `@error` directive is supported.
1605
+ #
1518
1606
  # @example
1519
1607
  # feature-exists(some-feature-that-exists) => true
1520
1608
  # feature-exists(what-is-this-i-dont-know) => false
1521
1609
  #
1522
1610
  # @overload feature_exists($feature)
1523
- # @param $feature [Sass::Script::Value::String] The name of the feature
1611
+ # @param $feature [Sass::Script::Value::String] The name of the feature
1524
1612
  # @return [Sass::Script::Value::Bool] Whether the feature is supported in this version of Sass
1525
1613
  # @raise [ArgumentError] if `$feature` isn't a string
1526
1614
  def feature_exists(feature)
@@ -1539,7 +1627,7 @@ module Sass::Script
1539
1627
  # unit(10px * 5em) => "em*px"
1540
1628
  # unit(10px * 5em / 30cm / 1rem) => "em*px/cm*rem"
1541
1629
  # @overload unit($number)
1542
- # @param $number [Sass::Script::Value::Number]
1630
+ # @param $number [Sass::Script::Value::Number]
1543
1631
  # @return [Sass::Script::Value::String] The unit(s) of the number, as a
1544
1632
  # quoted string
1545
1633
  # @raise [ArgumentError] if `$number` isn't a number
@@ -1555,7 +1643,7 @@ module Sass::Script
1555
1643
  # unitless(100) => true
1556
1644
  # unitless(100px) => false
1557
1645
  # @overload unitless($number)
1558
- # @param $number [Sass::Script::Value::Number]
1646
+ # @param $number [Sass::Script::Value::Number]
1559
1647
  # @return [Sass::Script::Value::Bool]
1560
1648
  # @raise [ArgumentError] if `$number` isn't a number
1561
1649
  def unitless(number)
@@ -1571,8 +1659,8 @@ module Sass::Script
1571
1659
  # comparable(100px, 3em) => false
1572
1660
  # comparable(10cm, 3mm) => true
1573
1661
  # @overload comparable($number1, $number2)
1574
- # @param $number1 [Sass::Script::Value::Number]
1575
- # @param $number2 [Sass::Script::Value::Number]
1662
+ # @param $number1 [Sass::Script::Value::Number]
1663
+ # @param $number2 [Sass::Script::Value::Number]
1576
1664
  # @return [Sass::Script::Value::Bool]
1577
1665
  # @raise [ArgumentError] if either parameter is the wrong type
1578
1666
  def comparable(number1, number2)
@@ -1580,7 +1668,7 @@ module Sass::Script
1580
1668
  assert_type number2, :Number, :number2
1581
1669
  bool(number1.comparable_to?(number2))
1582
1670
  end
1583
- declare :comparable, [:number1, :number2], :deprecated => [:number_1, :number_2]
1671
+ declare :comparable, [:number1, :number2]
1584
1672
 
1585
1673
  # Converts a unitless number to a percentage.
1586
1674
  #
@@ -1588,7 +1676,7 @@ module Sass::Script
1588
1676
  # percentage(0.2) => 20%
1589
1677
  # percentage(100px / 50px) => 200%
1590
1678
  # @overload percentage($number)
1591
- # @param $number [Sass::Script::Value::Number]
1679
+ # @param $number [Sass::Script::Value::Number]
1592
1680
  # @return [Sass::Script::Value::Number]
1593
1681
  # @raise [ArgumentError] if `$number` isn't a unitless number
1594
1682
  def percentage(number)
@@ -1597,7 +1685,7 @@ module Sass::Script
1597
1685
  end
1598
1686
  number(number.value * 100, '%')
1599
1687
  end
1600
- declare :percentage, [:number], :deprecated => [:value]
1688
+ declare :percentage, [:number]
1601
1689
 
1602
1690
  # Rounds a number to the nearest whole number.
1603
1691
  #
@@ -1605,13 +1693,13 @@ module Sass::Script
1605
1693
  # round(10.4px) => 10px
1606
1694
  # round(10.6px) => 11px
1607
1695
  # @overload round($number)
1608
- # @param $number [Sass::Script::Value::Number]
1696
+ # @param $number [Sass::Script::Value::Number]
1609
1697
  # @return [Sass::Script::Value::Number]
1610
1698
  # @raise [ArgumentError] if `$number` isn't a number
1611
1699
  def round(number)
1612
1700
  numeric_transformation(number) {|n| n.round}
1613
1701
  end
1614
- declare :round, [:number], :deprecated => [:value]
1702
+ declare :round, [:number]
1615
1703
 
1616
1704
  # Rounds a number up to the next whole number.
1617
1705
  #
@@ -1619,13 +1707,13 @@ module Sass::Script
1619
1707
  # ceil(10.4px) => 11px
1620
1708
  # ceil(10.6px) => 11px
1621
1709
  # @overload ceil($number)
1622
- # @param $number [Sass::Script::Value::Number]
1710
+ # @param $number [Sass::Script::Value::Number]
1623
1711
  # @return [Sass::Script::Value::Number]
1624
1712
  # @raise [ArgumentError] if `$number` isn't a number
1625
1713
  def ceil(number)
1626
1714
  numeric_transformation(number) {|n| n.ceil}
1627
1715
  end
1628
- declare :ceil, [:number], :deprecated => [:value]
1716
+ declare :ceil, [:number]
1629
1717
 
1630
1718
  # Rounds a number down to the previous whole number.
1631
1719
  #
@@ -1633,13 +1721,13 @@ module Sass::Script
1633
1721
  # floor(10.4px) => 10px
1634
1722
  # floor(10.6px) => 10px
1635
1723
  # @overload floor($number)
1636
- # @param $number [Sass::Script::Value::Number]
1724
+ # @param $number [Sass::Script::Value::Number]
1637
1725
  # @return [Sass::Script::Value::Number]
1638
1726
  # @raise [ArgumentError] if `$number` isn't a number
1639
1727
  def floor(number)
1640
1728
  numeric_transformation(number) {|n| n.floor}
1641
1729
  end
1642
- declare :floor, [:number], :deprecated => [:value]
1730
+ declare :floor, [:number]
1643
1731
 
1644
1732
  # Returns the absolute value of a number.
1645
1733
  #
@@ -1647,13 +1735,13 @@ module Sass::Script
1647
1735
  # abs(10px) => 10px
1648
1736
  # abs(-10px) => 10px
1649
1737
  # @overload abs($number)
1650
- # @param $number [Sass::Script::Value::Number]
1738
+ # @param $number [Sass::Script::Value::Number]
1651
1739
  # @return [Sass::Script::Value::Number]
1652
1740
  # @raise [ArgumentError] if `$number` isn't a number
1653
1741
  def abs(number)
1654
1742
  numeric_transformation(number) {|n| n.abs}
1655
1743
  end
1656
- declare :abs, [:number], :deprecated => [:value]
1744
+ declare :abs, [:number]
1657
1745
 
1658
1746
  # Finds the minimum of several numbers. This function takes any number of
1659
1747
  # arguments.
@@ -1662,7 +1750,7 @@ module Sass::Script
1662
1750
  # min(1px, 4px) => 1px
1663
1751
  # min(5em, 3em, 4em) => 3em
1664
1752
  # @overload min($numbers...)
1665
- # @param $numbers [[Sass::Script::Value::Number]]
1753
+ # @param $numbers [[Sass::Script::Value::Number]]
1666
1754
  # @return [Sass::Script::Value::Number]
1667
1755
  # @raise [ArgumentError] if any argument isn't a number, or if not all of
1668
1756
  # the arguments have comparable units
@@ -1679,7 +1767,7 @@ module Sass::Script
1679
1767
  # max(1px, 4px) => 4px
1680
1768
  # max(5em, 3em, 4em) => 5em
1681
1769
  # @overload max($numbers...)
1682
- # @param $numbers [[Sass::Script::Value::Number]]
1770
+ # @param $numbers [[Sass::Script::Value::Number]]
1683
1771
  # @return [Sass::Script::Value::Number]
1684
1772
  # @raise [ArgumentError] if any argument isn't a number, or if not all of
1685
1773
  # the arguments have comparable units
@@ -1698,7 +1786,7 @@ module Sass::Script
1698
1786
  # length(10px 20px 30px) => 3
1699
1787
  # length((width: 10px, height: 20px)) => 2
1700
1788
  # @overload length($list)
1701
- # @param $list [Sass::Script::Value::Base]
1789
+ # @param $list [Sass::Script::Value::Base]
1702
1790
  # @return [Sass::Script::Value::Number]
1703
1791
  def length(list)
1704
1792
  number(list.to_a.size)
@@ -1717,11 +1805,11 @@ module Sass::Script
1717
1805
  # @example
1718
1806
  # set-nth($list: 10px 20px 30px, $n: 2, $value: -20px) => 10px -20px 30px
1719
1807
  # @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`.
1808
+ # @param $list [Sass::Script::Value::Base] The list that will be copied, having the element
1809
+ # at index `$n` changed.
1810
+ # @param $n [Sass::Script::Value::Number] The index of the item to set.
1811
+ # Negative indices count from the end of the list.
1812
+ # @param $value [Sass::Script::Value::Base] The new value at index `$n`.
1725
1813
  # @return [Sass::Script::Value::List]
1726
1814
  # @raise [ArgumentError] if `$n` isn't an integer between 1 and the length
1727
1815
  # of `$list`
@@ -1750,9 +1838,9 @@ module Sass::Script
1750
1838
  # nth((Helvetica, Arial, sans-serif), 3) => sans-serif
1751
1839
  # nth((width: 10px, length: 20px), 2) => length, 20px
1752
1840
  # @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.
1841
+ # @param $list [Sass::Script::Value::Base]
1842
+ # @param $n [Sass::Script::Value::Number] The index of the item to get.
1843
+ # Negative indices count from the end of the list.
1756
1844
  # @return [Sass::Script::Value::Base]
1757
1845
  # @raise [ArgumentError] if `$n` isn't an integer between 1 and the length
1758
1846
  # of `$list`
@@ -1779,11 +1867,11 @@ module Sass::Script
1779
1867
  # join(10px, 20px, comma) => 10px, 20px
1780
1868
  # join((blue, red), (#abc, #def), space) => blue red #abc #def
1781
1869
  # @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.
1870
+ # @param $list1 [Sass::Script::Value::Base]
1871
+ # @param $list2 [Sass::Script::Value::Base]
1872
+ # @param $separator [Sass::Script::Value::String] The list separator to use.
1873
+ # If this is `comma` or `space`, that separator will be used. If this is
1874
+ # `auto` (the default), the separator is determined as explained above.
1787
1875
  # @return [Sass::Script::Value::List]
1788
1876
  def join(list1, list2, separator = identifier("auto"))
1789
1877
  assert_type separator, :String, :separator
@@ -1812,11 +1900,11 @@ module Sass::Script
1812
1900
  # append(10px, 20px, comma) => 10px, 20px
1813
1901
  # append((blue, red), green, space) => blue red green
1814
1902
  # @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.
1903
+ # @param $list [Sass::Script::Value::Base]
1904
+ # @param $val [Sass::Script::Value::Base]
1905
+ # @param $separator [Sass::Script::Value::String] The list separator to use.
1906
+ # If this is `comma` or `space`, that separator will be used. If this is
1907
+ # `auto` (the default), the separator is determined as explained above.
1820
1908
  # @return [Sass::Script::Value::List]
1821
1909
  def append(list, val, separator = identifier("auto"))
1822
1910
  assert_type separator, :String, :separator
@@ -1844,7 +1932,7 @@ module Sass::Script
1844
1932
  # zip(1px 1px 3px, solid dashed solid, red green blue)
1845
1933
  # => 1px solid red, 1px dashed green, 3px solid blue
1846
1934
  # @overload zip($lists...)
1847
- # @param $lists [[Sass::Script::Value::Base]]
1935
+ # @param $lists [[Sass::Script::Value::Base]]
1848
1936
  # @return [Sass::Script::Value::List]
1849
1937
  def zip(*lists)
1850
1938
  length = nil
@@ -1873,16 +1961,15 @@ module Sass::Script
1873
1961
  # @example
1874
1962
  # index(1px solid red, solid) => 2
1875
1963
  # index(1px solid red, dashed) => null
1876
- # index((width: 10px, height: 20px), (height, 20px)) => 2
1964
+ # index((width: 10px, height: 20px), (height 20px)) => 2
1877
1965
  # @overload index($list, $value)
1878
- # @param $list [Sass::Script::Value::Base]
1879
- # @param $value [Sass::Script::Value::Base]
1966
+ # @param $list [Sass::Script::Value::Base]
1967
+ # @param $value [Sass::Script::Value::Base]
1880
1968
  # @return [Sass::Script::Value::Number, Sass::Script::Value::Null] The
1881
1969
  # 1-based index of `$value` in `$list`, or `null`
1882
1970
  def index(list, value)
1883
1971
  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)
1972
+ index ? number(index + 1) : null
1886
1973
  end
1887
1974
  declare :index, [:list, :value]
1888
1975
 
@@ -1894,7 +1981,7 @@ module Sass::Script
1894
1981
  # list-separator(1px, 2px, 3px) => comma
1895
1982
  # list-separator('foo') => space
1896
1983
  # @overload list_separator($list)
1897
- # @param $list [Sass::Script::Value::Base]
1984
+ # @param $list [Sass::Script::Value::Base]
1898
1985
  # @return [Sass::Script::Value::String] `comma` or `space`
1899
1986
  def list_separator(list)
1900
1987
  identifier((list.separator || :space).to_s)
@@ -1909,14 +1996,14 @@ module Sass::Script
1909
1996
  # map-get(("foo": 1, "bar": 2), "bar") => 2
1910
1997
  # map-get(("foo": 1, "bar": 2), "baz") => null
1911
1998
  # @overload map_get($map, $key)
1912
- # @param $map [Sass::Script::Value::Map]
1913
- # @param $key [Sass::Script::Value::Base]
1999
+ # @param $map [Sass::Script::Value::Map]
2000
+ # @param $key [Sass::Script::Value::Base]
1914
2001
  # @return [Sass::Script::Value::Base] The value indexed by `$key`, or `null`
1915
2002
  # if the map doesn't contain the given key
1916
2003
  # @raise [ArgumentError] if `$map` is not a map
1917
2004
  def map_get(map, key)
1918
2005
  assert_type map, :Map, :map
1919
- to_h(map)[key] || null
2006
+ map.to_h[key] || null
1920
2007
  end
1921
2008
  declare :map_get, [:map, :key]
1922
2009
 
@@ -1933,46 +2020,47 @@ module Sass::Script
1933
2020
  # map-merge(("foo": 1), ("bar": 2)) => ("foo": 1, "bar": 2)
1934
2021
  # map-merge(("foo": 1, "bar": 2), ("bar": 3)) => ("foo": 1, "bar": 3)
1935
2022
  # @overload map_merge($map1, $map2)
1936
- # @param $map1 [Sass::Script::Value::Map]
1937
- # @param $map2 [Sass::Script::Value::Map]
2023
+ # @param $map1 [Sass::Script::Value::Map]
2024
+ # @param $map2 [Sass::Script::Value::Map]
1938
2025
  # @return [Sass::Script::Value::Map]
1939
2026
  # @raise [ArgumentError] if either parameter is not a map
1940
2027
  def map_merge(map1, map2)
1941
2028
  assert_type map1, :Map, :map1
1942
2029
  assert_type map2, :Map, :map2
1943
- map(to_h(map1).merge(to_h(map2)))
2030
+ map(map1.to_h.merge(map2.to_h))
1944
2031
  end
1945
2032
  declare :map_merge, [:map1, :map2]
1946
2033
 
1947
- # Returns a new map with a key removed.
2034
+ # Returns a new map with keys removed.
1948
2035
  #
1949
2036
  # @example
1950
2037
  # map-remove(("foo": 1, "bar": 2), "bar") => ("foo": 1)
2038
+ # map-remove(("foo": 1, "bar": 2, "baz": 3), "bar", "baz") => ("foo": 1)
1951
2039
  # 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]
2040
+ # @overload map_remove($map, $keys...)
2041
+ # @param $map [Sass::Script::Value::Map]
2042
+ # @param $keys [[Sass::Script::Value::Base]]
1955
2043
  # @return [Sass::Script::Value::Map]
1956
2044
  # @raise [ArgumentError] if `$map` is not a map
1957
- def map_remove(map, key)
2045
+ def map_remove(map, *keys)
1958
2046
  assert_type map, :Map, :map
1959
- hash = to_h(map).dup
1960
- hash.delete key
2047
+ hash = map.to_h.dup
2048
+ hash.delete_if {|key, _| keys.include?(key)}
1961
2049
  map(hash)
1962
2050
  end
1963
- declare :map_remove, [:map, :key]
2051
+ declare :map_remove, [:map, :key], :var_args => true
1964
2052
 
1965
2053
  # Returns a list of all keys in a map.
1966
2054
  #
1967
2055
  # @example
1968
2056
  # map-keys(("foo": 1, "bar": 2)) => "foo", "bar"
1969
2057
  # @overload map_keys($map)
1970
- # @param $map [Map]
2058
+ # @param $map [Map]
1971
2059
  # @return [List] the list of keys, comma-separated
1972
2060
  # @raise [ArgumentError] if `$map` is not a map
1973
2061
  def map_keys(map)
1974
2062
  assert_type map, :Map, :map
1975
- list(to_h(map).keys, :comma)
2063
+ list(map.to_h.keys, :comma)
1976
2064
  end
1977
2065
  declare :map_keys, [:map]
1978
2066
 
@@ -1983,12 +2071,12 @@ module Sass::Script
1983
2071
  # map-values(("foo": 1, "bar": 2)) => 1, 2
1984
2072
  # map-values(("foo": 1, "bar": 2, "baz": 1)) => 1, 2, 1
1985
2073
  # @overload map_values($map)
1986
- # @param $map [Map]
2074
+ # @param $map [Map]
1987
2075
  # @return [List] the list of values, comma-separated
1988
2076
  # @raise [ArgumentError] if `$map` is not a map
1989
2077
  def map_values(map)
1990
2078
  assert_type map, :Map, :map
1991
- list(to_h(map).values, :comma)
2079
+ list(map.to_h.values, :comma)
1992
2080
  end
1993
2081
  declare :map_values, [:map]
1994
2082
 
@@ -1998,13 +2086,13 @@ module Sass::Script
1998
2086
  # map-has-key(("foo": 1, "bar": 2), "foo") => true
1999
2087
  # map-has-key(("foo": 1, "bar": 2), "baz") => false
2000
2088
  # @overload map_has_key($map, $key)
2001
- # @param $map [Sass::Script::Value::Map]
2002
- # @param $key [Sass::Script::Value::Base]
2089
+ # @param $map [Sass::Script::Value::Map]
2090
+ # @param $key [Sass::Script::Value::Base]
2003
2091
  # @return [Sass::Script::Value::Bool]
2004
2092
  # @raise [ArgumentError] if `$map` is not a map
2005
2093
  def map_has_key(map, key)
2006
2094
  assert_type map, :Map, :map
2007
- bool(to_h(map).has_key?(key))
2095
+ bool(map.to_h.has_key?(key))
2008
2096
  end
2009
2097
  declare :map_has_key, [:map, :key]
2010
2098
 
@@ -2019,12 +2107,12 @@ module Sass::Script
2019
2107
  #
2020
2108
  # @include foo($arg1: val, $arg2: val);
2021
2109
  # @overload keywords($args)
2022
- # @param $args [Sass::Script::Value::ArgList]
2110
+ # @param $args [Sass::Script::Value::ArgList]
2023
2111
  # @return [Sass::Script::Value::Map]
2024
2112
  # @raise [ArgumentError] if `$args` isn't a variable argument list
2025
2113
  def keywords(args)
2026
2114
  assert_type args, :ArgList, :args
2027
- map(Sass::Util.map_keys(args.keywords.as_stored) {|k| Sass::Script::String.new(k)})
2115
+ map(Sass::Util.map_keys(args.keywords.as_stored) {|k| Sass::Script::Value::String.new(k)})
2028
2116
  end
2029
2117
  declare :keywords, [:args]
2030
2118
 
@@ -2036,10 +2124,10 @@ module Sass::Script
2036
2124
  # if(true, 1px, 2px) => 1px
2037
2125
  # if(false, 1px, 2px) => 2px
2038
2126
  # @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]
2127
+ # @param $condition [Sass::Script::Value::Base] Whether the `$if-true` or
2128
+ # `$if-false` will be returned
2129
+ # @param $if-true [Sass::Script::Tree::Node]
2130
+ # @param $if-false [Sass::Script::Tree::Node]
2043
2131
  # @return [Sass::Script::Value::Base] `$if-true` or `$if-false`
2044
2132
  def if(condition, if_true, if_false)
2045
2133
  if condition.to_bool
@@ -2076,10 +2164,10 @@ module Sass::Script
2076
2164
  # call(scale-color, #0a64ff, $lightness: -10%) => #0058ef
2077
2165
  #
2078
2166
  # $fn: nth;
2079
- # call($fn, 2, (a b c)) => b
2167
+ # call($fn, (a b c), 2) => b
2080
2168
  #
2081
2169
  # @overload call($name, $args...)
2082
- # @param $name [String] The name of the function to call.
2170
+ # @param $name [String] The name of the function to call.
2083
2171
  def call(name, *args)
2084
2172
  assert_type name, :String, :name
2085
2173
  kwargs = args.last.is_a?(Hash) ? args.pop : {}
@@ -2094,31 +2182,29 @@ module Sass::Script
2094
2182
  end
2095
2183
  declare :call, [:name], :var_args => true, :var_kwargs => true
2096
2184
 
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
2185
+ # This function only exists as a workaround for IE7's [`content:
2186
+ # counter` bug](http://jes.st/2013/ie7s-css-breaking-content-counter-bug/).
2187
+ # It works identically to any other plain-CSS function, except it
2099
2188
  # avoids adding spaces between the argument commas.
2100
2189
  #
2101
- # [bug]: http://jes.st/2013/ie7s-css-breaking-content-counter-bug/
2102
- #
2103
2190
  # @example
2104
2191
  # counter(item, ".") => counter(item,".")
2105
2192
  # @overload counter($args...)
2106
- # @return [String]
2193
+ # @return [Sass::Script::Value::String]
2107
2194
  def counter(*args)
2108
2195
  identifier("counter(#{args.map {|a| a.to_s(options)}.join(',')})")
2109
2196
  end
2110
2197
  declare :counter, [], :var_args => true
2111
2198
 
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
2199
+ # This function only exists as a workaround for IE7's [`content:
2200
+ # counter` bug](http://jes.st/2013/ie7s-css-breaking-content-counter-bug/).
2201
+ # It works identically to any other plain-CSS function, except it
2114
2202
  # avoids adding spaces between the argument commas.
2115
2203
  #
2116
- # [bug]: http://jes.st/2013/ie7s-css-breaking-content-counter-bug/
2117
- #
2118
2204
  # @example
2119
2205
  # counters(item, ".") => counters(item,".")
2120
2206
  # @overload counters($args...)
2121
- # @return [String]
2207
+ # @return [Sass::Script::Value::String]
2122
2208
  def counters(*args)
2123
2209
  identifier("counters(#{args.map {|a| a.to_s(options)}.join(',')})")
2124
2210
  end
@@ -2132,9 +2218,11 @@ module Sass::Script
2132
2218
  # variable-exists(a-false-value) => true
2133
2219
  #
2134
2220
  # 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
2221
+ #
2222
+ # @overload variable_exists($name)
2223
+ # @param $name [Sass::Script::Value::String] The name of the variable to
2224
+ # check. The name should not include the `$`.
2225
+ # @return [Sass::Script::Value::Bool] Whether the variable is defined in
2138
2226
  # the current scope.
2139
2227
  def variable_exists(name)
2140
2228
  assert_type name, :String, :name
@@ -2153,9 +2241,11 @@ module Sass::Script
2153
2241
  # $some-var: false;
2154
2242
  # @if global-variable-exists(some-var) { /* false, doesn't run */ }
2155
2243
  # }
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
2244
+ #
2245
+ # @overload global_variable_exists($name)
2246
+ # @param $name [Sass::Script::Value::String] The name of the variable to
2247
+ # check. The name should not include the `$`.
2248
+ # @return [Sass::Script::Value::Bool] Whether the variable is defined in
2159
2249
  # the global scope.
2160
2250
  def global_variable_exists(name)
2161
2251
  assert_type name, :String, :name
@@ -2170,9 +2260,11 @@ module Sass::Script
2170
2260
  #
2171
2261
  # @function myfunc { @return "something"; }
2172
2262
  # 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.
2263
+ #
2264
+ # @overload function_exists($name)
2265
+ # @param name [Sass::Script::Value::String] The name of the function to
2266
+ # check.
2267
+ # @return [Sass::Script::Value::Bool] Whether the function is defined.
2176
2268
  def function_exists(name)
2177
2269
  assert_type name, :String, :name
2178
2270
  exists = Sass::Script::Functions.callable?(name.value.tr("-", "_"))
@@ -2188,9 +2280,11 @@ module Sass::Script
2188
2280
  #
2189
2281
  # @mixin red-text { color: red; }
2190
2282
  # 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.
2283
+ #
2284
+ # @overload mixin_exists($name)
2285
+ # @param name [Sass::Script::Value::String] The name of the mixin to
2286
+ # check.
2287
+ # @return [Sass::Script::Value::Bool] Whether the mixin is defined.
2194
2288
  def mixin_exists(name)
2195
2289
  assert_type name, :String, :name
2196
2290
  bool(environment.mixin(name.value))
@@ -2199,8 +2293,9 @@ module Sass::Script
2199
2293
 
2200
2294
  # Return a string containing the value as its Sass representation.
2201
2295
  #
2202
- # @param value [Sass::Script::Value::Base] The value to inspect.
2203
- # @return [Sass::Script::Value::String] A respresentation of the value as
2296
+ # @overload inspect($value)
2297
+ # @param $value [Sass::Script::Value::Base] The value to inspect.
2298
+ # @return [Sass::Script::Value::String] A representation of the value as
2204
2299
  # it would be written in Sass.
2205
2300
  def inspect(value)
2206
2301
  unquoted_string(value.to_sass)
@@ -2209,12 +2304,12 @@ module Sass::Script
2209
2304
 
2210
2305
  # @overload random()
2211
2306
  # Return a decimal between 0 and 1, inclusive of 0 but not 1.
2212
- # @return [Sass::Script::Number] A decimal value.
2307
+ # @return [Sass::Script::Value::Number] A decimal value.
2213
2308
  # @overload random($limit)
2214
2309
  # Return an integer between 1 and `$limit`, inclusive of 1 but not `$limit`.
2215
2310
  # @param $limit [Sass::Script::Value::Number] The maximum of the random integer to be
2216
2311
  # returned, a positive integer.
2217
- # @return [Sass::Script::Number] An integer.
2312
+ # @return [Sass::Script::Value::Number] An integer.
2218
2313
  # @raise [ArgumentError] if the `$limit` is not 1 or greater
2219
2314
  def random(limit = nil)
2220
2315
  generator = Sass::Script::Functions.random_number_generator
@@ -2231,6 +2326,281 @@ module Sass::Script
2231
2326
  declare :random, []
2232
2327
  declare :random, [:limit]
2233
2328
 
2329
+ # Parses a user-provided selector into a list of lists of strings
2330
+ # as returned by `&`.
2331
+ #
2332
+ # @example
2333
+ # selector-parse(".foo .bar, .baz .bang") => ('.foo' '.bar', '.baz' '.bang')
2334
+ #
2335
+ # @overload selector_parse($selector)
2336
+ # @param $selector [Sass::Script::Value::String, Sass::Script::Value::List]
2337
+ # The selector to parse. This can be either a string, a list of
2338
+ # strings, or a list of lists of strings as returned by `&`.
2339
+ # @return [Sass::Script::Value::List]
2340
+ # A list of lists of strings representing `$selector`. This is
2341
+ # in the same format as a selector returned by `&`.
2342
+ def selector_parse(selector)
2343
+ parse_selector(selector, :selector).to_sass_script
2344
+ end
2345
+ declare :selector_parse, [:selector]
2346
+
2347
+ # Return a new selector with all selectors in `$selectors` nested beneath
2348
+ # one another as though they had been nested in the stylesheet as
2349
+ # `$selector1 { $selector2 { ... } }`.
2350
+ #
2351
+ # Unlike most selector functions, `selector-nest` allows the
2352
+ # parent selector `&` to be used in any selector but the first.
2353
+ #
2354
+ # @example
2355
+ # selector-nest(".foo", ".bar", ".baz") => .foo .bar .baz
2356
+ # selector-nest(".a .foo", ".b .bar") => .a .foo .b .bar
2357
+ # selector-nest(".foo", "&.bar") => .foo.bar
2358
+ #
2359
+ # @overload selector_nest($selectors...)
2360
+ # @param $selectors [[Sass::Script::Value::String, Sass::Script::Value::List]]
2361
+ # The selectors to nest. At least one selector must be passed. Each of
2362
+ # these can be either a string, a list of strings, or a list of lists of
2363
+ # strings as returned by `&`.
2364
+ # @return [Sass::Script::Value::List]
2365
+ # A list of lists of strings representing the result of nesting
2366
+ # `$selectors`. This is in the same format as a selector returned by
2367
+ # `&`.
2368
+ def selector_nest(*selectors)
2369
+ if selectors.empty?
2370
+ raise ArgumentError.new("$selectors: At least one selector must be passed")
2371
+ end
2372
+
2373
+ parsed = [parse_selector(selectors.first, :selectors)]
2374
+ parsed += selectors[1..-1].map {|sel| parse_selector(sel, :selectors, !!:parse_parent_ref)}
2375
+ parsed.inject {|result, child| child.resolve_parent_refs(result)}.to_sass_script
2376
+ end
2377
+ declare :selector_nest, [], :var_args => true
2378
+
2379
+ # Return a new selector with all selectors in `$selectors` appended one
2380
+ # another as though they had been nested in the stylesheet as `$selector1 {
2381
+ # &$selector2 { ... } }`.
2382
+ #
2383
+ # @example
2384
+ # selector-append(".foo", ".bar", ".baz") => .foo.bar.baz
2385
+ # selector-append(".a .foo", ".b .bar") => "a .foo.b .bar"
2386
+ # selector-append(".foo", "-suffix") => ".foo-suffix"
2387
+ #
2388
+ # @overload selector_append($selectors...)
2389
+ # @param $selectors [[Sass::Script::Value::String, Sass::Script::Value::List]]
2390
+ # The selectors to append. At least one selector must be passed. Each of
2391
+ # these can be either a string, a list of strings, or a list of lists of
2392
+ # strings as returned by `&`.
2393
+ # @return [Sass::Script::Value::List]
2394
+ # A list of lists of strings representing the result of appending
2395
+ # `$selectors`. This is in the same format as a selector returned by
2396
+ # `&`.
2397
+ # @raise [ArgumentError] if a selector could not be appended.
2398
+ def selector_append(*selectors)
2399
+ if selectors.empty?
2400
+ raise ArgumentError.new("$selectors: At least one selector must be passed")
2401
+ end
2402
+
2403
+ selectors.map {|sel| parse_selector(sel, :selectors)}.inject do |parent, child|
2404
+ child.members.each do |seq|
2405
+ sseq = seq.members.first
2406
+ unless sseq.is_a?(Sass::Selector::SimpleSequence)
2407
+ raise ArgumentError.new("Can't append \"#{seq}\" to \"#{parent}\"")
2408
+ end
2409
+
2410
+ base = sseq.base
2411
+ case base
2412
+ when Sass::Selector::Universal
2413
+ raise ArgumentError.new("Can't append \"#{seq}\" to \"#{parent}\"")
2414
+ when Sass::Selector::Element
2415
+ unless base.namespace.nil?
2416
+ raise ArgumentError.new("Can't append \"#{seq}\" to \"#{parent}\"")
2417
+ end
2418
+ sseq.members[0] = Sass::Selector::Parent.new(base.name)
2419
+ else
2420
+ sseq.members.unshift Sass::Selector::Parent.new
2421
+ end
2422
+ end
2423
+ child.resolve_parent_refs(parent)
2424
+ end.to_sass_script
2425
+ end
2426
+ declare :selector_append, [], :var_args => true
2427
+
2428
+ # Returns a new version of `$selector` with `$extendee` extended
2429
+ # with `$extender`. This works just like the result of
2430
+ #
2431
+ # $selector { ... }
2432
+ # $extender { @extend $extendee }
2433
+ #
2434
+ # @example
2435
+ # selector-extend(".a .b", ".b", ".foo .bar") => .a .b, .a .foo .bar, .foo .a .bar
2436
+ #
2437
+ # @overload selector_extend($selector, $extendee, $extender)
2438
+ # @param $selector [Sass::Script::Value::String, Sass::Script::Value::List]
2439
+ # The selector within which `$extendee` is extended with
2440
+ # `$extender`. This can be either a string, a list of strings,
2441
+ # or a list of lists of strings as returned by `&`.
2442
+ # @param $extendee [Sass::Script::Value::String, Sass::Script::Value::List]
2443
+ # The selector being extended. This can be either a string, a
2444
+ # list of strings, or a list of lists of strings as returned
2445
+ # by `&`.
2446
+ # @param $extender [Sass::Script::Value::String, Sass::Script::Value::List]
2447
+ # The selector being injected into `$selector`. This can be
2448
+ # either a string, a list of strings, or a list of lists of
2449
+ # strings as returned by `&`.
2450
+ # @return [Sass::Script::Value::List]
2451
+ # A list of lists of strings representing the result of the
2452
+ # extension. This is in the same format as a selector returned
2453
+ # by `&`.
2454
+ # @raise [ArgumentError] if the extension fails
2455
+ def selector_extend(selector, extendee, extender)
2456
+ selector = parse_selector(selector, :selector)
2457
+ extendee = parse_selector(extendee, :extendee)
2458
+ extender = parse_selector(extender, :extender)
2459
+
2460
+ extends = Sass::Util::SubsetMap.new
2461
+ begin
2462
+ extender.populate_extends(extends, extendee)
2463
+ selector.do_extend(extends).to_sass_script
2464
+ rescue Sass::SyntaxError => e
2465
+ raise ArgumentError.new(e.to_s)
2466
+ end
2467
+ end
2468
+ declare :selector_extend, [:selector, :extendee, :extender]
2469
+
2470
+ # Replaces all instances of `$original` with `$replacement` in `$selector`
2471
+ #
2472
+ # This works by using `@extend` and throwing away the original
2473
+ # selector. This means that it can be used to do very advanced
2474
+ # replacements; see the examples below.
2475
+ #
2476
+ # @example
2477
+ # selector-replace(".foo .bar", ".bar", ".baz") => ".foo .baz"
2478
+ # selector-replace(".foo.bar.baz", ".foo.baz", ".qux") => ".bar.qux"
2479
+ #
2480
+ # @overload selector_replace($selector, $original, $replacement)
2481
+ # @param $selector [Sass::Script::Value::String, Sass::Script::Value::List]
2482
+ # The selector within which `$original` is replaced with
2483
+ # `$replacement`. This can be either a string, a list of
2484
+ # strings, or a list of lists of strings as returned by `&`.
2485
+ # @param $original [Sass::Script::Value::String, Sass::Script::Value::List]
2486
+ # The selector being replaced. This can be either a string, a
2487
+ # list of strings, or a list of lists of strings as returned
2488
+ # by `&`.
2489
+ # @param $replacement [Sass::Script::Value::String, Sass::Script::Value::List]
2490
+ # The selector that `$original` is being replaced with. This
2491
+ # can be either a string, a list of strings, or a list of
2492
+ # lists of strings as returned by `&`.
2493
+ # @return [Sass::Script::Value::List]
2494
+ # A list of lists of strings representing the result of the
2495
+ # extension. This is in the same format as a selector returned
2496
+ # by `&`.
2497
+ # @raise [ArgumentError] if the replacement fails
2498
+ def selector_replace(selector, original, replacement)
2499
+ selector = parse_selector(selector, :selector)
2500
+ original = parse_selector(original, :original)
2501
+ replacement = parse_selector(replacement, :replacement)
2502
+
2503
+ extends = Sass::Util::SubsetMap.new
2504
+ begin
2505
+ replacement.populate_extends(extends, original)
2506
+ selector.do_extend(extends, [], !!:replace).to_sass_script
2507
+ rescue Sass::SyntaxError => e
2508
+ raise ArgumentError.new(e.to_s)
2509
+ end
2510
+ end
2511
+ declare :selector_replace, [:selector, :original, :replacement]
2512
+
2513
+ # Unifies two selectors into a single selector that matches only
2514
+ # elements matched by both input selectors. Returns `null` if
2515
+ # there is no such selector.
2516
+ #
2517
+ # Like the selector unification done for `@extend`, this doesn't
2518
+ # guarantee that the output selector will match *all* elements
2519
+ # matched by both input selectors. For example, if `.a .b` is
2520
+ # unified with `.x .y`, `.a .x .b.y, .x .a .b.y` will be returned,
2521
+ # but `.a.x .b.y` will not. This avoids exponential output size
2522
+ # while matching all elements that are likely to exist in
2523
+ # practice.
2524
+ #
2525
+ # @example
2526
+ # selector-unify(".a", ".b") => .a.b
2527
+ # selector-unify(".a .b", ".x .y") => .a .x .b.y, .x .a .b.y
2528
+ # selector-unify(".a.b", ".b.c") => .a.b.c
2529
+ # selector-unify("#a", "#b") => null
2530
+ #
2531
+ # @overload selector_unify($selector1, $selector2)
2532
+ # @param $selector1 [Sass::Script::Value::String, Sass::Script::Value::List]
2533
+ # The first selector to be unified. This can be either a
2534
+ # string, a list of strings, or a list of lists of strings as
2535
+ # returned by `&`.
2536
+ # @param $selector2 [Sass::Script::Value::String, Sass::Script::Value::List]
2537
+ # The second selector to be unified. This can be either a
2538
+ # string, a list of strings, or a list of lists of strings as
2539
+ # returned by `&`.
2540
+ # @return [Sass::Script::Value::List, Sass::Script::Value::Null]
2541
+ # A list of lists of strings representing the result of the
2542
+ # unification, or null if no unification exists. This is in
2543
+ # the same format as a selector returned by `&`.
2544
+ def selector_unify(selector1, selector2)
2545
+ selector1 = parse_selector(selector1, :selector1)
2546
+ selector2 = parse_selector(selector2, :selector2)
2547
+ return null unless (unified = selector1.unify(selector2))
2548
+ unified.to_sass_script
2549
+ end
2550
+ declare :selector_unify, [:selector1, :selector2]
2551
+
2552
+ # Returns the [simple
2553
+ # selectors](http://dev.w3.org/csswg/selectors4/#simple) that
2554
+ # comprise the compound selector `$selector`.
2555
+ #
2556
+ # Note that `$selector` **must be** a [compound
2557
+ # selector](http://dev.w3.org/csswg/selectors4/#compound). That
2558
+ # means it cannot contain commas or spaces. It also means that
2559
+ # unlike other selector functions, this takes only strings, not
2560
+ # lists.
2561
+ #
2562
+ # @example
2563
+ # simple-selectors(".foo.bar") => ".foo", ".bar"
2564
+ # simple-selectors(".foo.bar.baz") => ".foo", ".bar", ".baz"
2565
+ #
2566
+ # @overload simple_selectors($selector)
2567
+ # @param $selector [Sass::Script::Value::String]
2568
+ # The compound selector whose simple selectors will be extracted.
2569
+ # @return [Sass::Script::Value::List]
2570
+ # A list of simple selectors in the compound selector.
2571
+ def simple_selectors(selector)
2572
+ selector = parse_compound_selector(selector, :selector)
2573
+ list(selector.members.map {|simple| unquoted_string(simple.to_s)}, :comma)
2574
+ end
2575
+ declare :simple_selectors, [:selector]
2576
+
2577
+ # Returns whether `$super` is a superselector of `$sub`. This means that
2578
+ # `$super` matches all the elements that `$sub` matches, as well as possibly
2579
+ # additional elements. In general, simpler selectors tend to be
2580
+ # superselectors of more complex oned.
2581
+ #
2582
+ # @example
2583
+ # is-superselector(".foo", ".foo.bar") => true
2584
+ # is-superselector(".foo.bar", ".foo") => false
2585
+ # is-superselector(".bar", ".foo .bar") => true
2586
+ # is-superselector(".foo .bar", ".bar") => false
2587
+ #
2588
+ # @overload is_superselector($super, $sub)
2589
+ # @param $super [Sass::Script::Value::String, Sass::Script::Value::List]
2590
+ # The potential superselector. This can be either a string, a list of
2591
+ # strings, or a list of lists of strings as returned by `&`.
2592
+ # @param $sub [Sass::Script::Value::String, Sass::Script::Value::List]
2593
+ # The potential subselector. This can be either a string, a list of
2594
+ # strings, or a list of lists of strings as returned by `&`.
2595
+ # @return [Sass::Script::Value::Bool]
2596
+ # Whether `$selector1` is a superselector of `$selector2`.
2597
+ def is_superselector(sup, sub)
2598
+ sup = parse_selector(sup, :super)
2599
+ sub = parse_selector(sub, :sub)
2600
+ bool(sup.superselector?(sub))
2601
+ end
2602
+ declare :is_superselector, [:super, :sub]
2603
+
2234
2604
  private
2235
2605
 
2236
2606
  # This method implements the pattern of transforming a numeric value into
@@ -2250,23 +2620,7 @@ module Sass::Script
2250
2620
  assert_type amount, :Number, :amount
2251
2621
  Sass::Util.check_range('Amount', range, amount, units)
2252
2622
 
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))
2258
- end
2259
-
2260
- def to_h(obj)
2261
- return obj.to_h unless obj.is_a?(Sass::Script::Value::List) && obj.needs_map_warning?
2262
-
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.
2268
- WARNING
2269
- obj.to_h
2623
+ color.with(attr => color.send(attr).send(op, amount.value))
2270
2624
  end
2271
2625
  end
2272
2626
  end