sass 3.1.0 → 3.3.0

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 (260) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING +1 -1
  3. data/MIT-LICENSE +2 -2
  4. data/README.md +29 -17
  5. data/Rakefile +43 -9
  6. data/VERSION +1 -1
  7. data/VERSION_DATE +1 -0
  8. data/VERSION_NAME +1 -1
  9. data/bin/sass +6 -1
  10. data/bin/sass-convert +6 -1
  11. data/bin/scss +6 -1
  12. data/ext/mkrf_conf.rb +27 -0
  13. data/lib/sass/cache_stores/base.rb +7 -3
  14. data/lib/sass/cache_stores/chain.rb +3 -2
  15. data/lib/sass/cache_stores/filesystem.rb +5 -7
  16. data/lib/sass/cache_stores/memory.rb +1 -1
  17. data/lib/sass/cache_stores/null.rb +2 -2
  18. data/lib/sass/callbacks.rb +2 -1
  19. data/lib/sass/css.rb +168 -53
  20. data/lib/sass/engine.rb +502 -174
  21. data/lib/sass/environment.rb +151 -111
  22. data/lib/sass/error.rb +7 -7
  23. data/lib/sass/exec.rb +176 -60
  24. data/lib/sass/features.rb +40 -0
  25. data/lib/sass/importers/base.rb +46 -7
  26. data/lib/sass/importers/deprecated_path.rb +51 -0
  27. data/lib/sass/importers/filesystem.rb +113 -30
  28. data/lib/sass/importers.rb +1 -0
  29. data/lib/sass/logger/base.rb +30 -0
  30. data/lib/sass/logger/log_level.rb +45 -0
  31. data/lib/sass/logger.rb +12 -0
  32. data/lib/sass/media.rb +213 -0
  33. data/lib/sass/plugin/compiler.rb +194 -104
  34. data/lib/sass/plugin/configuration.rb +18 -25
  35. data/lib/sass/plugin/merb.rb +1 -1
  36. data/lib/sass/plugin/staleness_checker.rb +37 -11
  37. data/lib/sass/plugin.rb +10 -13
  38. data/lib/sass/railtie.rb +2 -1
  39. data/lib/sass/repl.rb +5 -6
  40. data/lib/sass/script/css_lexer.rb +8 -4
  41. data/lib/sass/script/css_parser.rb +5 -2
  42. data/lib/sass/script/functions.rb +1547 -618
  43. data/lib/sass/script/lexer.rb +122 -72
  44. data/lib/sass/script/parser.rb +304 -135
  45. data/lib/sass/script/tree/funcall.rb +306 -0
  46. data/lib/sass/script/{interpolation.rb → tree/interpolation.rb} +43 -13
  47. data/lib/sass/script/tree/list_literal.rb +77 -0
  48. data/lib/sass/script/tree/literal.rb +45 -0
  49. data/lib/sass/script/tree/map_literal.rb +64 -0
  50. data/lib/sass/script/{node.rb → tree/node.rb} +30 -12
  51. data/lib/sass/script/{operation.rb → tree/operation.rb} +33 -21
  52. data/lib/sass/script/{string_interpolation.rb → tree/string_interpolation.rb} +14 -4
  53. data/lib/sass/script/{unary_operation.rb → tree/unary_operation.rb} +21 -9
  54. data/lib/sass/script/tree/variable.rb +57 -0
  55. data/lib/sass/script/tree.rb +15 -0
  56. data/lib/sass/script/value/arg_list.rb +36 -0
  57. data/lib/sass/script/value/base.rb +238 -0
  58. data/lib/sass/script/value/bool.rb +40 -0
  59. data/lib/sass/script/{color.rb → value/color.rb} +256 -74
  60. data/lib/sass/script/value/deprecated_false.rb +55 -0
  61. data/lib/sass/script/value/helpers.rb +155 -0
  62. data/lib/sass/script/value/list.rb +128 -0
  63. data/lib/sass/script/value/map.rb +70 -0
  64. data/lib/sass/script/value/null.rb +49 -0
  65. data/lib/sass/script/{number.rb → value/number.rb} +115 -62
  66. data/lib/sass/script/{string.rb → value/string.rb} +9 -11
  67. data/lib/sass/script/value.rb +12 -0
  68. data/lib/sass/script.rb +35 -9
  69. data/lib/sass/scss/css_parser.rb +2 -12
  70. data/lib/sass/scss/parser.rb +657 -230
  71. data/lib/sass/scss/rx.rb +17 -12
  72. data/lib/sass/scss/static_parser.rb +37 -6
  73. data/lib/sass/scss.rb +0 -1
  74. data/lib/sass/selector/abstract_sequence.rb +35 -3
  75. data/lib/sass/selector/comma_sequence.rb +29 -14
  76. data/lib/sass/selector/sequence.rb +371 -74
  77. data/lib/sass/selector/simple.rb +28 -13
  78. data/lib/sass/selector/simple_sequence.rb +163 -36
  79. data/lib/sass/selector.rb +138 -36
  80. data/lib/sass/shared.rb +3 -5
  81. data/lib/sass/source/map.rb +196 -0
  82. data/lib/sass/source/position.rb +39 -0
  83. data/lib/sass/source/range.rb +41 -0
  84. data/lib/sass/stack.rb +126 -0
  85. data/lib/sass/supports.rb +228 -0
  86. data/lib/sass/tree/at_root_node.rb +82 -0
  87. data/lib/sass/tree/comment_node.rb +34 -29
  88. data/lib/sass/tree/content_node.rb +9 -0
  89. data/lib/sass/tree/css_import_node.rb +60 -0
  90. data/lib/sass/tree/debug_node.rb +3 -3
  91. data/lib/sass/tree/directive_node.rb +33 -3
  92. data/lib/sass/tree/each_node.rb +9 -9
  93. data/lib/sass/tree/extend_node.rb +20 -6
  94. data/lib/sass/tree/for_node.rb +6 -6
  95. data/lib/sass/tree/function_node.rb +12 -4
  96. data/lib/sass/tree/if_node.rb +2 -15
  97. data/lib/sass/tree/import_node.rb +11 -5
  98. data/lib/sass/tree/media_node.rb +27 -11
  99. data/lib/sass/tree/mixin_def_node.rb +15 -4
  100. data/lib/sass/tree/mixin_node.rb +27 -7
  101. data/lib/sass/tree/node.rb +69 -35
  102. data/lib/sass/tree/prop_node.rb +47 -31
  103. data/lib/sass/tree/return_node.rb +4 -3
  104. data/lib/sass/tree/root_node.rb +20 -4
  105. data/lib/sass/tree/rule_node.rb +37 -26
  106. data/lib/sass/tree/supports_node.rb +38 -0
  107. data/lib/sass/tree/trace_node.rb +33 -0
  108. data/lib/sass/tree/variable_node.rb +10 -4
  109. data/lib/sass/tree/visitors/base.rb +5 -8
  110. data/lib/sass/tree/visitors/check_nesting.rb +67 -52
  111. data/lib/sass/tree/visitors/convert.rb +134 -53
  112. data/lib/sass/tree/visitors/cssize.rb +245 -51
  113. data/lib/sass/tree/visitors/deep_copy.rb +102 -0
  114. data/lib/sass/tree/visitors/extend.rb +68 -0
  115. data/lib/sass/tree/visitors/perform.rb +331 -105
  116. data/lib/sass/tree/visitors/set_options.rb +125 -0
  117. data/lib/sass/tree/visitors/to_css.rb +259 -95
  118. data/lib/sass/tree/warn_node.rb +3 -3
  119. data/lib/sass/tree/while_node.rb +3 -3
  120. data/lib/sass/util/cross_platform_random.rb +19 -0
  121. data/lib/sass/util/multibyte_string_scanner.rb +157 -0
  122. data/lib/sass/util/normalized_map.rb +130 -0
  123. data/lib/sass/util/ordered_hash.rb +192 -0
  124. data/lib/sass/util/subset_map.rb +11 -2
  125. data/lib/sass/util/test.rb +9 -0
  126. data/lib/sass/util.rb +565 -39
  127. data/lib/sass/version.rb +27 -15
  128. data/lib/sass.rb +39 -4
  129. data/test/sass/cache_test.rb +15 -0
  130. data/test/sass/compiler_test.rb +223 -0
  131. data/test/sass/conversion_test.rb +901 -107
  132. data/test/sass/css2sass_test.rb +94 -0
  133. data/test/sass/engine_test.rb +1059 -164
  134. data/test/sass/exec_test.rb +86 -0
  135. data/test/sass/extend_test.rb +933 -837
  136. data/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
  137. data/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
  138. data/test/sass/functions_test.rb +995 -136
  139. data/test/sass/importer_test.rb +338 -18
  140. data/test/sass/logger_test.rb +58 -0
  141. data/test/sass/more_results/more_import.css +2 -2
  142. data/test/sass/plugin_test.rb +114 -30
  143. data/test/sass/results/cached_import_option.css +3 -0
  144. data/test/sass/results/filename_fn.css +3 -0
  145. data/test/sass/results/import.css +2 -2
  146. data/test/sass/results/import_charset.css +1 -0
  147. data/test/sass/results/import_charset_1_8.css +1 -0
  148. data/test/sass/results/import_charset_ibm866.css +1 -0
  149. data/test/sass/results/import_content.css +1 -0
  150. data/test/sass/results/script.css +1 -1
  151. data/test/sass/results/scss_import.css +2 -2
  152. data/test/sass/results/units.css +2 -2
  153. data/test/sass/script_conversion_test.rb +43 -1
  154. data/test/sass/script_test.rb +380 -36
  155. data/test/sass/scss/css_test.rb +257 -75
  156. data/test/sass/scss/scss_test.rb +2322 -110
  157. data/test/sass/source_map_test.rb +887 -0
  158. data/test/sass/templates/_cached_import_option_partial.scss +1 -0
  159. data/test/sass/templates/_double_import_loop2.sass +1 -0
  160. data/test/sass/templates/_filename_fn_import.scss +11 -0
  161. data/test/sass/templates/_imported_content.sass +3 -0
  162. data/test/sass/templates/_same_name_different_partiality.scss +1 -0
  163. data/test/sass/templates/bork5.sass +3 -0
  164. data/test/sass/templates/cached_import_option.scss +3 -0
  165. data/test/sass/templates/double_import_loop1.sass +1 -0
  166. data/test/sass/templates/filename_fn.scss +18 -0
  167. data/test/sass/templates/import_charset.sass +2 -0
  168. data/test/sass/templates/import_charset_1_8.sass +2 -0
  169. data/test/sass/templates/import_charset_ibm866.sass +2 -0
  170. data/test/sass/templates/import_content.sass +4 -0
  171. data/test/sass/templates/same_name_different_ext.sass +2 -0
  172. data/test/sass/templates/same_name_different_ext.scss +1 -0
  173. data/test/sass/templates/same_name_different_partiality.scss +1 -0
  174. data/test/sass/templates/single_import_loop.sass +1 -0
  175. data/test/sass/templates/subdir/import_up1.scss +1 -0
  176. data/test/sass/templates/subdir/import_up2.scss +1 -0
  177. data/test/sass/test_helper.rb +1 -1
  178. data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
  179. data/test/sass/util/normalized_map_test.rb +51 -0
  180. data/test/sass/util_test.rb +183 -0
  181. data/test/sass/value_helpers_test.rb +181 -0
  182. data/test/test_helper.rb +45 -5
  183. data/vendor/listen/CHANGELOG.md +228 -0
  184. data/vendor/listen/CONTRIBUTING.md +38 -0
  185. data/vendor/listen/Gemfile +30 -0
  186. data/vendor/listen/Guardfile +8 -0
  187. data/vendor/{fssm → listen}/LICENSE +1 -1
  188. data/vendor/listen/README.md +315 -0
  189. data/vendor/listen/Rakefile +47 -0
  190. data/vendor/listen/Vagrantfile +96 -0
  191. data/vendor/listen/lib/listen/adapter.rb +214 -0
  192. data/vendor/listen/lib/listen/adapters/bsd.rb +112 -0
  193. data/vendor/listen/lib/listen/adapters/darwin.rb +85 -0
  194. data/vendor/listen/lib/listen/adapters/linux.rb +113 -0
  195. data/vendor/listen/lib/listen/adapters/polling.rb +67 -0
  196. data/vendor/listen/lib/listen/adapters/windows.rb +87 -0
  197. data/vendor/listen/lib/listen/dependency_manager.rb +126 -0
  198. data/vendor/listen/lib/listen/directory_record.rb +371 -0
  199. data/vendor/listen/lib/listen/listener.rb +225 -0
  200. data/vendor/listen/lib/listen/multi_listener.rb +143 -0
  201. data/vendor/listen/lib/listen/turnstile.rb +28 -0
  202. data/vendor/listen/lib/listen/version.rb +3 -0
  203. data/vendor/listen/lib/listen.rb +40 -0
  204. data/vendor/listen/listen.gemspec +22 -0
  205. data/vendor/listen/spec/listen/adapter_spec.rb +183 -0
  206. data/vendor/listen/spec/listen/adapters/bsd_spec.rb +36 -0
  207. data/vendor/listen/spec/listen/adapters/darwin_spec.rb +37 -0
  208. data/vendor/listen/spec/listen/adapters/linux_spec.rb +47 -0
  209. data/vendor/listen/spec/listen/adapters/polling_spec.rb +68 -0
  210. data/vendor/listen/spec/listen/adapters/windows_spec.rb +30 -0
  211. data/vendor/listen/spec/listen/dependency_manager_spec.rb +107 -0
  212. data/vendor/listen/spec/listen/directory_record_spec.rb +1225 -0
  213. data/vendor/listen/spec/listen/listener_spec.rb +169 -0
  214. data/vendor/listen/spec/listen/multi_listener_spec.rb +174 -0
  215. data/vendor/listen/spec/listen/turnstile_spec.rb +56 -0
  216. data/vendor/listen/spec/listen_spec.rb +73 -0
  217. data/vendor/listen/spec/spec_helper.rb +21 -0
  218. data/vendor/listen/spec/support/adapter_helper.rb +629 -0
  219. data/vendor/listen/spec/support/directory_record_helper.rb +55 -0
  220. data/vendor/listen/spec/support/fixtures_helper.rb +29 -0
  221. data/vendor/listen/spec/support/listeners_helper.rb +156 -0
  222. data/vendor/listen/spec/support/platform_helper.rb +15 -0
  223. metadata +344 -271
  224. data/lib/sass/less.rb +0 -382
  225. data/lib/sass/script/bool.rb +0 -18
  226. data/lib/sass/script/funcall.rb +0 -162
  227. data/lib/sass/script/list.rb +0 -76
  228. data/lib/sass/script/literal.rb +0 -245
  229. data/lib/sass/script/variable.rb +0 -54
  230. data/lib/sass/scss/sass_parser.rb +0 -11
  231. data/test/sass/less_conversion_test.rb +0 -653
  232. data/vendor/fssm/README.markdown +0 -55
  233. data/vendor/fssm/Rakefile +0 -59
  234. data/vendor/fssm/VERSION.yml +0 -5
  235. data/vendor/fssm/example.rb +0 -9
  236. data/vendor/fssm/fssm.gemspec +0 -77
  237. data/vendor/fssm/lib/fssm/backends/fsevents.rb +0 -36
  238. data/vendor/fssm/lib/fssm/backends/inotify.rb +0 -26
  239. data/vendor/fssm/lib/fssm/backends/polling.rb +0 -25
  240. data/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +0 -131
  241. data/vendor/fssm/lib/fssm/monitor.rb +0 -26
  242. data/vendor/fssm/lib/fssm/path.rb +0 -91
  243. data/vendor/fssm/lib/fssm/pathname.rb +0 -502
  244. data/vendor/fssm/lib/fssm/state/directory.rb +0 -57
  245. data/vendor/fssm/lib/fssm/state/file.rb +0 -24
  246. data/vendor/fssm/lib/fssm/support.rb +0 -63
  247. data/vendor/fssm/lib/fssm/tree.rb +0 -176
  248. data/vendor/fssm/lib/fssm.rb +0 -33
  249. data/vendor/fssm/profile/prof-cache.rb +0 -40
  250. data/vendor/fssm/profile/prof-fssm-pathname.html +0 -1231
  251. data/vendor/fssm/profile/prof-pathname.rb +0 -68
  252. data/vendor/fssm/profile/prof-plain-pathname.html +0 -988
  253. data/vendor/fssm/profile/prof.html +0 -2379
  254. data/vendor/fssm/spec/path_spec.rb +0 -75
  255. data/vendor/fssm/spec/root/duck/quack.txt +0 -0
  256. data/vendor/fssm/spec/root/file.css +0 -0
  257. data/vendor/fssm/spec/root/file.rb +0 -0
  258. data/vendor/fssm/spec/root/file.yml +0 -0
  259. data/vendor/fssm/spec/root/moo/cow.txt +0 -0
  260. data/vendor/fssm/spec/spec_helper.rb +0 -14
@@ -1,10 +1,12 @@
1
+ require 'sass/script/value/helpers'
2
+
1
3
  module Sass::Script
2
4
  # Methods in this module are accessible from the SassScript context.
3
5
  # For example, you can write
4
6
  #
5
- # $color = hsl(120deg, 100%, 50%)
7
+ # $color: hsl(120deg, 100%, 50%)
6
8
  #
7
- # and it will call {Sass::Script::Functions#hsl}.
9
+ # and it will call {Functions#hsl}.
8
10
  #
9
11
  # The following functions are provided:
10
12
  #
@@ -13,13 +15,12 @@ module Sass::Script
13
15
  # ## RGB Functions
14
16
  #
15
17
  # \{#rgb rgb($red, $green, $blue)}
16
- # : Converts an `rgb(red, green, blue)` triplet into a color.
18
+ # : Creates a {Sass::Script::Value::Color Color} from red, green, and blue
19
+ # values.
17
20
  #
18
21
  # \{#rgba rgba($red, $green, $blue, $alpha)}
19
- # : Converts an `rgba(red, green, blue, alpha)` quadruplet into a color.
20
- #
21
- # \{#rgba rgba($color, $alpha)}
22
- # : Adds an alpha layer to any color value.
22
+ # : Creates a {Sass::Script::Value::Color Color} from red, green, blue, and
23
+ # alpha values.
23
24
  #
24
25
  # \{#red red($color)}
25
26
  # : Gets the red component of a color.
@@ -30,16 +31,18 @@ module Sass::Script
30
31
  # \{#blue blue($color)}
31
32
  # : Gets the blue component of a color.
32
33
  #
33
- # \{#mix mix($color-1, $color-2, \[$weight\])}
34
+ # \{#mix mix($color1, $color2, \[$weight\])}
34
35
  # : Mixes two colors together.
35
36
  #
36
37
  # ## HSL Functions
37
38
  #
38
39
  # \{#hsl hsl($hue, $saturation, $lightness)}
39
- # : Converts an `hsl(hue, saturation, lightness)` triplet into a color.
40
+ # : Creates a {Sass::Script::Value::Color Color} from hue, saturation, and
41
+ # lightness values.
40
42
  #
41
43
  # \{#hsla hsla($hue, $saturation, $lightness, $alpha)}
42
- # : Converts an `hsla(hue, saturation, lightness, alpha)` quadruplet into a color.
44
+ # : Creates a {Sass::Script::Value::Color Color} from hue, saturation,
45
+ # lightness, and alpha values.
43
46
  #
44
47
  # \{#hue hue($color)}
45
48
  # : Gets the hue component of a color.
@@ -80,7 +83,7 @@ module Sass::Script
80
83
  # : Gets the alpha component (opacity) of a color.
81
84
  #
82
85
  # \{#rgba rgba($color, $alpha)}
83
- # : Add or change an alpha layer for any color value.
86
+ # : Changes the alpha component for a color.
84
87
  #
85
88
  # \{#opacify opacify($color, $amount)} / \{#fade_in fade-in($color, $amount)}
86
89
  # : Makes a color more opaque.
@@ -90,42 +93,77 @@ module Sass::Script
90
93
  #
91
94
  # ## Other Color Functions
92
95
  #
93
- # \{#adjust_color adjust-color($color, \[$red\], \[$green\], \[$blue\], \[$hue\], \[$saturation\], \[$lightness\], \[$alpha\]}
94
- # : Increase or decrease any of the components of a color.
96
+ # \{#adjust_color adjust-color($color, \[$red\], \[$green\], \[$blue\],
97
+ # \[$hue\], \[$saturation\], \[$lightness\], \[$alpha\])}
98
+ # : Increases or decreases one or more components of a color.
95
99
  #
96
- # \{#scale_color scale-color($color, \[$red\], \[$green\], \[$blue\], \[$hue\], \[$saturation\], \[$lightness\], \[$alpha\]}
97
- # : Fluidly scale one or more components of a color.
100
+ # \{#scale_color scale-color($color, \[$red\], \[$green\], \[$blue\],
101
+ # \[$saturation\], \[$lightness\], \[$alpha\])}
102
+ # : Fluidly scales one or more properties of a color.
98
103
  #
99
- # \{#change_color change-color($color, \[$red\], \[$green\], \[$blue\], \[$hue\], \[$saturation\], \[$lightness\], \[$alpha\]}
104
+ # \{#change_color change-color($color, \[$red\], \[$green\], \[$blue\],
105
+ # \[$hue\], \[$saturation\], \[$lightness\], \[$alpha\])}
100
106
  # : Changes one or more properties of a color.
101
107
  #
108
+ # \{#ie_hex_str ie-hex-str($color)}
109
+ # : Converts a color into the format understood by IE filters.
110
+ #
102
111
  # ## String Functions
103
112
  #
104
113
  # \{#unquote unquote($string)}
105
- # : Removes the quotes from a string.
114
+ # : Removes quotes from a string.
106
115
  #
107
116
  # \{#quote quote($string)}
108
117
  # : Adds quotes to a string.
109
118
  #
119
+ # \{#str_length str-length($string)}
120
+ # : Returns the number of characters in a string.
121
+ #
122
+ # \{#str_insert str-insert($string, $insert, $index)}
123
+ # : Inserts `$insert` into `$string` at `$index`.
124
+ #
125
+ # \{#str_index str-index($string, $substring)}
126
+ # : Returns the index of the first occurance of `$substring` in `$string`.
127
+ #
128
+ # \{#str_slice str-slice($string, $start-at, [$end-at])}
129
+ # : Extracts a substring from `$string`.
130
+ #
131
+ # \{#to_upper_case to-upper-case($string)}
132
+ # : Converts a string to upper case.
133
+ #
134
+ # \{#to_lower_case to-lower-case($string)}
135
+ # : Converts a string to lower case.
136
+ #
110
137
  # ## Number Functions
111
138
  #
112
- # \{#percentage percentage($value)}
139
+ # \{#percentage percentage($number)}
113
140
  # : Converts a unitless number to a percentage.
114
141
  #
115
- # \{#round round($value)}
142
+ # \{#round round($number)}
116
143
  # : Rounds a number to the nearest whole number.
117
144
  #
118
- # \{#ceil ceil($value)}
119
- # : Rounds a number up to the nearest whole number.
145
+ # \{#ceil ceil($number)}
146
+ # : Rounds a number up to the next whole number.
120
147
  #
121
- # \{#floor floor($value)}
122
- # : Rounds a number down to the nearest whole number.
148
+ # \{#floor floor($number)}
149
+ # : Rounds a number down to the previous whole number.
123
150
  #
124
- # \{#abs abs($value)}
151
+ # \{#abs abs($number)}
125
152
  # : Returns the absolute value of a number.
126
153
  #
154
+ # \{#min min($numbers...)\}
155
+ # : Finds the minimum of several numbers.
156
+ #
157
+ # \{#max max($numbers...)\}
158
+ # : Finds the maximum of several numbers.
159
+ #
160
+ # \{#random random([$limit])\}
161
+ # : Returns a random number.
162
+ #
127
163
  # ## List Functions {#list-functions}
128
164
  #
165
+ # All list functions work for maps as well, treating them as lists of pairs.
166
+ #
129
167
  # \{#length length($list)}
130
168
  # : Returns the length of a list.
131
169
  #
@@ -135,24 +173,84 @@ module Sass::Script
135
173
  # \{#join join($list1, $list2, \[$separator\])}
136
174
  # : Joins together two lists into one.
137
175
  #
176
+ # \{#append append($list1, $val, \[$separator\])}
177
+ # : Appends a single value onto the end of a list.
178
+ #
179
+ # \{#zip zip($lists...)}
180
+ # : Combines several lists into a single multidimensional list.
181
+ #
182
+ # \{#index index($list, $value)}
183
+ # : Returns the position of a value within a list.
184
+ #
185
+ # \{#list_separator list-separator(#list)}
186
+ # : Returns the separator of a list.
187
+ #
188
+ # ## Map Functions {#map-functions}
189
+ #
190
+ # \{#map_get map-get($map, $key)}
191
+ # : Returns the value in a map associated with a given key.
192
+ #
193
+ # \{#map_merge map-merge($map1, $map2)}
194
+ # : Merges two maps together into a new map.
195
+ #
196
+ # \{#map_remove map-remove($map, $key)}
197
+ # : Returns a new map with a key removed.
198
+ #
199
+ # \{#map_keys map-keys($map)}
200
+ # : Returns a list of all keys in a map.
201
+ #
202
+ # \{#map_values map-values($map)}
203
+ # : Returns a list of all values in a map.
204
+ #
205
+ # \{#map_has_key map-has-key($key)}
206
+ # : Returns whether a map has a value associated with a given key.
207
+ #
208
+ # \{#keywords keywords($args)}
209
+ # : Returns the keywords passed to a function that takes variable arguments.
210
+ #
138
211
  # ## Introspection Functions
139
212
  #
213
+ # \{#feature_exists feature-exists($feature)}
214
+ # : Returns whether a feature exists in the current Sass runtime.
215
+ #
216
+ # \{#variable_exists variable-exists($name)}
217
+ # : Returns whether a variable with the given name exists in the current scope.
218
+ #
219
+ # \{#global_variable_exists global-variable-exists($name)}
220
+ # : Returns whether a variable with the given name exists in the global scope.
221
+ #
222
+ # \{#function_exists function-exists($name)}
223
+ # : Returns whether a function with the given name exists.
224
+ #
225
+ # \{#mixin_exists mixin-exists($name)}
226
+ # : Returns whether a mixin with the given name exists.
227
+ #
228
+ # \{#inspect inspect($value)}
229
+ # : Returns the string representation of a value as it would be represented in Sass.
230
+ #
140
231
  # \{#type_of type-of($value)}
141
232
  # : Returns the type of a value.
142
233
  #
143
234
  # \{#unit unit($number)}
144
- # : Returns the units associated with a number.
235
+ # : Returns the unit(s) associated with a number.
145
236
  #
146
237
  # \{#unitless unitless($number)}
147
- # : Returns whether a number has units or not.
238
+ # : Returns whether a number has units.
239
+ #
240
+ # \{#comparable comparable($number1, $number2)}
241
+ # : Returns whether two numbers can be added, subtracted, or compared.
148
242
  #
149
- # \{#comparable comparable($number-1, $number-2)}
150
- # : Returns whether two numbers can be added or compared.
243
+ # \{#call call($name, $args...)}
244
+ # : Dynamically calls a Sass function.
151
245
  #
152
246
  # ## Miscellaneous Functions
153
247
  #
154
248
  # \{#if if($condition, $if-true, $if-false)}
155
- # : Returns one of two values, depending on whether or not a condition is true.
249
+ # : Returns one of two values, depending on whether or not `$condition` is
250
+ # true.
251
+ #
252
+ # \{#unique_id unique-id()}
253
+ # : Returns a unique CSS identifier.
156
254
  #
157
255
  # ## Adding Custom Functions
158
256
  #
@@ -162,9 +260,9 @@ module Sass::Script
162
260
  # module Sass::Script::Functions
163
261
  # def reverse(string)
164
262
  # assert_type string, :String
165
- # Sass::Script::String.new(string.value.reverse)
263
+ # Sass::Script::Value::String.new(string.value.reverse)
166
264
  # end
167
- # declare :reverse, :args => [:string]
265
+ # declare :reverse, [:string]
168
266
  # end
169
267
  #
170
268
  # Calling {declare} tells Sass the argument names for your function.
@@ -172,14 +270,15 @@ module Sass::Script
172
270
  # {declare} can also allow your function to take arbitrary keyword arguments.
173
271
  #
174
272
  # There are a few things to keep in mind when modifying this module.
175
- # First of all, the arguments passed are {Sass::Script::Literal} objects.
176
- # Literal objects are also expected to be returned.
273
+ # First of all, the arguments passed are {Value} objects.
274
+ # Value objects are also expected to be returned.
177
275
  # This means that Ruby values must be unwrapped and wrapped.
178
276
  #
179
- # Most Literal objects support the {Sass::Script::Literal#value value} accessor
180
- # for getting their Ruby values.
181
- # Color objects, though, must be accessed using {Sass::Script::Color#rgb rgb},
182
- # {Sass::Script::Color#red red}, {Sass::Script::Color#blue green}, or {Sass::Script::Color#blue blue}.
277
+ # Most Value objects support the {Value::Base#value value} accessor for getting
278
+ # their Ruby values. Color objects, though, must be accessed using
279
+ # {Sass::Script::Value::Color#rgb rgb}, {Sass::Script::Value::Color#red red},
280
+ # {Sass::Script::Value::Color#blue green}, or {Sass::Script::Value::Color#blue
281
+ # blue}.
183
282
  #
184
283
  # Second, making Ruby functions accessible from Sass introduces the temptation
185
284
  # to do things like database access within stylesheets.
@@ -199,19 +298,21 @@ module Sass::Script
199
298
  #
200
299
  # ### Caveats
201
300
  #
202
- # When creating new {Literal} objects within functions,
203
- # be aware that it's not safe to call {Literal#to_s #to_s}
204
- # (or other methods that use the string representation)
205
- # on those objects without first setting {Node#options= the #options attribute}.
301
+ # When creating new {Value} objects within functions, be aware that it's not
302
+ # safe to call {Value::Base#to_s #to_s} (or other methods that use the string
303
+ # representation) on those objects without first setting {Tree::Node#options=
304
+ # the #options attribute}.
206
305
  module Functions
207
306
  @signatures = {}
208
307
 
209
308
  # A class representing a Sass function signature.
210
309
  #
211
- # @attr args [Array<Symbol>] The names of the arguments to the function.
310
+ # @attr args [Array<String>] The names of the arguments to the function.
311
+ # @attr delayed_args [Array<String>] The names of the arguments whose evaluation should be
312
+ # delayed.
212
313
  # @attr var_args [Boolean] Whether the function takes a variable number of arguments.
213
314
  # @attr var_kwargs [Boolean] Whether the function takes an arbitrary set of keyword arguments.
214
- Signature = Struct.new(:args, :var_args, :var_kwargs)
315
+ Signature = Struct.new(:args, :delayed_args, :var_args, :var_kwargs, :deprecated)
215
316
 
216
317
  # Declare a Sass signature for a Ruby-defined function.
217
318
  # This includes the names of the arguments,
@@ -228,6 +329,12 @@ module Sass::Script
228
329
  # but none of them but the first will be used
229
330
  # unless the user uses keyword arguments.
230
331
  #
332
+ # @example
333
+ # declare :rgba, [:hex, :alpha]
334
+ # declare :rgba, [:red, :green, :blue, :alpha]
335
+ # declare :accepts_anything, [], :var_args => true, :var_kwargs => true
336
+ # declare :some_func, [:foo, :bar, :baz], :var_kwargs => true
337
+ #
231
338
  # @param method_name [Symbol] The name of the method
232
339
  # whose signature is being declared.
233
340
  # @param args [Array<Symbol>] The names of the arguments for the function signature.
@@ -238,21 +345,30 @@ module Sass::Script
238
345
  # Whether the function accepts other keyword arguments
239
346
  # in addition to those in `:args`.
240
347
  # If this is true, the Ruby function will be passed a hash from strings
241
- # to {Sass::Script::Literal}s as the last argument.
348
+ # to {Value}s as the last argument.
242
349
  # In addition, if this is true and `:var_args` is not,
243
350
  # Sass will ensure that the last argument passed is a hash.
244
- #
245
- # @example
246
- # declare :rgba, [:hex, :alpha]
247
- # declare :rgba, [:red, :green, :blue, :alpha]
248
- # declare :accepts_anything, [], :var_args => true, :var_kwargs => true
249
- # declare :some_func, [:foo, :bar, :baz], :var_kwargs => true
250
351
  def self.declare(method_name, args, options = {})
352
+ delayed_args = []
353
+ args = args.map do |a|
354
+ a = a.to_s
355
+ if a[0] == ?&
356
+ a = a[1..-1]
357
+ delayed_args << a
358
+ end
359
+ a
360
+ end
361
+ # We don't expose this functionality except to certain builtin methods.
362
+ if delayed_args.any? && method_name != :if
363
+ raise ArgumentError.new("Delayed arguments are not allowed for method #{method_name}")
364
+ end
251
365
  @signatures[method_name] ||= []
252
366
  @signatures[method_name] << Signature.new(
253
- args.map {|s| s.to_s},
367
+ args,
368
+ delayed_args,
254
369
  options[:var_args],
255
- options[:var_kwargs])
370
+ options[:var_kwargs],
371
+ options[:deprecated] && options[:deprecated].map {|a| a.to_s})
256
372
  end
257
373
 
258
374
  # Determine the correct signature for the number of arguments
@@ -260,8 +376,8 @@ module Sass::Script
260
376
  # If no signatures match, the first signature is returned for error messaging.
261
377
  #
262
378
  # @param method_name [Symbol] The name of the Ruby function to be called.
263
- # @param arg_arity [Number] The number of unnamed arguments the function was passed.
264
- # @param kwarg_arity [Number] The number of keyword arguments the function was passed.
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.
265
381
  #
266
382
  # @return [{Symbol => Object}, nil]
267
383
  # The signature options for the matching signature,
@@ -269,42 +385,76 @@ module Sass::Script
269
385
  def self.signature(method_name, arg_arity, kwarg_arity)
270
386
  return unless @signatures[method_name]
271
387
  @signatures[method_name].each do |signature|
272
- return signature if signature.args.size == arg_arity + kwarg_arity
273
- next unless signature.args.size < arg_arity + kwarg_arity
388
+ sig_arity = signature.args.size
389
+ return signature if sig_arity == arg_arity + kwarg_arity
390
+ next unless sig_arity < arg_arity + kwarg_arity
274
391
 
275
392
  # We have enough args.
276
393
  # Now we need to figure out which args are varargs
277
394
  # and if the signature allows them.
278
395
  t_arg_arity, t_kwarg_arity = arg_arity, kwarg_arity
279
- if signature.args.size > t_arg_arity
396
+ if sig_arity > t_arg_arity
280
397
  # we transfer some kwargs arity to args arity
281
398
  # if it does not have enough args -- assuming the names will work out.
282
- t_kwarg_arity -= (signature.args.size - t_arg_arity)
283
- t_arg_arity = signature.args.size
399
+ t_kwarg_arity -= (sig_arity - t_arg_arity)
400
+ t_arg_arity = sig_arity
284
401
  end
285
402
 
286
- if ( t_arg_arity == signature.args.size || t_arg_arity > signature.args.size && signature.var_args ) &&
287
- (t_kwarg_arity == 0 || t_kwarg_arity > 0 && signature.var_kwargs)
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)
288
405
  return signature
289
406
  end
290
407
  end
291
408
  @signatures[method_name].first
292
409
  end
293
410
 
411
+ # Sets the random seed used by Sass's internal random number generator.
412
+ #
413
+ # This can be used to ensure consistent random number sequences which
414
+ # allows for consistent results when testing, etc.
415
+ #
416
+ # @param seed [Integer]
417
+ # @return [Integer] The same seed.
418
+ def self.random_seed=(seed)
419
+ @random_number_generator = Sass::Util::CrossPlatformRandom.new(seed)
420
+ end
421
+
422
+ # Get Sass's internal random number generator.
423
+ #
424
+ # @return [Random]
425
+ def self.random_number_generator
426
+ @random_number_generator ||= Sass::Util::CrossPlatformRandom.new
427
+ end
428
+
294
429
  # The context in which methods in {Script::Functions} are evaluated.
295
430
  # That means that all instance methods of {EvaluationContext}
296
431
  # are available to use in functions.
297
432
  class EvaluationContext
298
433
  include Functions
434
+ include Value::Helpers
435
+
436
+ # 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.
439
+ TYPE_NAMES = {:ArgList => 'variable argument list'}
440
+
441
+ # The environment for this function. This environment's
442
+ # {Environment#parent} is the global environment, and its
443
+ # {Environment#caller} is a read-only view of the local environment of the
444
+ # caller of this function.
445
+ #
446
+ # @return [Environment]
447
+ attr_reader :environment
299
448
 
300
449
  # The options hash for the {Sass::Engine} that is processing the function call
301
450
  #
302
451
  # @return [{Symbol => Object}]
303
452
  attr_reader :options
304
453
 
305
- # @param options [{Symbol => Object}] See \{#options}
306
- def initialize(options)
307
- @options = options
454
+ # @param environment [Environment] See \{#environment}
455
+ def initialize(environment)
456
+ @environment = environment
457
+ @options = environment.options
308
458
  end
309
459
 
310
460
  # Asserts that the type of a given SassScript value
@@ -317,15 +467,79 @@ module Sass::Script
317
467
  # @example
318
468
  # assert_type value, :String
319
469
  # assert_type value, :Number
320
- # @param value [Sass::Script::Literal] A SassScript value
470
+ # @param value [Sass::Script::Value::Base] A SassScript value
321
471
  # @param type [Symbol] The name of the type the value is expected to be
322
- # @param name [String, nil] The name of the argument.
472
+ # @param name [String, Symbol, nil] The name of the argument.
473
+ # @raise [ArgumentError] if value is not of the correct type.
323
474
  def assert_type(value, type, name = nil)
324
- return if value.is_a?(Sass::Script.const_get(type))
325
- err = "#{value.inspect} is not a #{type.to_s.downcase}"
326
- err = "$#{name}: " + err if name
475
+ 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?
478
+ err = "#{value.inspect} is not a #{TYPE_NAMES[type] || type.to_s.downcase}"
479
+ err = "$#{name.to_s.gsub('_', '-')}: " + err if name
327
480
  raise ArgumentError.new(err)
328
481
  end
482
+
483
+ # Asserts that the unit of the number is as expected.
484
+ #
485
+ # @example
486
+ # assert_unit number, "px"
487
+ # assert_unit number, nil
488
+ # @param number [Sass::Script::Value::Number] The number to be validated.
489
+ # @param unit [::String]
490
+ # The unit that the number must have.
491
+ # If nil, the number must be unitless.
492
+ # @param name [::String] The name of the parameter being validated.
493
+ # @raise [ArgumentError] if number is not of the correct unit or is not a number.
494
+ def assert_unit(number, unit, name = nil)
495
+ assert_type number, :Number, name
496
+ return if number.is_unit?(unit)
497
+ expectation = unit ? "have a unit of #{unit}" : "be unitless"
498
+ if name
499
+ raise ArgumentError.new("Expected $#{name} to #{expectation} but got #{number}")
500
+ else
501
+ raise ArgumentError.new("Expected #{number} to #{expectation}")
502
+ end
503
+ end
504
+
505
+ # Asserts that the value is an integer.
506
+ #
507
+ # @example
508
+ # assert_integer 2px
509
+ # assert_integer 2.5px
510
+ # => SyntaxError: "Expected 2.5px to be an integer"
511
+ # assert_integer 2.5px, "width"
512
+ # => SyntaxError: "Expected width to be an integer but got 2.5px"
513
+ # @param number [Sass::Script::Value::Base] The value to be validated.
514
+ # @param name [::String] The name of the parameter being validated.
515
+ # @raise [ArgumentError] if number is not an integer or is not a number.
516
+ def assert_integer(number, name = nil)
517
+ assert_type number, :Number, name
518
+ return if number.int?
519
+ if name
520
+ raise ArgumentError.new("Expected $#{name} to be an integer but got #{number}")
521
+ else
522
+ raise ArgumentError.new("Expected #{number} to be an integer")
523
+ end
524
+ end
525
+
526
+ # Performs a node that has been delayed for execution.
527
+ #
528
+ # @private
529
+ # @param node [Sass::Script::Tree::Node,
530
+ # Sass::Script::Value::Base] When this is a tree node, it's
531
+ # performed in the caller's environment. When it's a value
532
+ # (which can happen when the value had to be performed already
533
+ # -- like for a splat), it's returned as-is.
534
+ # @param env [Sass::Environment] The environment within which to perform the node.
535
+ # Defaults to the (read-only) environment of the caller.
536
+ def perform(node, env = environment.caller)
537
+ if node.is_a?(Sass::Script::Value::Base)
538
+ node
539
+ else
540
+ node.perform(env)
541
+ end
542
+ end
329
543
  end
330
544
 
331
545
  class << self
@@ -336,6 +550,7 @@ module Sass::Script
336
550
  alias_method :callable?, :public_method_defined?
337
551
 
338
552
  private
553
+
339
554
  def include(*args)
340
555
  r = super
341
556
  # We have to re-include ourselves into EvaluationContext to work around
@@ -345,75 +560,81 @@ module Sass::Script
345
560
  end
346
561
  end
347
562
 
348
- # Creates a {Color} object from red, green, and blue values.
563
+ # Creates a {Sass::Script::Value::Color Color} object from red, green, and
564
+ # blue values.
349
565
  #
350
- # @param red [Number]
351
- # A number between 0 and 255 inclusive,
352
- # or between 0% and 100% inclusive
353
- # @param green [Number]
354
- # A number between 0 and 255 inclusive,
355
- # or between 0% and 100% inclusive
356
- # @param blue [Number]
357
- # A number between 0 and 255 inclusive,
358
- # or between 0% and 100% inclusive
359
566
  # @see #rgba
360
- # @return [Color]
567
+ # @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
577
+ # @return [Sass::Script::Value::Color]
578
+ # @raise [ArgumentError] if any parameter is the wrong type or out of bounds
361
579
  def rgb(red, green, blue)
362
- assert_type red, :Number
363
- assert_type green, :Number
364
- assert_type blue, :Number
365
-
366
- Color.new([red, green, blue].map do |c|
367
- v = c.value
368
- if c.numerator_units == ["%"] && c.denominator_units.empty?
369
- next v * 255 / 100.0 if (0..100).include?(v)
370
- raise ArgumentError.new("Color value #{c} must be between 0% and 100% inclusive")
371
- else
372
- next v if (0..255).include?(v)
373
- raise ArgumentError.new("Color value #{v} must be between 0 and 255 inclusive")
374
- end
375
- end)
580
+ assert_type red, :Number, :red
581
+ assert_type green, :Number, :green
582
+ assert_type blue, :Number, :blue
583
+
584
+ color_attrs = [[red, :red], [green, :green], [blue, :blue]].map do |(c, name)|
585
+ if c.is_unit?("%")
586
+ v = Sass::Util.check_range("$#{name}: Color value", 0..100, c, '%')
587
+ v * 255 / 100.0
588
+ elsif c.unitless?
589
+ Sass::Util.check_range("$#{name}: Color value", 0..255, c)
590
+ else
591
+ raise ArgumentError.new("Expected #{c} to be unitless or have a unit of % but got #{c}")
592
+ end
593
+ end
594
+ Sass::Script::Value::Color.new(color_attrs)
376
595
  end
377
596
  declare :rgb, [:red, :green, :blue]
378
597
 
598
+ # Creates a {Sass::Script::Value::Color Color} from red, green, blue, and
599
+ # alpha values.
379
600
  # @see #rgb
380
- # @overload rgba(red, green, blue, alpha)
381
- # Creates a {Color} object from red, green, and blue values,
382
- # as well as an alpha channel indicating opacity.
383
- #
384
- # @param red [Number]
385
- # A number between 0 and 255 inclusive
386
- # @param green [Number]
387
- # A number between 0 and 255 inclusive
388
- # @param blue [Number]
389
- # A number between 0 and 255 inclusive
390
- # @param alpha [Number]
391
- # A number between 0 and 1
392
- # @return [Color]
393
- #
394
- # @overload rgba(color, alpha)
395
- # Sets the opacity of a color.
601
+ #
602
+ # @overload rgba($red, $green, $blue, $alpha)
603
+ # @param $red [Sass::Script::Value::Number] The amount of red in the
604
+ # color. Must be between 0 and 255 inclusive
605
+ # @param $green [Sass::Script::Value::Number] The amount of green in the
606
+ # color. Must be between 0 and 255 inclusive
607
+ # @param $blue [Sass::Script::Value::Number] The amount of blue in the
608
+ # color. Must be between 0 and 255 inclusive
609
+ # @param $alpha [Sass::Script::Value::Number] The opacity of the color.
610
+ # Must be between 0 and 1 inclusive
611
+ # @return [Sass::Script::Value::Color]
612
+ # @raise [ArgumentError] if any parameter is the wrong type or out of
613
+ # bounds
614
+ #
615
+ # @overload rgba($color, $alpha)
616
+ # Sets the opacity of an existing color.
396
617
  #
397
618
  # @example
398
619
  # rgba(#102030, 0.5) => rgba(16, 32, 48, 0.5)
399
620
  # rgba(blue, 0.2) => rgba(0, 0, 255, 0.2)
400
621
  #
401
- # @param color [Color]
402
- # @param alpha [Number]
403
- # A number between 0 and 1
404
- # @return [Color]
622
+ # @param $color [Sass::Script::Value::Color] The color whose opacity will
623
+ # be changed.
624
+ # @param $alpha [Sass::Script::Value::Number] The new opacity of the
625
+ # color. Must be between 0 and 1 inclusive
626
+ # @return [Sass::Script::Value::Color]
627
+ # @raise [ArgumentError] if `$alpha` is out of bounds or either parameter
628
+ # is the wrong type
405
629
  def rgba(*args)
406
630
  case args.size
407
631
  when 2
408
632
  color, alpha = args
409
633
 
410
- assert_type color, :Color
411
- assert_type alpha, :Number
412
-
413
- unless (0..1).include?(alpha.value)
414
- raise ArgumentError.new("Alpha channel #{alpha.value} must be between 0 and 1 inclusive")
415
- end
634
+ assert_type color, :Color, :color
635
+ assert_type alpha, :Number, :alpha
416
636
 
637
+ Sass::Util.check_range('Alpha channel', 0..1, alpha)
417
638
  color.with(:alpha => alpha.value)
418
639
  when 4
419
640
  red, green, blue, alpha = args
@@ -425,194 +646,221 @@ module Sass::Script
425
646
  declare :rgba, [:red, :green, :blue, :alpha]
426
647
  declare :rgba, [:color, :alpha]
427
648
 
428
- # Creates a {Color} object from hue, saturation, and lightness.
429
- # Uses the algorithm from the [CSS3 spec](http://www.w3.org/TR/css3-color/#hsl-color).
649
+ # Creates a {Sass::Script::Value::Color Color} from hue, saturation, and
650
+ # lightness values. Uses the algorithm from the [CSS3 spec][].
651
+ #
652
+ # [CSS3 spec]: http://www.w3.org/TR/css3-color/#hsl-color
430
653
  #
431
- # @param hue [Number] The hue of the color.
432
- # Should be between 0 and 360 degrees, inclusive
433
- # @param saturation [Number] The saturation of the color.
434
- # Must be between `0%` and `100%`, inclusive
435
- # @param lightness [Number] The lightness of the color.
436
- # Must be between `0%` and `100%`, inclusive
437
- # @return [Color] The resulting color
438
654
  # @see #hsla
439
- # @raise [ArgumentError] if `saturation` or `lightness` are out of bounds
655
+ # @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
662
+ # @return [Sass::Script::Value::Color]
663
+ # @raise [ArgumentError] if `$saturation` or `$lightness` are out of bounds
664
+ # or any parameter is the wrong type
440
665
  def hsl(hue, saturation, lightness)
441
- hsla(hue, saturation, lightness, Number.new(1))
666
+ hsla(hue, saturation, lightness, number(1))
442
667
  end
443
668
  declare :hsl, [:hue, :saturation, :lightness]
444
669
 
445
- # Creates a {Color} object from hue, saturation, and lightness,
446
- # as well as an alpha channel indicating opacity.
447
- # Uses the algorithm from the [CSS3 spec](http://www.w3.org/TR/css3-color/#hsl-color).
448
- #
449
- # @param hue [Number] The hue of the color.
450
- # Should be between 0 and 360 degrees, inclusive
451
- # @param saturation [Number] The saturation of the color.
452
- # Must be between `0%` and `100%`, inclusive
453
- # @param lightness [Number] The lightness of the color.
454
- # Must be between `0%` and `100%`, inclusive
455
- # @param alpha [Number] The opacity of the color.
456
- # Must be between 0 and 1, inclusive
457
- # @return [Color] The resulting color
670
+ # Creates a {Sass::Script::Value::Color Color} from hue,
671
+ # saturation, lightness, and alpha values. Uses the algorithm from
672
+ # the [CSS3 spec][].
673
+ #
674
+ # [CSS3 spec]: http://www.w3.org/TR/css3-color/#hsl-color
675
+ #
458
676
  # @see #hsl
459
- # @raise [ArgumentError] if `saturation`, `lightness`, or `alpha` are out of bounds
677
+ # @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
686
+ # @return [Sass::Script::Value::Color]
687
+ # @raise [ArgumentError] if `$saturation`, `$lightness`, or `$alpha` are out
688
+ # of bounds or any parameter is the wrong type
460
689
  def hsla(hue, saturation, lightness, alpha)
461
- assert_type hue, :Number
462
- assert_type saturation, :Number
463
- assert_type lightness, :Number
464
- assert_type alpha, :Number
690
+ assert_type hue, :Number, :hue
691
+ assert_type saturation, :Number, :saturation
692
+ assert_type lightness, :Number, :lightness
693
+ assert_type alpha, :Number, :alpha
465
694
 
466
- unless (0..1).include?(alpha.value)
467
- raise ArgumentError.new("Alpha channel #{alpha.value} must be between 0 and 1")
468
- end
695
+ Sass::Util.check_range('Alpha channel', 0..1, alpha)
469
696
 
470
- original_s = saturation
471
- original_l = lightness
472
- # This algorithm is from http://www.w3.org/TR/css3-color#hsl-color
473
- h, s, l = [hue, saturation, lightness].map { |a| a.value }
474
- raise ArgumentError.new("Saturation #{s} must be between 0% and 100%") unless (0..100).include?(s)
475
- raise ArgumentError.new("Lightness #{l} must be between 0% and 100%") unless (0..100).include?(l)
697
+ h = hue.value
698
+ s = Sass::Util.check_range('Saturation', 0..100, saturation, '%')
699
+ l = Sass::Util.check_range('Lightness', 0..100, lightness, '%')
476
700
 
477
- Color.new(:hue => h, :saturation => s, :lightness => l, :alpha => alpha.value)
701
+ Sass::Script::Value::Color.new(
702
+ :hue => h, :saturation => s, :lightness => l, :alpha => alpha.value)
478
703
  end
479
704
  declare :hsla, [:hue, :saturation, :lightness, :alpha]
480
705
 
481
- # Returns the red component of a color.
706
+ # Gets the red component of a color. Calculated from HSL where necessary via
707
+ # [this algorithm][hsl-to-rgb].
708
+ #
709
+ # [hsl-to-rgb]: http://www.w3.org/TR/css3-color/#hsl-color
482
710
  #
483
- # @param color [Color]
484
- # @return [Number]
485
- # @raise [ArgumentError] If `color` isn't a color
711
+ # @overload red($color)
712
+ # @param $color [Sass::Script::Value::Color]
713
+ # @return [Sass::Script::Value::Number] The red component, between 0 and 255
714
+ # inclusive
715
+ # @raise [ArgumentError] if `$color` isn't a color
486
716
  def red(color)
487
- assert_type color, :Color
488
- Sass::Script::Number.new(color.red)
717
+ assert_type color, :Color, :color
718
+ number(color.red)
489
719
  end
490
720
  declare :red, [:color]
491
721
 
492
- # Returns the green component of a color.
722
+ # Gets the green component of a color. Calculated from HSL where necessary
723
+ # via [this algorithm][hsl-to-rgb].
493
724
  #
494
- # @param color [Color]
495
- # @return [Number]
496
- # @raise [ArgumentError] If `color` isn't a color
725
+ # [hsl-to-rgb]: http://www.w3.org/TR/css3-color/#hsl-color
726
+ #
727
+ # @overload green($color)
728
+ # @param $color [Sass::Script::Value::Color]
729
+ # @return [Sass::Script::Value::Number] The green component, between 0 and
730
+ # 255 inclusive
731
+ # @raise [ArgumentError] if `$color` isn't a color
497
732
  def green(color)
498
- assert_type color, :Color
499
- Sass::Script::Number.new(color.green)
733
+ assert_type color, :Color, :color
734
+ number(color.green)
500
735
  end
501
736
  declare :green, [:color]
502
737
 
503
- # Returns the blue component of a color.
738
+ # Gets the blue component of a color. Calculated from HSL where necessary
739
+ # via [this algorithm][hsl-to-rgb].
740
+ #
741
+ # [hsl-to-rgb]: http://www.w3.org/TR/css3-color/#hsl-color
504
742
  #
505
- # @param color [Color]
506
- # @return [Number]
507
- # @raise [ArgumentError] If `color` isn't a color
743
+ # @overload blue($color)
744
+ # @param $color [Sass::Script::Value::Color]
745
+ # @return [Sass::Script::Value::Number] The blue component, between 0 and
746
+ # 255 inclusive
747
+ # @raise [ArgumentError] if `$color` isn't a color
508
748
  def blue(color)
509
- assert_type color, :Color
510
- Sass::Script::Number.new(color.blue)
749
+ assert_type color, :Color, :color
750
+ number(color.blue)
511
751
  end
512
752
  declare :blue, [:color]
513
753
 
514
- # Returns the hue component of a color.
515
- #
516
- # See [the CSS3 HSL specification](http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV).
754
+ # Returns the hue component of a color. See [the CSS3 HSL
755
+ # specification][hsl]. Calculated from RGB where necessary via [this
756
+ # algorithm][rgb-to-hsl].
517
757
  #
518
- # Calculated from RGB where necessary via [this algorithm](http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV).
758
+ # [hsl]: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
759
+ # [rgb-to-hsl]: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
519
760
  #
520
- # @param color [Color]
521
- # @return [Number] between 0deg and 360deg
522
- # @see #adjust_hue
523
- # @raise [ArgumentError] if `color` isn't a color
761
+ # @overload hue($color)
762
+ # @param $color [Sass::Script::Value::Color]
763
+ # @return [Sass::Script::Value::Number] The hue component, between 0deg and
764
+ # 360deg
765
+ # @raise [ArgumentError] if `$color` isn't a color
524
766
  def hue(color)
525
- assert_type color, :Color
526
- Sass::Script::Number.new(color.hue, ["deg"])
767
+ assert_type color, :Color, :color
768
+ number(color.hue, "deg")
527
769
  end
528
770
  declare :hue, [:color]
529
771
 
530
- # Returns the saturation component of a color.
772
+ # Returns the saturation component of a color. See [the CSS3 HSL
773
+ # specification][hsl]. Calculated from RGB where necessary via [this
774
+ # algorithm][rgb-to-hsl].
531
775
  #
532
- # See [the CSS3 HSL specification](http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV).
776
+ # [hsl]: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
777
+ # [rgb-to-hsl]: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
533
778
  #
534
- # Calculated from RGB where necessary via [this algorithm](http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV).
535
- #
536
- # @param color [Color]
537
- # @return [Number] between 0% and 100%
538
- # @see #saturate
539
- # @see #desaturate
540
- # @raise [ArgumentError] if `color` isn't a color
779
+ # @overload saturation($color)
780
+ # @param $color [Sass::Script::Value::Color]
781
+ # @return [Sass::Script::Value::Number] The saturation component, between 0%
782
+ # and 100%
783
+ # @raise [ArgumentError] if `$color` isn't a color
541
784
  def saturation(color)
542
- assert_type color, :Color
543
- Sass::Script::Number.new(color.saturation, ["%"])
785
+ assert_type color, :Color, :color
786
+ number(color.saturation, "%")
544
787
  end
545
788
  declare :saturation, [:color]
546
789
 
547
- # Returns the hue component of a color.
548
- #
549
- # See [the CSS3 HSL specification](http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV).
790
+ # Returns the lightness component of a color. See [the CSS3 HSL
791
+ # specification][hsl]. Calculated from RGB where necessary via [this
792
+ # algorithm][rgb-to-hsl].
550
793
  #
551
- # Calculated from RGB where necessary via [this algorithm](http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV).
794
+ # [hsl]: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
795
+ # [rgb-to-hsl]: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
552
796
  #
553
- # @param color [Color]
554
- # @return [Number] between 0% and 100%
555
- # @see #lighten
556
- # @see #darken
557
- # @raise [ArgumentError] if `color` isn't a color
797
+ # @overload lightness($color)
798
+ # @param $color [Sass::Script::Value::Color]
799
+ # @return [Sass::Script::Value::Number] The lightness component, between 0%
800
+ # and 100%
801
+ # @raise [ArgumentError] if `$color` isn't a color
558
802
  def lightness(color)
559
- assert_type color, :Color
560
- Sass::Script::Number.new(color.lightness, ["%"])
803
+ assert_type color, :Color, :color
804
+ number(color.lightness, "%")
561
805
  end
562
806
  declare :lightness, [:color]
563
807
 
564
- # Returns the alpha component (opacity) of a color.
565
- # This is 1 unless otherwise specified.
808
+ # Returns the alpha component (opacity) of a color. This is 1 unless
809
+ # otherwise specified.
566
810
  #
567
- # This function also supports the proprietary Microsoft
568
- # `alpha(opacity=20)` syntax.
811
+ # This function also supports the proprietary Microsoft `alpha(opacity=20)`
812
+ # syntax as a special case.
569
813
  #
570
- # @overload def alpha(color)
571
- # @param color [Color]
572
- # @return [Number]
573
- # @see #opacify
574
- # @see #transparentize
575
- # @raise [ArgumentError] If `color` isn't a color
814
+ # @overload alpha($color)
815
+ # @param $color [Sass::Script::Value::Color]
816
+ # @return [Sass::Script::Value::Number] The alpha component, between 0 and 1
817
+ # @raise [ArgumentError] if `$color` isn't a color
576
818
  def alpha(*args)
577
819
  if args.all? do |a|
578
- a.is_a?(Sass::Script::String) && a.type == :identifier &&
579
- a.value =~ /^[a-zA-Z]+\s*=/
580
- end
820
+ a.is_a?(Sass::Script::Value::String) && a.type == :identifier &&
821
+ a.value =~ /^[a-zA-Z]+\s*=/
822
+ end
581
823
  # Support the proprietary MS alpha() function
582
- return Sass::Script::String.new("alpha(#{args.map {|a| a.to_s}.join(", ")})")
824
+ return identifier("alpha(#{args.map {|a| a.to_s}.join(", ")})")
583
825
  end
584
826
 
585
- opacity(*args)
827
+ raise ArgumentError.new("wrong number of arguments (#{args.size} for 1)") if args.size != 1
828
+
829
+ assert_type args.first, :Color, :color
830
+ number(args.first.alpha)
586
831
  end
587
832
  declare :alpha, [:color]
588
833
 
589
- # Returns the alpha component (opacity) of a color.
590
- # This is 1 unless otherwise specified.
834
+ # Returns the alpha component (opacity) of a color. This is 1 unless
835
+ # otherwise specified.
591
836
  #
592
- # @param color [Color]
593
- # @return [Number]
594
- # @see #opacify
595
- # @see #transparentize
596
- # @raise [ArgumentError] If `color` isn't a color
837
+ # @overload opacity($color)
838
+ # @param $color [Sass::Script::Value::Color]
839
+ # @return [Sass::Script::Value::Number] The alpha component, between 0 and 1
840
+ # @raise [ArgumentError] if `$color` isn't a color
597
841
  def opacity(color)
598
- assert_type color, :Color
599
- Sass::Script::Number.new(color.alpha)
842
+ if color.is_a?(Sass::Script::Value::Number)
843
+ return identifier("opacity(#{color})")
844
+ end
845
+ assert_type color, :Color, :color
846
+ number(color.alpha)
600
847
  end
601
848
  declare :opacity, [:color]
602
849
 
603
- # Makes a color more opaque.
604
- # Takes a color and an amount between 0 and 1,
605
- # and returns a color with the opacity increased by that value.
850
+ # Makes a color more opaque. Takes a color and a number between 0 and 1, and
851
+ # returns a color with the opacity increased by that amount.
606
852
  #
853
+ # @see #transparentize
607
854
  # @example
608
855
  # opacify(rgba(0, 0, 0, 0.5), 0.1) => rgba(0, 0, 0, 0.6)
609
856
  # opacify(rgba(0, 0, 17, 0.8), 0.2) => #001
610
- # @param color [Color]
611
- # @param amount [Number]
612
- # @return [Color]
613
- # @see #transparentize
614
- # @raise [ArgumentError] If `color` isn't a color,
615
- # or `number` isn't a number between 0 and 1
857
+ # @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
861
+ # @return [Sass::Script::Value::Color]
862
+ # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
863
+ # is the wrong type
616
864
  def opacify(color, amount)
617
865
  _adjust(color, amount, :alpha, 0..1, :+)
618
866
  end
@@ -621,19 +869,20 @@ module Sass::Script
621
869
  alias_method :fade_in, :opacify
622
870
  declare :fade_in, [:color, :amount]
623
871
 
624
- # Makes a color more transparent.
625
- # Takes a color and an amount between 0 and 1,
626
- # and returns a color with the opacity decreased by that value.
872
+ # Makes a color more transparent. Takes a color and a number between 0 and
873
+ # 1, and returns a color with the opacity decreased by that amount.
627
874
  #
875
+ # @see #opacify
628
876
  # @example
629
877
  # transparentize(rgba(0, 0, 0, 0.5), 0.1) => rgba(0, 0, 0, 0.4)
630
878
  # transparentize(rgba(0, 0, 0, 0.8), 0.2) => rgba(0, 0, 0, 0.6)
631
- # @param color [Color]
632
- # @param amount [Number]
633
- # @return [Color]
634
- # @see #opacify
635
- # @raise [ArgumentError] If `color` isn't a color,
636
- # or `number` isn't a number between 0 and 1
879
+ # @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
883
+ # @return [Sass::Script::Value::Color]
884
+ # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
885
+ # is the wrong type
637
886
  def transparentize(color, amount)
638
887
  _adjust(color, amount, :alpha, 0..1, :-)
639
888
  end
@@ -642,131 +891,162 @@ module Sass::Script
642
891
  alias_method :fade_out, :transparentize
643
892
  declare :fade_out, [:color, :amount]
644
893
 
645
- # Makes a color lighter.
646
- # Takes a color and an amount between 0% and 100%,
647
- # and returns a color with the lightness increased by that value.
894
+ # Makes a color lighter. Takes a color and a number between `0%` and `100%`,
895
+ # and returns a color with the lightness increased by that amount.
648
896
  #
897
+ # @see #darken
649
898
  # @example
650
899
  # lighten(hsl(0, 0%, 0%), 30%) => hsl(0, 0, 30)
651
900
  # lighten(#800, 20%) => #e00
652
- # @param color [Color]
653
- # @param amount [Number]
654
- # @return [Color]
655
- # @see #darken
656
- # @raise [ArgumentError] If `color` isn't a color,
657
- # or `number` isn't a number between 0% and 100%
901
+ # @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%`
905
+ # @return [Sass::Script::Value::Color]
906
+ # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
907
+ # is the wrong type
658
908
  def lighten(color, amount)
659
909
  _adjust(color, amount, :lightness, 0..100, :+, "%")
660
910
  end
661
911
  declare :lighten, [:color, :amount]
662
912
 
663
- # Makes a color darker.
664
- # Takes a color and an amount between 0% and 100%,
665
- # and returns a color with the lightness decreased by that value.
913
+ # Makes a color darker. Takes a color and a number between 0% and 100%, and
914
+ # returns a color with the lightness decreased by that amount.
666
915
  #
916
+ # @see #lighten
667
917
  # @example
668
918
  # darken(hsl(25, 100%, 80%), 30%) => hsl(25, 100%, 50%)
669
919
  # darken(#800, 20%) => #200
670
- # @param color [Color]
671
- # @param amount [Number]
672
- # @return [Color]
673
- # @see #lighten
674
- # @raise [ArgumentError] If `color` isn't a color,
675
- # or `number` isn't a number between 0% and 100%
920
+ # @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%`
924
+ # @return [Sass::Script::Value::Color]
925
+ # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
926
+ # is the wrong type
676
927
  def darken(color, amount)
677
928
  _adjust(color, amount, :lightness, 0..100, :-, "%")
678
929
  end
679
930
  declare :darken, [:color, :amount]
680
931
 
681
- # Makes a color more saturated.
682
- # Takes a color and an amount between 0% and 100%,
683
- # and returns a color with the saturation increased by that value.
932
+ # Makes a color more saturated. Takes a color and a number between 0% and
933
+ # 100%, and returns a color with the saturation increased by that amount.
684
934
  #
935
+ # @see #desaturate
685
936
  # @example
686
937
  # saturate(hsl(120, 30%, 90%), 20%) => hsl(120, 50%, 90%)
687
938
  # saturate(#855, 20%) => #9e3f3f
688
- # @param color [Color]
689
- # @param amount [Number]
690
- # @return [Color]
691
- # @see #desaturate
692
- # @raise [ArgumentError] If `color` isn't a color,
693
- # or `number` isn't a number between 0% and 100%
694
- def saturate(color, amount)
939
+ # @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%`
943
+ # @return [Sass::Script::Value::Color]
944
+ # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
945
+ # is the wrong type
946
+ def saturate(color, amount = nil)
947
+ # Support the filter effects definition of saturate.
948
+ # https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html
949
+ return identifier("saturate(#{color})") if amount.nil?
695
950
  _adjust(color, amount, :saturation, 0..100, :+, "%")
696
951
  end
697
952
  declare :saturate, [:color, :amount]
953
+ declare :saturate, [:amount]
698
954
 
699
- # Makes a color less saturated.
700
- # Takes a color and an amount between 0% and 100%,
701
- # and returns a color with the saturation decreased by that value.
955
+ # Makes a color less saturated. Takes a color and a number between 0% and
956
+ # 100%, and returns a color with the saturation decreased by that value.
702
957
  #
958
+ # @see #saturate
703
959
  # @example
704
960
  # desaturate(hsl(120, 30%, 90%), 20%) => hsl(120, 10%, 90%)
705
961
  # desaturate(#855, 20%) => #726b6b
706
- # @param color [Color]
707
- # @param amount [Number]
708
- # @return [Color]
709
- # @see #saturate
710
- # @raise [ArgumentError] If `color` isn't a color,
711
- # or `number` isn't a number between 0% and 100%
962
+ # @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%`
966
+ # @return [Sass::Script::Value::Color]
967
+ # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
968
+ # is the wrong type
712
969
  def desaturate(color, amount)
713
970
  _adjust(color, amount, :saturation, 0..100, :-, "%")
714
971
  end
715
972
  declare :desaturate, [:color, :amount]
716
973
 
717
- # Changes the hue of a color while retaining the lightness and saturation.
718
- # Takes a color and a number of degrees (usually between -360deg and 360deg),
719
- # and returns a color with the hue rotated by that value.
974
+ # Changes the hue of a color. Takes a color and a number of degrees (usually
975
+ # between `-360deg` and `360deg`), and returns a color with the hue rotated
976
+ # along the color wheel by that amount.
720
977
  #
721
978
  # @example
722
979
  # adjust-hue(hsl(120, 30%, 90%), 60deg) => hsl(180, 30%, 90%)
723
980
  # adjust-hue(hsl(120, 30%, 90%), 060deg) => hsl(60, 30%, 90%)
724
981
  # adjust-hue(#811, 45deg) => #886a11
725
- # @param color [Color]
726
- # @param amount [Number]
727
- # @return [Color]
728
- # @raise [ArgumentError] If `color` isn't a color, or `number` isn't a number
982
+ # @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
986
+ # @return [Sass::Script::Value::Color]
987
+ # @raise [ArgumentError] if either parameter is the wrong type
729
988
  def adjust_hue(color, degrees)
730
- assert_type color, :Color
731
- assert_type degrees, :Number
989
+ assert_type color, :Color, :color
990
+ assert_type degrees, :Number, :degrees
732
991
  color.with(:hue => color.hue + degrees.value)
733
992
  end
734
993
  declare :adjust_hue, [:color, :degrees]
735
994
 
736
- # Adjusts one or more properties of a color.
737
- # This can change the red, green, blue, hue, saturation, value, and alpha properties.
738
- # The properties are specified as keyword arguments,
739
- # and are added to or subtracted from the color's current value for that property.
995
+ # Converts a color into the format understood by IE filters.
740
996
  #
741
- # `$red`, `$green`, and `$blue` properties should be between 0 and 255.
742
- # `$saturation` and `$lightness` should be between 0% and 100%.
743
- # `$alpha` should be between 0 and 1.
997
+ # @example
998
+ # ie-hex-str(#abc) => #FFAABBCC
999
+ # ie-hex-str(#3322BB) => #FF3322BB
1000
+ # ie-hex-str(rgba(0, 255, 0, 0.5)) => #8000FF00
1001
+ # @overload ie_hex_str($color)
1002
+ # @param $color [Sass::Script::Value::Color]
1003
+ # @return [Sass::Script::Value::String] The IE-formatted string
1004
+ # representation of the color
1005
+ # @raise [ArgumentError] if `$color` isn't a color
1006
+ def ie_hex_str(color)
1007
+ assert_type color, :Color, :color
1008
+ alpha = (color.alpha * 255).round.to_s(16).rjust(2, '0')
1009
+ identifier("##{alpha}#{color.send(:hex_str)[1..-1]}".upcase)
1010
+ end
1011
+ declare :ie_hex_str, [:color]
1012
+
1013
+ # Increases or decreases one or more properties of a color. This can change
1014
+ # the red, green, blue, hue, saturation, value, and alpha properties. The
1015
+ # properties are specified as keyword arguments, and are added to or
1016
+ # subtracted from the color's current value for that property.
744
1017
  #
745
- # All properties are optional.
746
- # You can't specify both RGB properties (`$red`, `$green`, `$blue`)
747
- # and HSL properties (`$hue`, `$saturation`, `$value`) at the same time.
1018
+ # All properties are optional. You can't specify both RGB properties
1019
+ # (`$red`, `$green`, `$blue`) and HSL properties (`$hue`, `$saturation`,
1020
+ # `$value`) at the same time.
748
1021
  #
749
1022
  # @example
750
1023
  # adjust-color(#102030, $blue: 5) => #102035
751
1024
  # adjust-color(#102030, $red: -5, $blue: 5) => #0b2035
752
1025
  # adjust-color(hsl(25, 100%, 80%), $lightness: -30%, $alpha: -0.4) => hsla(25, 100%, 50%, 0.6)
753
- # @param color [Color]
754
- # @param red [Number]
755
- # @param green [Number]
756
- # @param blue [Number]
757
- # @param hue [Number]
758
- # @param saturation [Number]
759
- # @param lightness [Number]
760
- # @param alpha [Number]
761
- # @return [Color]
762
- # @raise [ArgumentError] if `color` is not a color,
763
- # if any keyword argument is not a number,
764
- # if any keyword argument is not in the legal range,
765
- # if an unexpected keyword argument is given,
766
- # or if both HSL and RGB properties are given.
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
1043
+ # @return [Sass::Script::Value::Color]
1044
+ # @raise [ArgumentError] if any parameter is the wrong type or out-of
1045
+ # bounds, or if RGB properties and HSL properties are adjusted at the
1046
+ # same time
767
1047
  def adjust_color(color, kwargs)
768
- assert_type color, :Color
769
- with = Sass::Util.map_hash({
1048
+ assert_type color, :Color, :color
1049
+ with = Sass::Util.map_hash(
770
1050
  "red" => [-255..255, ""],
771
1051
  "green" => [-255..255, ""],
772
1052
  "blue" => [-255..255, ""],
@@ -774,13 +1054,12 @@ module Sass::Script
774
1054
  "saturation" => [-100..100, "%"],
775
1055
  "lightness" => [-100..100, "%"],
776
1056
  "alpha" => [-1..1, ""]
777
- }) do |name, (range, units)|
1057
+ ) do |name, (range, units)|
778
1058
 
779
- next unless val = kwargs.delete(name)
1059
+ val = kwargs.delete(name)
1060
+ next unless val
780
1061
  assert_type val, :Number, name
781
- if range && !range.include?(val.value)
782
- raise ArgumentError.new("$#{name}: Amount #{val} must be between #{range.first}#{units} and #{range.last}#{units}")
783
- end
1062
+ Sass::Util.check_range("$#{name}: Amount", range, val, units) if range
784
1063
  adjusted = color.send(name) + val.value
785
1064
  adjusted = [0, Sass::Util.restrict(adjusted, range)].max if range
786
1065
  [name.to_sym, adjusted]
@@ -795,68 +1074,67 @@ module Sass::Script
795
1074
  end
796
1075
  declare :adjust_color, [:color], :var_kwargs => true
797
1076
 
798
- # Scales one or more properties of a color by a percentage value.
799
- # Unlike \{#adjust_color adjust-color}, which changes a color's properties by fixed amounts,
800
- # \{#scale_color scale-color} fluidly changes them based on how high or low they already are.
801
- # That means that lightening an already-light color with \{#scale_color scale-color}
802
- # won't change the lightness much,
803
- # but lightening a dark color by the same amount will change it more dramatically.
804
- # This has the benefit of making `scale-color($color, ...)` have a similar effect
805
- # regardless of what `$color` is.
806
- #
807
- # For example, the lightness of a color can be anywhere between 0 and 100.
808
- # If `scale-color($color, $lightness: 40%)` is called, the resulting color's lightness
809
- # will be 40% of the way between its original lightness and 100.
810
- # If `scale-color($color, $lightness: -40%)` is called instead,
811
- # the lightness will be 40% of the way between the original and 0.
812
- #
813
- # This can change the red, green, blue, saturation, value, and alpha properties.
814
- # The properties are specified as keyword arguments.
815
- # All arguments should be percentages between 0% and 100%.
816
- #
817
- # All properties are optional.
818
- # You can't specify both RGB properties (`$red`, `$green`, `$blue`)
819
- # and HSL properties (`$saturation`, `$value`) at the same time.
1077
+ # Fluidly scales one or more properties of a color. Unlike
1078
+ # \{#adjust_color adjust-color}, which changes a color's properties by fixed
1079
+ # amounts, \{#scale_color scale-color} fluidly changes them based on how
1080
+ # high or low they already are. That means that lightening an already-light
1081
+ # color with \{#scale_color scale-color} won't change the lightness much,
1082
+ # but lightening a dark color by the same amount will change it more
1083
+ # dramatically. This has the benefit of making `scale-color($color, ...)`
1084
+ # have a similar effect regardless of what `$color` is.
1085
+ #
1086
+ # For example, the lightness of a color can be anywhere between `0%` and
1087
+ # `100%`. If `scale-color($color, $lightness: 40%)` is called, the resulting
1088
+ # color's lightness will be 40% of the way between its original lightness
1089
+ # and 100. If `scale-color($color, $lightness: -40%)` is called instead, the
1090
+ # lightness will be 40% of the way between the original and 0.
1091
+ #
1092
+ # This can change the red, green, blue, saturation, value, and alpha
1093
+ # properties. The properties are specified as keyword arguments. All
1094
+ # arguments should be percentages between `0%` and `100%`.
1095
+ #
1096
+ # All properties are optional. You can't specify both RGB properties
1097
+ # (`$red`, `$green`, `$blue`) and HSL properties (`$saturation`, `$value`)
1098
+ # at the same time.
820
1099
  #
821
1100
  # @example
822
- # scale-color(hsl(120, 70, 80), $lightness: 50%) => hsl(120, 70, 90)
823
- # scale-color(rgb(200, 150, 170), $green: -40%, $blue: 70%) => rgb(200, 90, 229)
824
- # scale-color(hsl(200, 70, 80), $saturation: -90%, $alpha: -30%) => hsla(200, 7, 80, 0.7)
825
- # @param color [Color]
826
- # @param red [Number]
827
- # @param green [Number]
828
- # @param blue [Number]
829
- # @param saturation [Number]
830
- # @param lightness [Number]
831
- # @param alpha [Number]
832
- # @return [Color]
833
- # @raise [ArgumentError] if `color` is not a color,
834
- # if any keyword argument is not a percentage between 0% and 100%,
835
- # if an unexpected keyword argument is given,
836
- # or if both HSL and RGB properties are given.
1101
+ # scale-color(hsl(120, 70%, 80%), $lightness: 50%) => hsl(120, 70%, 90%)
1102
+ # scale-color(rgb(200, 150%, 170%), $green: -40%, $blue: 70%) => rgb(200, 90, 229)
1103
+ # 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]
1113
+ # @return [Sass::Script::Value::Color]
1114
+ # @raise [ArgumentError] if any parameter is the wrong type or out-of
1115
+ # bounds, or if RGB properties and HSL properties are adjusted at the
1116
+ # same time
837
1117
  def scale_color(color, kwargs)
838
- assert_type color, :Color
839
- with = Sass::Util.map_hash({
1118
+ assert_type color, :Color, :color
1119
+ with = Sass::Util.map_hash(
840
1120
  "red" => 255,
841
1121
  "green" => 255,
842
1122
  "blue" => 255,
843
1123
  "saturation" => 100,
844
1124
  "lightness" => 100,
845
1125
  "alpha" => 1
846
- }) do |name, max|
1126
+ ) do |name, max|
847
1127
 
848
- next unless val = kwargs.delete(name)
1128
+ val = kwargs.delete(name)
1129
+ next unless val
849
1130
  assert_type val, :Number, name
850
- if !(val.numerator_units == ['%'] && val.denominator_units.empty?)
851
- raise ArgumentError.new("$#{name}: Amount #{val} must be a % (e.g. #{val.value}%)")
852
- elsif !(-100..100).include?(val.value)
853
- raise ArgumentError.new("$#{name}: Amount #{val} must be between -100% and 100%")
854
- end
1131
+ assert_unit val, '%', name
1132
+ Sass::Util.check_range("$#{name}: Amount", -100..100, val, '%')
855
1133
 
856
1134
  current = color.send(name)
857
- scale = val.value/100.0
1135
+ scale = val.value / 100.0
858
1136
  diff = scale > 0 ? max - current : current
859
- [name.to_sym, current + diff*scale]
1137
+ [name.to_sym, current + diff * scale]
860
1138
  end
861
1139
 
862
1140
  unless kwargs.empty?
@@ -868,44 +1146,48 @@ module Sass::Script
868
1146
  end
869
1147
  declare :scale_color, [:color], :var_kwargs => true
870
1148
 
871
- # Changes one or more properties of a color.
872
- # This can change the red, green, blue, hue, saturation, value, and alpha properties.
873
- # The properties are specified as keyword arguments,
874
- # and replace the color's current value for that property.
875
- #
876
- # `$red`, `$green`, and `$blue` properties should be between 0 and 255.
877
- # `$saturation` and `$lightness` should be between 0% and 100%.
878
- # `$alpha` should be between 0 and 1.
1149
+ # Changes one or more properties of a color. This can change the red, green,
1150
+ # blue, hue, saturation, value, and alpha properties. The properties are
1151
+ # specified as keyword arguments, and replace the color's current value for
1152
+ # that property.
879
1153
  #
880
- # All properties are optional.
881
- # You can't specify both RGB properties (`$red`, `$green`, `$blue`)
882
- # and HSL properties (`$hue`, `$saturation`, `$value`) at the same time.
1154
+ # All properties are optional. You can't specify both RGB properties
1155
+ # (`$red`, `$green`, `$blue`) and HSL properties (`$hue`, `$saturation`,
1156
+ # `$value`) at the same time.
883
1157
  #
884
1158
  # @example
885
1159
  # change-color(#102030, $blue: 5) => #102005
886
1160
  # change-color(#102030, $red: 120, $blue: 5) => #782005
887
1161
  # change-color(hsl(25, 100%, 80%), $lightness: 40%, $alpha: 0.8) => hsla(25, 100%, 40%, 0.8)
888
- # @param color [Color]
889
- # @param red [Number]
890
- # @param green [Number]
891
- # @param blue [Number]
892
- # @param hue [Number]
893
- # @param saturation [Number]
894
- # @param lightness [Number]
895
- # @param alpha [Number]
896
- # @return [Color]
897
- # @raise [ArgumentError] if `color` is not a color,
898
- # if any keyword argument is not a number,
899
- # if any keyword argument is not in the legal range,
900
- # if an unexpected keyword argument is given,
901
- # or if both HSL and RGB properties are given.
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
1179
+ # @return [Sass::Script::Value::Color]
1180
+ # @raise [ArgumentError] if any parameter is the wrong type or out-of
1181
+ # bounds, or if RGB properties and HSL properties are adjusted at the
1182
+ # same time
902
1183
  def change_color(color, kwargs)
903
- assert_type color, :Color
904
- with = Sass::Util.map_hash(%w[red green blue hue saturation lightness alpha]) do |name, max|
905
- next unless val = kwargs.delete(name)
1184
+ assert_type color, :Color, :color
1185
+ with = Sass::Util.to_hash(%w[red green blue hue saturation lightness alpha].map do |name|
1186
+ val = kwargs.delete(name)
1187
+ next unless val
906
1188
  assert_type val, :Number, name
907
1189
  [name.to_sym, val.value]
908
- end
1190
+ end)
909
1191
 
910
1192
  unless kwargs.empty?
911
1193
  name, val = kwargs.to_a.first
@@ -916,123 +1198,131 @@ module Sass::Script
916
1198
  end
917
1199
  declare :change_color, [:color], :var_kwargs => true
918
1200
 
919
- # Mixes together two colors.
920
- # Specifically, takes the average of each of the RGB components,
921
- # optionally weighted by the given percentage.
922
- # The opacity of the colors is also considered when weighting the components.
1201
+ # Mixes two colors together. Specifically, takes the average of each of the
1202
+ # RGB components, optionally weighted by the given percentage. The opacity
1203
+ # of the colors is also considered when weighting the components.
923
1204
  #
924
1205
  # The weight specifies the amount of the first color that should be included
925
- # in the returned color.
926
- # The default, 50%, means that half the first color
927
- # and half the second color should be used.
928
- # 25% means that a quarter of the first color
929
- # and three quarters of the second color should be used.
1206
+ # in the returned color. The default, `50%`, means that half the first color
1207
+ # and half the second color should be used. `25%` means that a quarter of
1208
+ # the first color and three quarters of the second color should be used.
930
1209
  #
931
1210
  # @example
932
1211
  # mix(#f00, #00f) => #7f007f
933
1212
  # mix(#f00, #00f, 25%) => #3f00bf
934
1213
  # mix(rgba(255, 0, 0, 0.5), #00f) => rgba(63, 0, 191, 0.75)
935
- # @overload mix(color1, color2, weight: 50%)
936
- # @param color1 [Color]
937
- # @param color2 [Color]
938
- # @param weight [Number] between 0% and 100%
939
- # @return [Color]
940
- # @raise [ArgumentError] if `color1` or `color2` aren't colors,
941
- # or `weight` isn't a number between 0% and 100%
942
- def mix(color1, color2, weight = Number.new(50))
943
- assert_type color1, :Color
944
- assert_type color2, :Color
945
- assert_type weight, :Number
946
-
947
- unless (0..100).include?(weight.value)
948
- raise ArgumentError.new("Weight #{weight} must be between 0% and 100%")
949
- end
950
-
951
- # This algorithm factors in both the user-provided weight
952
- # and the difference between the alpha values of the two colors
953
- # to decide how to perform the weighted average of the two RGB values.
1214
+ # @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`
1220
+ # @return [Sass::Script::Value::Color]
1221
+ # @raise [ArgumentError] if `$weight` is out of bounds or any parameter is
1222
+ # the wrong type
1223
+ def mix(color1, color2, weight = number(50))
1224
+ assert_type color1, :Color, :color1
1225
+ assert_type color2, :Color, :color2
1226
+ assert_type weight, :Number, :weight
1227
+
1228
+ Sass::Util.check_range("Weight", 0..100, weight, '%')
1229
+
1230
+ # This algorithm factors in both the user-provided weight (w) and the
1231
+ # difference between the alpha values of the two colors (a) to decide how
1232
+ # to perform the weighted average of the two RGB values.
954
1233
  #
955
1234
  # It works by first normalizing both parameters to be within [-1, 1],
956
- # where 1 indicates "only use color1", -1 indicates "only use color 0",
957
- # and all values in between indicated a proportionately weighted average.
1235
+ # where 1 indicates "only use color1", -1 indicates "only use color2", and
1236
+ # all values in between indicated a proportionately weighted average.
958
1237
  #
959
- # Once we have the normalized variables w and a,
960
- # we apply the formula (w + a)/(1 + w*a)
961
- # to get the combined weight (in [-1, 1]) of color1.
1238
+ # Once we have the normalized variables w and a, we apply the formula
1239
+ # (w + a)/(1 + w*a) to get the combined weight (in [-1, 1]) of color1.
962
1240
  # This formula has two especially nice properties:
963
1241
  #
964
1242
  # * When either w or a are -1 or 1, the combined weight is also that number
965
1243
  # (cases where w * a == -1 are undefined, and handled as a special case).
966
1244
  #
967
- # * When a is 0, the combined weight is w, and vice versa
1245
+ # * When a is 0, the combined weight is w, and vice versa.
968
1246
  #
969
1247
  # Finally, the weight of color1 is renormalized to be within [0, 1]
970
1248
  # and the weight of color2 is given by 1 minus the weight of color1.
971
- p = weight.value/100.0
972
- w = p*2 - 1
1249
+ p = (weight.value / 100.0).to_f
1250
+ w = p * 2 - 1
973
1251
  a = color1.alpha - color2.alpha
974
1252
 
975
- w1 = (((w * a == -1) ? w : (w + a)/(1 + w*a)) + 1)/2.0
1253
+ w1 = ((w * a == -1 ? w : (w + a) / (1 + w * a)) + 1) / 2.0
976
1254
  w2 = 1 - w1
977
1255
 
978
- rgb = color1.rgb.zip(color2.rgb).map {|v1, v2| v1*w1 + v2*w2}
979
- alpha = color1.alpha*p + color2.alpha*(1-p)
980
- Color.new(rgb + [alpha])
1256
+ rgba = color1.rgb.zip(color2.rgb).map {|v1, v2| v1 * w1 + v2 * w2}
1257
+ rgba << color1.alpha * p + color2.alpha * (1 - p)
1258
+ rgb_color(*rgba)
981
1259
  end
982
- declare :mix, [:color_1, :color_2]
983
- declare :mix, [:color_1, :color_2, :weight]
1260
+ declare :mix, [:color1, :color2], :deprecated => [:color_1, :color_2]
1261
+ declare :mix, [:color1, :color2, :weight], :deprecated => [:color_1, :color_2, :weight]
984
1262
 
985
- # Converts a color to grayscale.
986
- # This is identical to `desaturate(color, 100%)`.
1263
+ # Converts a color to grayscale. This is identical to `desaturate(color,
1264
+ # 100%)`.
987
1265
  #
988
- # @param color [Color]
989
- # @return [Color]
990
- # @raise [ArgumentError] if `color` isn't a color
991
1266
  # @see #desaturate
1267
+ # @overload grayscale($color)
1268
+ # @param $color [Sass::Script::Value::Color]
1269
+ # @return [Sass::Script::Value::Color]
1270
+ # @raise [ArgumentError] if `$color` isn't a color
992
1271
  def grayscale(color)
993
- desaturate color, Number.new(100)
1272
+ if color.is_a?(Sass::Script::Value::Number)
1273
+ return identifier("grayscale(#{color})")
1274
+ end
1275
+ desaturate color, number(100)
994
1276
  end
995
1277
  declare :grayscale, [:color]
996
1278
 
997
- # Returns the complement of a color.
998
- # This is identical to `adjust-hue(color, 180deg)`.
1279
+ # Returns the complement of a color. This is identical to `adjust-hue(color,
1280
+ # 180deg)`.
999
1281
  #
1000
- # @param color [Color]
1001
- # @return [Color]
1002
- # @raise [ArgumentError] if `color` isn't a color
1003
1282
  # @see #adjust_hue #adjust-hue
1283
+ # @overload complement($color)
1284
+ # @param $color [Sass::Script::Value::Color]
1285
+ # @return [Sass::Script::Value::Color]
1286
+ # @raise [ArgumentError] if `$color` isn't a color
1004
1287
  def complement(color)
1005
- adjust_hue color, Number.new(180)
1288
+ adjust_hue color, number(180)
1006
1289
  end
1007
1290
  declare :complement, [:color]
1008
1291
 
1009
- # Returns the inverse (negative) of a color.
1010
- # The red, green, and blue values are inverted, while the opacity is left alone.
1292
+ # Returns the inverse (negative) of a color. The red, green, and blue values
1293
+ # are inverted, while the opacity is left alone.
1011
1294
  #
1012
- # @param color [Color]
1013
- # @return [Color]
1014
- # @raise [ArgumentError] if `color` isn't a color
1295
+ # @overload invert($color)
1296
+ # @param $color [Sass::Script::Value::Color]
1297
+ # @return [Sass::Script::Value::Color]
1298
+ # @raise [ArgumentError] if `$color` isn't a color
1015
1299
  def invert(color)
1016
- assert_type color, :Color
1300
+ if color.is_a?(Sass::Script::Value::Number)
1301
+ return identifier("invert(#{color})")
1302
+ end
1303
+
1304
+ assert_type color, :Color, :color
1017
1305
  color.with(
1018
1306
  :red => (255 - color.red),
1019
1307
  :green => (255 - color.green),
1020
1308
  :blue => (255 - color.blue))
1021
1309
  end
1310
+ declare :invert, [:color]
1022
1311
 
1023
- # Removes quotes from a string if the string is quoted,
1024
- # or returns the same string if it's not.
1312
+ # Removes quotes from a string. If the string is already unquoted, this will
1313
+ # return it unmodified.
1025
1314
  #
1026
- # @param string [String]
1027
- # @return [String]
1028
- # @raise [ArgumentError] if `string` isn't a string
1029
1315
  # @see #quote
1030
1316
  # @example
1031
1317
  # unquote("foo") => foo
1032
1318
  # unquote(foo) => foo
1319
+ # @overload unquote($string)
1320
+ # @param $string [Sass::Script::Value::String]
1321
+ # @return [Sass::Script::Value::String]
1322
+ # @raise [ArgumentError] if `$string` isn't a string
1033
1323
  def unquote(string)
1034
- if string.is_a?(Sass::Script::String)
1035
- Sass::Script::String.new(string.value, :identifier)
1324
+ if string.is_a?(Sass::Script::Value::String) && string.type != :identifier
1325
+ identifier(string.value)
1036
1326
  else
1037
1327
  string
1038
1328
  end
@@ -1042,20 +1332,170 @@ module Sass::Script
1042
1332
  # Add quotes to a string if the string isn't quoted,
1043
1333
  # or returns the same string if it is.
1044
1334
  #
1045
- # @param string [String]
1046
- # @return [String]
1047
- # @raise [ArgumentError] if `string` isn't a string
1048
1335
  # @see #unquote
1049
1336
  # @example
1050
1337
  # quote("foo") => "foo"
1051
1338
  # quote(foo) => "foo"
1339
+ # @overload quote($string)
1340
+ # @param $string [Sass::Script::Value::String]
1341
+ # @return [Sass::Script::Value::String]
1342
+ # @raise [ArgumentError] if `$string` isn't a string
1052
1343
  def quote(string)
1053
- assert_type string, :String
1054
- Sass::Script::String.new(string.value, :string)
1344
+ assert_type string, :String, :string
1345
+ if string.type != :string
1346
+ quoted_string(string.value)
1347
+ else
1348
+ string
1349
+ end
1055
1350
  end
1056
1351
  declare :quote, [:string]
1057
1352
 
1058
- # Inspects the type of the argument, returning it as an unquoted string.
1353
+ # Returns the number of characters in a string.
1354
+ #
1355
+ # @example
1356
+ # str-length("foo") => 3
1357
+ # @overload str_length($string)
1358
+ # @param $string [Sass::Script::Value::String]
1359
+ # @return [Sass::Script::Value::Number]
1360
+ # @raise [ArgumentError] if `$string` isn't a string
1361
+ def str_length(string)
1362
+ assert_type string, :String, :string
1363
+ number(string.value.size)
1364
+ end
1365
+ declare :str_length, [:string]
1366
+
1367
+ # Inserts `$insert` into `$string` at `$index`.
1368
+ #
1369
+ # Note that unlike some languages, the first character in a Sass string is
1370
+ # number 1, the second number 2, and so forth.
1371
+ #
1372
+ # @example
1373
+ # str-insert("abcd", "X", 1) => "Xabcd"
1374
+ # str-insert("abcd", "X", 4) => "abcXd"
1375
+ # str-insert("abcd", "X", 5) => "abcdX"
1376
+ #
1377
+ # @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
1384
+ # @return [Sass::Script::Value::String] The result string. This will be
1385
+ # quoted if and only if `$string` was quoted
1386
+ # @raise [ArgumentError] if any parameter is the wrong type
1387
+ def str_insert(original, insert, index)
1388
+ assert_type original, :String, :string
1389
+ assert_type insert, :String, :insert
1390
+ assert_integer index, :index
1391
+ assert_unit index, nil, :index
1392
+ insertion_point = if index.value > 0
1393
+ [index.value - 1, original.value.size].min
1394
+ else
1395
+ [index.value, -original.value.size - 1].max
1396
+ end
1397
+ result = original.value.dup.insert(insertion_point, insert.value)
1398
+ Sass::Script::Value::String.new(result, original.type)
1399
+ end
1400
+ declare :str_insert, [:string, :insert, :index]
1401
+
1402
+ # Returns the index of the first occurance of `$substring` in `$string`. If
1403
+ # there is no such occurance, returns `null`.
1404
+ #
1405
+ # Note that unlike some languages, the first character in a Sass string is
1406
+ # number 1, the second number 2, and so forth.
1407
+ #
1408
+ # @example
1409
+ # str-index(abcd, a) => 1
1410
+ # str-index(abcd, ab) => 1
1411
+ # str-index(abcd, X) => null
1412
+ # str-index(abcd, c) => 3
1413
+ #
1414
+ # @overload str_index($string, $substring)
1415
+ # @param $string [Sass::Script::Value::String]
1416
+ # @param $substring [Sass::Script::Value::String]
1417
+ # @return [Sass::Script::Value::Number, Sass::Script::Value::Null]
1418
+ # @raise [ArgumentError] if any parameter is the wrong type
1419
+ def str_index(string, substring)
1420
+ assert_type string, :String, :string
1421
+ assert_type substring, :String, :substring
1422
+ index = string.value.index(substring.value)
1423
+ index ? number(index + 1) : null
1424
+ end
1425
+ declare :str_index, [:string, :substring]
1426
+
1427
+ # Extracts a substring from `$string`. The substring will begin at index
1428
+ # `$start-at` and ends at index `$end-at`.
1429
+ #
1430
+ # Note that unlike some languages, the first character in a Sass string is
1431
+ # number 1, the second number 2, and so forth.
1432
+ #
1433
+ # @example
1434
+ # str-slice("abcd", 2, 3) => "bc"
1435
+ # str-slice("abcd", 2) => "bcd"
1436
+ # str-slice("abcd", -3, -2) => "bc"
1437
+ # str-slice("abcd", 2, -2) => "bc"
1438
+ #
1439
+ # @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
1448
+ # @raise [ArgumentError] if any parameter is the wrong type
1449
+ def str_slice(string, start_at, end_at = nil)
1450
+ assert_type string, :String, :string
1451
+ assert_unit start_at, nil, "start-at"
1452
+
1453
+ end_at = number(-1) if end_at.nil?
1454
+ assert_unit end_at, nil, "end-at"
1455
+
1456
+ s = start_at.value > 0 ? start_at.value - 1 : start_at.value
1457
+ e = end_at.value > 0 ? end_at.value - 1 : end_at.value
1458
+ s = string.value.length + s if s < 0
1459
+ s = 0 if s < 0
1460
+ e = string.value.length + e if e < 0
1461
+ e = 0 if s < 0
1462
+ extracted = string.value.slice(s..e)
1463
+ Sass::Script::Value::String.new(extracted || "", string.type)
1464
+ end
1465
+ declare :str_slice, [:string, :start_at]
1466
+ declare :str_slice, [:string, :start_at, :end_at]
1467
+
1468
+ # Converts a string to upper case.
1469
+ #
1470
+ # @example
1471
+ # to-upper-case(abcd) => ABCD
1472
+ #
1473
+ # @overload to_upper_case($string)
1474
+ # @param $string [Sass::Script::Value::String]
1475
+ # @return [Sass::Script::Value::String]
1476
+ # @raise [ArgumentError] if `$string` isn't a string
1477
+ def to_upper_case(string)
1478
+ assert_type string, :String, :string
1479
+ Sass::Script::Value::String.new(string.value.upcase, string.type)
1480
+ end
1481
+ declare :to_upper_case, [:string]
1482
+
1483
+ # Convert a string to lower case,
1484
+ #
1485
+ # @example
1486
+ # to-lower-case(ABCD) => abcd
1487
+ #
1488
+ # @overload to_lower_case($string)
1489
+ # @param $string [Sass::Script::Value::String]
1490
+ # @return [Sass::Script::Value::String]
1491
+ # @raise [ArgumentError] if `$string` isn't a string
1492
+ def to_lower_case(string)
1493
+ assert_type string, :String, :string
1494
+ Sass::Script::Value::String.new(string.value.downcase, string.type)
1495
+ end
1496
+ declare :to_lower_case, [:string]
1497
+
1498
+ # Returns the type of a value.
1059
1499
  #
1060
1500
  # @example
1061
1501
  # type-of(100px) => number
@@ -1064,15 +1504,33 @@ module Sass::Script
1064
1504
  # type-of(true) => bool
1065
1505
  # type-of(#fff) => color
1066
1506
  # type-of(blue) => color
1067
- # @param value [Literal] The object to inspect
1068
- # @return [String] The unquoted string name of the literal's type
1507
+ # @overload type_of($value)
1508
+ # @param $value [Sass::Script::Value::Base] The value to inspect
1509
+ # @return [Sass::Script::Value::String] The unquoted string name of the
1510
+ # value's type
1069
1511
  def type_of(value)
1070
- Sass::Script::String.new(value.class.name.gsub(/Sass::Script::/,'').downcase)
1512
+ identifier(value.class.name.gsub(/Sass::Script::Value::/, '').downcase)
1071
1513
  end
1072
1514
  declare :type_of, [:value]
1073
1515
 
1074
- # Inspects the unit of the number, returning it as a quoted string.
1075
- # Complex units are sorted in alphabetical order by numerator and denominator.
1516
+ # Returns whether a feature exists in the current Sass runtime.
1517
+ #
1518
+ # @example
1519
+ # feature-exists(some-feature-that-exists) => true
1520
+ # feature-exists(what-is-this-i-dont-know) => false
1521
+ #
1522
+ # @overload feature_exists($feature)
1523
+ # @param $feature [Sass::Script::Value::String] The name of the feature
1524
+ # @return [Sass::Script::Value::Bool] Whether the feature is supported in this version of Sass
1525
+ # @raise [ArgumentError] if `$feature` isn't a string
1526
+ def feature_exists(feature)
1527
+ assert_type feature, :String, :feature
1528
+ bool(Sass.has_feature?(feature.value))
1529
+ end
1530
+ declare :feature_exists, [:feature]
1531
+
1532
+ # Returns the unit(s) associated with a number. Complex units are sorted in
1533
+ # alphabetical order by numerator and denominator.
1076
1534
  #
1077
1535
  # @example
1078
1536
  # unit(100) => ""
@@ -1080,159 +1538,239 @@ module Sass::Script
1080
1538
  # unit(3em) => "em"
1081
1539
  # unit(10px * 5em) => "em*px"
1082
1540
  # unit(10px * 5em / 30cm / 1rem) => "em*px/cm*rem"
1083
- # @param number [Literal] The number to inspect
1084
- # @return [String] The unit(s) of the number
1085
- # @raise [ArgumentError] if `number` isn't a number
1541
+ # @overload unit($number)
1542
+ # @param $number [Sass::Script::Value::Number]
1543
+ # @return [Sass::Script::Value::String] The unit(s) of the number, as a
1544
+ # quoted string
1545
+ # @raise [ArgumentError] if `$number` isn't a number
1086
1546
  def unit(number)
1087
- assert_type number, :Number
1088
- Sass::Script::String.new(number.unit_str, :string)
1547
+ assert_type number, :Number, :number
1548
+ quoted_string(number.unit_str)
1089
1549
  end
1090
1550
  declare :unit, [:number]
1091
1551
 
1092
- # Inspects the unit of the number, returning a boolean indicating if it is unitless.
1552
+ # Returns whether a number has units.
1093
1553
  #
1094
1554
  # @example
1095
1555
  # unitless(100) => true
1096
1556
  # unitless(100px) => false
1097
- # @param number [Literal] The number to inspect
1098
- # @return [Bool] Whether or not the number is unitless
1099
- # @raise [ArgumentError] if `number` isn't a number
1557
+ # @overload unitless($number)
1558
+ # @param $number [Sass::Script::Value::Number]
1559
+ # @return [Sass::Script::Value::Bool]
1560
+ # @raise [ArgumentError] if `$number` isn't a number
1100
1561
  def unitless(number)
1101
- assert_type number, :Number
1102
- Sass::Script::Bool.new(number.unitless?)
1562
+ assert_type number, :Number, :number
1563
+ bool(number.unitless?)
1103
1564
  end
1104
1565
  declare :unitless, [:number]
1105
1566
 
1106
- # Returns true if two numbers are similar enough to be added, subtracted, or compared.
1567
+ # Returns whether two numbers can added, subtracted, or compared.
1107
1568
  #
1108
1569
  # @example
1109
1570
  # comparable(2px, 1px) => true
1110
1571
  # comparable(100px, 3em) => false
1111
1572
  # comparable(10cm, 3mm) => true
1112
- # @param number_1 [Number]
1113
- # @param number_2 [Number]
1114
- # @return [Bool] indicating if the numbers can be compared.
1115
- # @raise [ArgumentError] if `number_1` or `number_2` aren't numbers
1116
- def comparable(number_1, number_2)
1117
- assert_type number_1, :Number
1118
- assert_type number_2, :Number
1119
- Sass::Script::Bool.new(number_1.comparable_to?(number_2))
1573
+ # @overload comparable($number1, $number2)
1574
+ # @param $number1 [Sass::Script::Value::Number]
1575
+ # @param $number2 [Sass::Script::Value::Number]
1576
+ # @return [Sass::Script::Value::Bool]
1577
+ # @raise [ArgumentError] if either parameter is the wrong type
1578
+ def comparable(number1, number2)
1579
+ assert_type number1, :Number, :number1
1580
+ assert_type number2, :Number, :number2
1581
+ bool(number1.comparable_to?(number2))
1120
1582
  end
1121
- declare :comparable, [:number_1, :number_2]
1583
+ declare :comparable, [:number1, :number2], :deprecated => [:number_1, :number_2]
1122
1584
 
1123
- # Converts a decimal number to a percentage.
1585
+ # Converts a unitless number to a percentage.
1124
1586
  #
1125
1587
  # @example
1588
+ # percentage(0.2) => 20%
1126
1589
  # percentage(100px / 50px) => 200%
1127
- # @param value [Number] The decimal number to convert to a percentage
1128
- # @return [Number] The percentage
1129
- # @raise [ArgumentError] If `value` isn't a unitless number
1130
- def percentage(value)
1131
- unless value.is_a?(Sass::Script::Number) && value.unitless?
1132
- raise ArgumentError.new("#{value.inspect} is not a unitless number")
1590
+ # @overload percentage($number)
1591
+ # @param $number [Sass::Script::Value::Number]
1592
+ # @return [Sass::Script::Value::Number]
1593
+ # @raise [ArgumentError] if `$number` isn't a unitless number
1594
+ def percentage(number)
1595
+ unless number.is_a?(Sass::Script::Value::Number) && number.unitless?
1596
+ raise ArgumentError.new("$number: #{number.inspect} is not a unitless number")
1133
1597
  end
1134
- Sass::Script::Number.new(value.value * 100, ['%'])
1598
+ number(number.value * 100, '%')
1135
1599
  end
1136
- declare :percentage, [:value]
1600
+ declare :percentage, [:number], :deprecated => [:value]
1137
1601
 
1138
1602
  # Rounds a number to the nearest whole number.
1139
1603
  #
1140
1604
  # @example
1141
1605
  # round(10.4px) => 10px
1142
1606
  # round(10.6px) => 11px
1143
- # @param value [Number] The number
1144
- # @return [Number] The rounded number
1145
- # @raise [ArgumentError] if `value` isn't a number
1146
- def round(value)
1147
- numeric_transformation(value) {|n| n.round}
1607
+ # @overload round($number)
1608
+ # @param $number [Sass::Script::Value::Number]
1609
+ # @return [Sass::Script::Value::Number]
1610
+ # @raise [ArgumentError] if `$number` isn't a number
1611
+ def round(number)
1612
+ numeric_transformation(number) {|n| n.round}
1148
1613
  end
1149
- declare :round, [:value]
1614
+ declare :round, [:number], :deprecated => [:value]
1150
1615
 
1151
- # Rounds a number up to the nearest whole number.
1616
+ # Rounds a number up to the next whole number.
1152
1617
  #
1153
1618
  # @example
1154
- # ciel(10.4px) => 11px
1155
- # ciel(10.6px) => 11px
1156
- # @param value [Number] The number
1157
- # @return [Number] The rounded number
1158
- # @raise [ArgumentError] if `value` isn't a number
1159
- def ceil(value)
1160
- numeric_transformation(value) {|n| n.ceil}
1619
+ # ceil(10.4px) => 11px
1620
+ # ceil(10.6px) => 11px
1621
+ # @overload ceil($number)
1622
+ # @param $number [Sass::Script::Value::Number]
1623
+ # @return [Sass::Script::Value::Number]
1624
+ # @raise [ArgumentError] if `$number` isn't a number
1625
+ def ceil(number)
1626
+ numeric_transformation(number) {|n| n.ceil}
1161
1627
  end
1162
- declare :ceil, [:value]
1628
+ declare :ceil, [:number], :deprecated => [:value]
1163
1629
 
1164
- # Rounds down to the nearest whole number.
1630
+ # Rounds a number down to the previous whole number.
1165
1631
  #
1166
1632
  # @example
1167
1633
  # floor(10.4px) => 10px
1168
1634
  # floor(10.6px) => 10px
1169
- # @param value [Number] The number
1170
- # @return [Number] The rounded number
1171
- # @raise [ArgumentError] if `value` isn't a number
1172
- def floor(value)
1173
- numeric_transformation(value) {|n| n.floor}
1635
+ # @overload floor($number)
1636
+ # @param $number [Sass::Script::Value::Number]
1637
+ # @return [Sass::Script::Value::Number]
1638
+ # @raise [ArgumentError] if `$number` isn't a number
1639
+ def floor(number)
1640
+ numeric_transformation(number) {|n| n.floor}
1174
1641
  end
1175
- declare :floor, [:value]
1642
+ declare :floor, [:number], :deprecated => [:value]
1176
1643
 
1177
- # Finds the absolute value of a number.
1644
+ # Returns the absolute value of a number.
1178
1645
  #
1179
1646
  # @example
1180
1647
  # abs(10px) => 10px
1181
1648
  # abs(-10px) => 10px
1182
- # @param value [Number] The number
1183
- # @return [Number] The absolute value
1184
- # @raise [ArgumentError] if `value` isn't a number
1185
- def abs(value)
1186
- numeric_transformation(value) {|n| n.abs}
1649
+ # @overload abs($number)
1650
+ # @param $number [Sass::Script::Value::Number]
1651
+ # @return [Sass::Script::Value::Number]
1652
+ # @raise [ArgumentError] if `$number` isn't a number
1653
+ def abs(number)
1654
+ numeric_transformation(number) {|n| n.abs}
1187
1655
  end
1188
- declare :abs, [:value]
1656
+ declare :abs, [:number], :deprecated => [:value]
1657
+
1658
+ # Finds the minimum of several numbers. This function takes any number of
1659
+ # arguments.
1660
+ #
1661
+ # @example
1662
+ # min(1px, 4px) => 1px
1663
+ # min(5em, 3em, 4em) => 3em
1664
+ # @overload min($numbers...)
1665
+ # @param $numbers [[Sass::Script::Value::Number]]
1666
+ # @return [Sass::Script::Value::Number]
1667
+ # @raise [ArgumentError] if any argument isn't a number, or if not all of
1668
+ # the arguments have comparable units
1669
+ def min(*numbers)
1670
+ numbers.each {|n| assert_type n, :Number}
1671
+ numbers.inject {|min, num| min.lt(num).to_bool ? min : num}
1672
+ end
1673
+ declare :min, [], :var_args => :true
1674
+
1675
+ # Finds the maximum of several numbers. This function takes any number of
1676
+ # arguments.
1677
+ #
1678
+ # @example
1679
+ # max(1px, 4px) => 4px
1680
+ # max(5em, 3em, 4em) => 5em
1681
+ # @overload max($numbers...)
1682
+ # @param $numbers [[Sass::Script::Value::Number]]
1683
+ # @return [Sass::Script::Value::Number]
1684
+ # @raise [ArgumentError] if any argument isn't a number, or if not all of
1685
+ # the arguments have comparable units
1686
+ def max(*values)
1687
+ values.each {|v| assert_type v, :Number}
1688
+ values.inject {|max, val| max.gt(val).to_bool ? max : val}
1689
+ end
1690
+ declare :max, [], :var_args => :true
1189
1691
 
1190
1692
  # Return the length of a list.
1191
1693
  #
1694
+ # This can return the number of pairs in a map as well.
1695
+ #
1192
1696
  # @example
1193
1697
  # length(10px) => 1
1194
1698
  # length(10px 20px 30px) => 3
1195
- # @param list [Literal] The list
1196
- # @return [Number] The length
1699
+ # length((width: 10px, height: 20px)) => 2
1700
+ # @overload length($list)
1701
+ # @param $list [Sass::Script::Value::Base]
1702
+ # @return [Sass::Script::Value::Number]
1197
1703
  def length(list)
1198
- Sass::Script::Number.new(list.to_a.size)
1704
+ number(list.to_a.size)
1199
1705
  end
1200
1706
  declare :length, [:list]
1201
1707
 
1708
+ # Return a new list, based on the list provided, but with the nth
1709
+ # element changed to the value given.
1710
+ #
1711
+ # Note that unlike some languages, the first item in a Sass list is number
1712
+ # 1, the second number 2, and so forth.
1713
+ #
1714
+ # Negative index values address elements in reverse order, starting with the last element
1715
+ # in the list.
1716
+ #
1717
+ # @example
1718
+ # set-nth($list: 10px 20px 30px, $n: 2, $value: -20px) => 10px -20px 30px
1719
+ # @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`.
1725
+ # @return [Sass::Script::Value::List]
1726
+ # @raise [ArgumentError] if `$n` isn't an integer between 1 and the length
1727
+ # of `$list`
1728
+ def set_nth(list, n, value)
1729
+ assert_type n, :Number, :n
1730
+ Sass::Script::Value::List.assert_valid_index(list, n)
1731
+ index = n.to_i > 0 ? n.to_i - 1 : n.to_i
1732
+ new_list = list.to_a.dup
1733
+ new_list[index] = value
1734
+ Sass::Script::Value::List.new(new_list, list.separator)
1735
+ end
1736
+ declare :set_nth, [:list, :n, :value]
1737
+
1202
1738
  # Gets the nth item in a list.
1203
1739
  #
1204
- # Note that unlike some languages, the first item in a Sass list is number 1,
1205
- # the second number 2, and so forth.
1740
+ # Note that unlike some languages, the first item in a Sass list is number
1741
+ # 1, the second number 2, and so forth.
1742
+ #
1743
+ # This can return the nth pair in a map as well.
1744
+ #
1745
+ # Negative index values address elements in reverse order, starting with the last element in
1746
+ # the list.
1206
1747
  #
1207
1748
  # @example
1208
1749
  # nth(10px 20px 30px, 1) => 10px
1209
1750
  # nth((Helvetica, Arial, sans-serif), 3) => sans-serif
1210
- # @param list [Literal] The list
1211
- # @param n [Number] The index into the list
1212
- # @return [Literal] The nth item in the list
1213
- # @raise [ArgumentError] If `n` isn't an integer between 1 and the list's length.
1751
+ # nth((width: 10px, length: 20px), 2) => length, 20px
1752
+ # @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.
1756
+ # @return [Sass::Script::Value::Base]
1757
+ # @raise [ArgumentError] if `$n` isn't an integer between 1 and the length
1758
+ # of `$list`
1214
1759
  def nth(list, n)
1215
- assert_type n, :Number
1216
- if !n.int?
1217
- raise ArgumentError.new("List index #{n} must be an integer")
1218
- elsif n.to_i < 1
1219
- raise ArgumentError.new("List index #{n} must be greater than or equal to 1")
1220
- elsif list.to_a.size == 0
1221
- raise ArgumentError.new("List index is #{n} but list has no items")
1222
- elsif n.to_i > (size = list.to_a.size)
1223
- raise ArgumentError.new("List index is #{n} but list is only #{size} item#{'s' if size != 1} long")
1224
- end
1760
+ assert_type n, :Number, :n
1761
+ Sass::Script::Value::List.assert_valid_index(list, n)
1225
1762
 
1226
- list.to_a[n.to_i - 1]
1763
+ index = n.to_i > 0 ? n.to_i - 1 : n.to_i
1764
+ list.to_a[index]
1227
1765
  end
1228
1766
  declare :nth, [:list, :n]
1229
1767
 
1230
- # Joins together two lists into a new list.
1768
+ # Joins together two lists into one.
1231
1769
  #
1232
- # Unless the `$separator` argument is passed,
1233
- # if one list is comma-separated and one is space-separated,
1234
- # the first parameter's separator is used for the resulting list.
1235
- # If the lists have only one item each, spaces are used for the resulting list.
1770
+ # Unless `$separator` is passed, if one list is comma-separated and one is
1771
+ # space-separated, the first parameter's separator is used for the resulting
1772
+ # list. If both lists have fewer than two items, spaces are used for the
1773
+ # resulting list.
1236
1774
  #
1237
1775
  # @example
1238
1776
  # join(10px 20px, 30px 40px) => 10px 20px 30px 40px
@@ -1240,81 +1778,458 @@ module Sass::Script
1240
1778
  # join(10px, 20px) => 10px 20px
1241
1779
  # join(10px, 20px, comma) => 10px, 20px
1242
1780
  # join((blue, red), (#abc, #def), space) => blue red #abc #def
1243
- # @overload join(list1, list2, separator: auto)
1244
- # @param list1 [Literal] The first list to join
1245
- # @param list2 [Literal] The second list to join
1246
- # @param separator [String] How the list separator (comma or space) should be determined.
1247
- # If this is `comma` or `space`, that is always the separator;
1248
- # if this is `auto` (the default), the separator is determined as explained above.
1249
- def join(list1, list2, separator = Sass::Script::String.new("auto"))
1250
- assert_type separator, :String
1781
+ # @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.
1787
+ # @return [Sass::Script::Value::List]
1788
+ def join(list1, list2, separator = identifier("auto"))
1789
+ assert_type separator, :String, :separator
1251
1790
  unless %w[auto space comma].include?(separator.value)
1252
1791
  raise ArgumentError.new("Separator name must be space, comma, or auto")
1253
1792
  end
1254
- sep1 = list1.separator if list1.is_a?(Sass::Script::List) && !list1.value.empty?
1255
- sep2 = list2.separator if list2.is_a?(Sass::Script::List) && !list2.value.empty?
1256
- Sass::Script::List.new(
1257
- list1.to_a + list2.to_a,
1258
- if separator.value == 'auto'
1259
- sep1 || sep2 || :space
1260
- else
1261
- separator.value.to_sym
1262
- end)
1793
+ sep = if separator.value == 'auto'
1794
+ list1.separator || list2.separator || :space
1795
+ else
1796
+ separator.value.to_sym
1797
+ end
1798
+ list(list1.to_a + list2.to_a, sep)
1263
1799
  end
1264
1800
  declare :join, [:list1, :list2]
1265
1801
  declare :join, [:list1, :list2, :separator]
1266
1802
 
1267
1803
  # Appends a single value onto the end of a list.
1268
1804
  #
1269
- # Unless the `$separator` argument is passed,
1270
- # if the list has only one item,
1805
+ # Unless the `$separator` argument is passed, if the list had only one item,
1271
1806
  # the resulting list will be space-separated.
1272
1807
  #
1273
1808
  # @example
1274
1809
  # append(10px 20px, 30px) => 10px 20px 30px
1275
1810
  # append((blue, red), green) => blue, red, green
1276
1811
  # append(10px 20px, 30px 40px) => 10px 20px (30px 40px)
1277
- # join(10px, 20px, comma) => 10px, 20px
1278
- # join((blue, red), green, space) => blue red green
1279
- # @overload join(list, val, separator: auto)
1280
- # @param list1 [Literal] The first list to join
1281
- # @param list2 [Literal] The second list to join
1282
- # @param separator [String] How the list separator (comma or space) should be determined.
1283
- # If this is `comma` or `space`, that is always the separator;
1284
- # if this is `auto` (the default), the separator is determined as explained above.
1285
- def append(list, val, separator = Sass::Script::String.new("auto"))
1286
- assert_type separator, :String
1812
+ # append(10px, 20px, comma) => 10px, 20px
1813
+ # append((blue, red), green, space) => blue red green
1814
+ # @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.
1820
+ # @return [Sass::Script::Value::List]
1821
+ def append(list, val, separator = identifier("auto"))
1822
+ assert_type separator, :String, :separator
1287
1823
  unless %w[auto space comma].include?(separator.value)
1288
1824
  raise ArgumentError.new("Separator name must be space, comma, or auto")
1289
1825
  end
1290
- sep = list.separator if list.is_a?(Sass::Script::List)
1291
- Sass::Script::List.new(
1292
- list.to_a + [val],
1293
- if separator.value == 'auto'
1294
- sep || :space
1295
- else
1296
- separator.value.to_sym
1297
- end)
1826
+ sep = if separator.value == 'auto'
1827
+ list.separator || :space
1828
+ else
1829
+ separator.value.to_sym
1830
+ end
1831
+ list(list.to_a + [val], sep)
1298
1832
  end
1299
1833
  declare :append, [:list, :val]
1300
1834
  declare :append, [:list, :val, :separator]
1301
1835
 
1302
- # Returns one of two values based on the truth value of the first argument.
1836
+ # Combines several lists into a single multidimensional list. The nth value
1837
+ # of the resulting list is a space separated list of the source lists' nth
1838
+ # values.
1839
+ #
1840
+ # The length of the resulting list is the length of the
1841
+ # shortest list.
1842
+ #
1843
+ # @example
1844
+ # zip(1px 1px 3px, solid dashed solid, red green blue)
1845
+ # => 1px solid red, 1px dashed green, 3px solid blue
1846
+ # @overload zip($lists...)
1847
+ # @param $lists [[Sass::Script::Value::Base]]
1848
+ # @return [Sass::Script::Value::List]
1849
+ def zip(*lists)
1850
+ length = nil
1851
+ values = []
1852
+ lists.each do |list|
1853
+ array = list.to_a
1854
+ values << array.dup
1855
+ length = length.nil? ? array.length : [length, array.length].min
1856
+ end
1857
+ values.each do |value|
1858
+ value.slice!(length)
1859
+ end
1860
+ new_list_value = values.first.zip(*values[1..-1])
1861
+ list(new_list_value.map {|list| list(list, :space)}, :comma)
1862
+ end
1863
+ declare :zip, [], :var_args => true
1864
+
1865
+ # Returns the position of a value within a list. If the value isn't found,
1866
+ # returns `null` instead.
1867
+ #
1868
+ # Note that unlike some languages, the first item in a Sass list is number
1869
+ # 1, the second number 2, and so forth.
1870
+ #
1871
+ # This can return the position of a pair in a map as well.
1872
+ #
1873
+ # @example
1874
+ # index(1px solid red, solid) => 2
1875
+ # index(1px solid red, dashed) => null
1876
+ # index((width: 10px, height: 20px), (height, 20px)) => 2
1877
+ # @overload index($list, $value)
1878
+ # @param $list [Sass::Script::Value::Base]
1879
+ # @param $value [Sass::Script::Value::Base]
1880
+ # @return [Sass::Script::Value::Number, Sass::Script::Value::Null] The
1881
+ # 1-based index of `$value` in `$list`, or `null`
1882
+ def index(list, value)
1883
+ 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)
1886
+ end
1887
+ declare :index, [:list, :value]
1888
+
1889
+ # Returns the separator of a list. If the list doesn't have a separator due
1890
+ # to having fewer than two elements, returns `space`.
1891
+ #
1892
+ # @example
1893
+ # list-separator(1px 2px 3px) => space
1894
+ # list-separator(1px, 2px, 3px) => comma
1895
+ # list-separator('foo') => space
1896
+ # @overload list_separator($list)
1897
+ # @param $list [Sass::Script::Value::Base]
1898
+ # @return [Sass::Script::Value::String] `comma` or `space`
1899
+ def list_separator(list)
1900
+ identifier((list.separator || :space).to_s)
1901
+ end
1902
+ declare :separator, [:list]
1903
+
1904
+ # Returns the value in a map associated with the given key. If the map
1905
+ # doesn't have such a key, returns `null`.
1906
+ #
1907
+ # @example
1908
+ # map-get(("foo": 1, "bar": 2), "foo") => 1
1909
+ # map-get(("foo": 1, "bar": 2), "bar") => 2
1910
+ # map-get(("foo": 1, "bar": 2), "baz") => null
1911
+ # @overload map_get($map, $key)
1912
+ # @param $map [Sass::Script::Value::Map]
1913
+ # @param $key [Sass::Script::Value::Base]
1914
+ # @return [Sass::Script::Value::Base] The value indexed by `$key`, or `null`
1915
+ # if the map doesn't contain the given key
1916
+ # @raise [ArgumentError] if `$map` is not a map
1917
+ def map_get(map, key)
1918
+ assert_type map, :Map, :map
1919
+ to_h(map)[key] || null
1920
+ end
1921
+ declare :map_get, [:map, :key]
1922
+
1923
+ # Merges two maps together into a new map. Keys in `$map2` will take
1924
+ # precedence over keys in `$map1`.
1925
+ #
1926
+ # This is the best way to add new values to a map.
1927
+ #
1928
+ # All keys in the returned map that also appear in `$map1` will have the
1929
+ # same order as in `$map1`. New keys from `$map2` will be placed at the end
1930
+ # of the map.
1931
+ #
1932
+ # @example
1933
+ # map-merge(("foo": 1), ("bar": 2)) => ("foo": 1, "bar": 2)
1934
+ # map-merge(("foo": 1, "bar": 2), ("bar": 3)) => ("foo": 1, "bar": 3)
1935
+ # @overload map_merge($map1, $map2)
1936
+ # @param $map1 [Sass::Script::Value::Map]
1937
+ # @param $map2 [Sass::Script::Value::Map]
1938
+ # @return [Sass::Script::Value::Map]
1939
+ # @raise [ArgumentError] if either parameter is not a map
1940
+ def map_merge(map1, map2)
1941
+ assert_type map1, :Map, :map1
1942
+ assert_type map2, :Map, :map2
1943
+ map(to_h(map1).merge(to_h(map2)))
1944
+ end
1945
+ declare :map_merge, [:map1, :map2]
1946
+
1947
+ # Returns a new map with a key removed.
1948
+ #
1949
+ # @example
1950
+ # map-remove(("foo": 1, "bar": 2), "bar") => ("foo": 1)
1951
+ # 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]
1955
+ # @return [Sass::Script::Value::Map]
1956
+ # @raise [ArgumentError] if `$map` is not a map
1957
+ def map_remove(map, key)
1958
+ assert_type map, :Map, :map
1959
+ hash = to_h(map).dup
1960
+ hash.delete key
1961
+ map(hash)
1962
+ end
1963
+ declare :map_remove, [:map, :key]
1964
+
1965
+ # Returns a list of all keys in a map.
1966
+ #
1967
+ # @example
1968
+ # map-keys(("foo": 1, "bar": 2)) => "foo", "bar"
1969
+ # @overload map_keys($map)
1970
+ # @param $map [Map]
1971
+ # @return [List] the list of keys, comma-separated
1972
+ # @raise [ArgumentError] if `$map` is not a map
1973
+ def map_keys(map)
1974
+ assert_type map, :Map, :map
1975
+ list(to_h(map).keys, :comma)
1976
+ end
1977
+ declare :map_keys, [:map]
1978
+
1979
+ # Returns a list of all values in a map. This list may include duplicate
1980
+ # values, if multiple keys have the same value.
1981
+ #
1982
+ # @example
1983
+ # map-values(("foo": 1, "bar": 2)) => 1, 2
1984
+ # map-values(("foo": 1, "bar": 2, "baz": 1)) => 1, 2, 1
1985
+ # @overload map_values($map)
1986
+ # @param $map [Map]
1987
+ # @return [List] the list of values, comma-separated
1988
+ # @raise [ArgumentError] if `$map` is not a map
1989
+ def map_values(map)
1990
+ assert_type map, :Map, :map
1991
+ list(to_h(map).values, :comma)
1992
+ end
1993
+ declare :map_values, [:map]
1994
+
1995
+ # Returns whether a map has a value associated with a given key.
1996
+ #
1997
+ # @example
1998
+ # map-has-key(("foo": 1, "bar": 2), "foo") => true
1999
+ # map-has-key(("foo": 1, "bar": 2), "baz") => false
2000
+ # @overload map_has_key($map, $key)
2001
+ # @param $map [Sass::Script::Value::Map]
2002
+ # @param $key [Sass::Script::Value::Base]
2003
+ # @return [Sass::Script::Value::Bool]
2004
+ # @raise [ArgumentError] if `$map` is not a map
2005
+ def map_has_key(map, key)
2006
+ assert_type map, :Map, :map
2007
+ bool(to_h(map).has_key?(key))
2008
+ end
2009
+ declare :map_has_key, [:map, :key]
2010
+
2011
+ # Returns the map of named arguments passed to a function or mixin that
2012
+ # takes a variable argument list. The argument names are strings, and they
2013
+ # do not contain the leading `$`.
2014
+ #
2015
+ # @example
2016
+ # @mixin foo($args...) {
2017
+ # @debug keywords($args); //=> (arg1: val, arg2: val)
2018
+ # }
2019
+ #
2020
+ # @include foo($arg1: val, $arg2: val);
2021
+ # @overload keywords($args)
2022
+ # @param $args [Sass::Script::Value::ArgList]
2023
+ # @return [Sass::Script::Value::Map]
2024
+ # @raise [ArgumentError] if `$args` isn't a variable argument list
2025
+ def keywords(args)
2026
+ assert_type args, :ArgList, :args
2027
+ map(Sass::Util.map_keys(args.keywords.as_stored) {|k| Sass::Script::String.new(k)})
2028
+ end
2029
+ declare :keywords, [:args]
2030
+
2031
+ # Returns one of two values, depending on whether or not `$condition` is
2032
+ # true. Just like in `@if`, all values other than `false` and `null` are
2033
+ # considered to be true.
1303
2034
  #
1304
2035
  # @example
1305
2036
  # if(true, 1px, 2px) => 1px
1306
2037
  # if(false, 1px, 2px) => 2px
1307
- # @param condition [Bool] Whether the first or second value will be returned.
1308
- # @param if_true [Literal] The value that will be returned if `$condition` is true.
1309
- # @param if_false [Literal] The value that will be returned if `$condition` is false.
2038
+ # @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]
2043
+ # @return [Sass::Script::Value::Base] `$if-true` or `$if-false`
1310
2044
  def if(condition, if_true, if_false)
1311
2045
  if condition.to_bool
1312
- if_true
2046
+ perform(if_true)
2047
+ else
2048
+ perform(if_false)
2049
+ end
2050
+ end
2051
+ declare :if, [:condition, :"&if_true", :"&if_false"]
2052
+
2053
+ # Returns a unique CSS identifier. The identifier is returned as an unquoted
2054
+ # string. The identifier returned is only guaranteed to be unique within the
2055
+ # scope of a single Sass run.
2056
+ #
2057
+ # @overload unique_id()
2058
+ # @return [Sass::Script::Value::String]
2059
+ def unique_id
2060
+ generator = Sass::Script::Functions.random_number_generator
2061
+ Thread.current[:sass_last_unique_id] ||= generator.rand(36**8)
2062
+ # avoid the temptation of trying to guess the next unique value.
2063
+ value = (Thread.current[:sass_last_unique_id] += (generator.rand(10) + 1))
2064
+ # the u makes this a legal identifier if it would otherwise start with a number.
2065
+ identifier("u" + value.to_s(36).rjust(8, '0'))
2066
+ end
2067
+ declare :unique_id, []
2068
+
2069
+ # Dynamically calls a function. This can call user-defined
2070
+ # functions, built-in functions, or plain CSS functions. It will
2071
+ # pass along all arguments, including keyword arguments, to the
2072
+ # called function.
2073
+ #
2074
+ # @example
2075
+ # call(rgb, 10, 100, 255) => #0a64ff
2076
+ # call(scale-color, #0a64ff, $lightness: -10%) => #0058ef
2077
+ #
2078
+ # $fn: nth;
2079
+ # call($fn, 2, (a b c)) => b
2080
+ #
2081
+ # @overload call($name, $args...)
2082
+ # @param $name [String] The name of the function to call.
2083
+ def call(name, *args)
2084
+ assert_type name, :String, :name
2085
+ kwargs = args.last.is_a?(Hash) ? args.pop : {}
2086
+ funcall = Sass::Script::Tree::Funcall.new(
2087
+ name.value,
2088
+ args.map {|a| Sass::Script::Tree::Literal.new(a)},
2089
+ Sass::Util.map_vals(kwargs) {|v| Sass::Script::Tree::Literal.new(v)},
2090
+ nil,
2091
+ nil)
2092
+ funcall.options = options
2093
+ perform(funcall)
2094
+ end
2095
+ declare :call, [:name], :var_args => true, :var_kwargs => true
2096
+
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
2099
+ # avoids adding spaces between the argument commas.
2100
+ #
2101
+ # [bug]: http://jes.st/2013/ie7s-css-breaking-content-counter-bug/
2102
+ #
2103
+ # @example
2104
+ # counter(item, ".") => counter(item,".")
2105
+ # @overload counter($args...)
2106
+ # @return [String]
2107
+ def counter(*args)
2108
+ identifier("counter(#{args.map {|a| a.to_s(options)}.join(',')})")
2109
+ end
2110
+ declare :counter, [], :var_args => true
2111
+
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
2114
+ # avoids adding spaces between the argument commas.
2115
+ #
2116
+ # [bug]: http://jes.st/2013/ie7s-css-breaking-content-counter-bug/
2117
+ #
2118
+ # @example
2119
+ # counters(item, ".") => counters(item,".")
2120
+ # @overload counters($args...)
2121
+ # @return [String]
2122
+ def counters(*args)
2123
+ identifier("counters(#{args.map {|a| a.to_s(options)}.join(',')})")
2124
+ end
2125
+ declare :counters, [], :var_args => true
2126
+
2127
+ # Check whether a variable with the given name exists in the current
2128
+ # scope or in the global scope.
2129
+ #
2130
+ # @example
2131
+ # $a-false-value: false;
2132
+ # variable-exists(a-false-value) => true
2133
+ #
2134
+ # 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
2138
+ # the current scope.
2139
+ def variable_exists(name)
2140
+ assert_type name, :String, :name
2141
+ bool(environment.caller.var(name.value))
2142
+ end
2143
+ declare :variable_exists, [:name]
2144
+
2145
+ # Check whether a variable with the given name exists in the global
2146
+ # scope (at the top level of the file).
2147
+ #
2148
+ # @example
2149
+ # $a-false-value: false;
2150
+ # global-variable-exists(a-false-value) => true
2151
+ #
2152
+ # .foo {
2153
+ # $some-var: false;
2154
+ # @if global-variable-exists(some-var) { /* false, doesn't run */ }
2155
+ # }
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
2159
+ # the global scope.
2160
+ def global_variable_exists(name)
2161
+ assert_type name, :String, :name
2162
+ bool(environment.global_env.var(name.value))
2163
+ end
2164
+ declare :global_variable_exists, [:name]
2165
+
2166
+ # Check whether a function with the given name exists.
2167
+ #
2168
+ # @example
2169
+ # function-exists(lighten) => true
2170
+ #
2171
+ # @function myfunc { @return "something"; }
2172
+ # 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.
2176
+ def function_exists(name)
2177
+ assert_type name, :String, :name
2178
+ exists = Sass::Script::Functions.callable?(name.value.tr("-", "_"))
2179
+ exists ||= environment.function(name.value)
2180
+ bool(exists)
2181
+ end
2182
+ declare :function_exists, [:name]
2183
+
2184
+ # Check whether a mixin with the given name exists.
2185
+ #
2186
+ # @example
2187
+ # mixin-exists(nonexistent) => false
2188
+ #
2189
+ # @mixin red-text { color: red; }
2190
+ # 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.
2194
+ def mixin_exists(name)
2195
+ assert_type name, :String, :name
2196
+ bool(environment.mixin(name.value))
2197
+ end
2198
+ declare :mixin_exists, [:name]
2199
+
2200
+ # Return a string containing the value as its Sass representation.
2201
+ #
2202
+ # @param value [Sass::Script::Value::Base] The value to inspect.
2203
+ # @return [Sass::Script::Value::String] A respresentation of the value as
2204
+ # it would be written in Sass.
2205
+ def inspect(value)
2206
+ unquoted_string(value.to_sass)
2207
+ end
2208
+ declare :inspect, [:value]
2209
+
2210
+ # @overload random()
2211
+ # Return a decimal between 0 and 1, inclusive of 0 but not 1.
2212
+ # @return [Sass::Script::Number] A decimal value.
2213
+ # @overload random($limit)
2214
+ # Return an integer between 1 and `$limit`, inclusive of 1 but not `$limit`.
2215
+ # @param $limit [Sass::Script::Value::Number] The maximum of the random integer to be
2216
+ # returned, a positive integer.
2217
+ # @return [Sass::Script::Number] An integer.
2218
+ # @raise [ArgumentError] if the `$limit` is not 1 or greater
2219
+ def random(limit = nil)
2220
+ generator = Sass::Script::Functions.random_number_generator
2221
+ if limit
2222
+ assert_integer limit, "limit"
2223
+ if limit.value < 1
2224
+ raise ArgumentError.new("$limit #{limit} must be greater than or equal to 1")
2225
+ end
2226
+ number(1 + generator.rand(limit.value))
1313
2227
  else
1314
- if_false
2228
+ number(generator.rand)
1315
2229
  end
1316
2230
  end
1317
- declare :if, [:condition, :if_true, :if_false]
2231
+ declare :random, []
2232
+ declare :random, [:limit]
1318
2233
 
1319
2234
  private
1320
2235
 
@@ -1322,16 +2237,18 @@ module Sass::Script
1322
2237
  # another numeric value with the same units.
1323
2238
  # It yields a number to a block to perform the operation and return a number
1324
2239
  def numeric_transformation(value)
1325
- assert_type value, :Number
1326
- Sass::Script::Number.new(yield(value.value), value.numerator_units, value.denominator_units)
2240
+ assert_type value, :Number, :value
2241
+ Sass::Script::Value::Number.new(
2242
+ yield(value.value), value.numerator_units, value.denominator_units)
1327
2243
  end
1328
2244
 
2245
+ # @comment
2246
+ # rubocop:disable ParameterLists
1329
2247
  def _adjust(color, amount, attr, range, op, units = "")
1330
- assert_type color, :Color
1331
- assert_type amount, :Number
1332
- unless range.include?(amount.value)
1333
- raise ArgumentError.new("Amount #{amount} must be between #{range.first}#{units} and #{range.last}#{units}")
1334
- end
2248
+ # rubocop:enable ParameterLists
2249
+ assert_type color, :Color, :color
2250
+ assert_type amount, :Number, :amount
2251
+ Sass::Util.check_range('Amount', range, amount, units)
1335
2252
 
1336
2253
  # TODO: is it worth restricting here,
1337
2254
  # or should we do so in the Color constructor itself,
@@ -1339,5 +2256,17 @@ module Sass::Script
1339
2256
  color.with(attr => Sass::Util.restrict(
1340
2257
  color.send(attr).send(op, amount.value), range))
1341
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
2270
+ end
1342
2271
  end
1343
2272
  end