xass 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (252) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/Gemfile +9 -0
  4. data/Gemfile.lock +39 -0
  5. data/README.md +131 -193
  6. data/lib/initialize.rb +8 -0
  7. data/lib/xass.rb +67 -0
  8. data/spec/secrets.yml +4 -0
  9. data/spec/spec_helper.rb +8 -0
  10. data/spec/test_spec.rb +5 -0
  11. data/template/secrets.yml +2 -0
  12. data/xass.gemspec +15 -0
  13. metadata +53 -294
  14. data/.yardopts +0 -11
  15. data/CONTRIBUTING +0 -3
  16. data/MIT-LICENSE +0 -20
  17. data/Rakefile +0 -349
  18. data/VERSION +0 -1
  19. data/VERSION_NAME +0 -1
  20. data/bin/push +0 -13
  21. data/bin/sass +0 -13
  22. data/bin/sass-convert +0 -12
  23. data/bin/scss +0 -13
  24. data/extra/update_watch.rb +0 -13
  25. data/init.rb +0 -18
  26. data/lib/sass/cache_stores/base.rb +0 -88
  27. data/lib/sass/cache_stores/chain.rb +0 -33
  28. data/lib/sass/cache_stores/filesystem.rb +0 -64
  29. data/lib/sass/cache_stores/memory.rb +0 -47
  30. data/lib/sass/cache_stores/null.rb +0 -25
  31. data/lib/sass/cache_stores.rb +0 -15
  32. data/lib/sass/callbacks.rb +0 -66
  33. data/lib/sass/css.rb +0 -409
  34. data/lib/sass/engine.rb +0 -930
  35. data/lib/sass/environment.rb +0 -101
  36. data/lib/sass/error.rb +0 -201
  37. data/lib/sass/exec.rb +0 -707
  38. data/lib/sass/importers/base.rb +0 -139
  39. data/lib/sass/importers/filesystem.rb +0 -186
  40. data/lib/sass/importers.rb +0 -22
  41. data/lib/sass/logger/base.rb +0 -32
  42. data/lib/sass/logger/log_level.rb +0 -49
  43. data/lib/sass/logger.rb +0 -15
  44. data/lib/sass/media.rb +0 -213
  45. data/lib/sass/plugin/compiler.rb +0 -406
  46. data/lib/sass/plugin/configuration.rb +0 -123
  47. data/lib/sass/plugin/generic.rb +0 -15
  48. data/lib/sass/plugin/merb.rb +0 -48
  49. data/lib/sass/plugin/rack.rb +0 -60
  50. data/lib/sass/plugin/rails.rb +0 -47
  51. data/lib/sass/plugin/staleness_checker.rb +0 -199
  52. data/lib/sass/plugin.rb +0 -133
  53. data/lib/sass/railtie.rb +0 -10
  54. data/lib/sass/repl.rb +0 -57
  55. data/lib/sass/root.rb +0 -7
  56. data/lib/sass/script/arg_list.rb +0 -52
  57. data/lib/sass/script/bool.rb +0 -18
  58. data/lib/sass/script/color.rb +0 -606
  59. data/lib/sass/script/css_lexer.rb +0 -29
  60. data/lib/sass/script/css_parser.rb +0 -31
  61. data/lib/sass/script/funcall.rb +0 -245
  62. data/lib/sass/script/functions.rb +0 -1543
  63. data/lib/sass/script/interpolation.rb +0 -79
  64. data/lib/sass/script/lexer.rb +0 -345
  65. data/lib/sass/script/list.rb +0 -85
  66. data/lib/sass/script/literal.rb +0 -221
  67. data/lib/sass/script/node.rb +0 -99
  68. data/lib/sass/script/null.rb +0 -37
  69. data/lib/sass/script/number.rb +0 -453
  70. data/lib/sass/script/operation.rb +0 -110
  71. data/lib/sass/script/parser.rb +0 -502
  72. data/lib/sass/script/string.rb +0 -51
  73. data/lib/sass/script/string_interpolation.rb +0 -103
  74. data/lib/sass/script/unary_operation.rb +0 -69
  75. data/lib/sass/script/variable.rb +0 -58
  76. data/lib/sass/script.rb +0 -39
  77. data/lib/sass/scss/css_parser.rb +0 -36
  78. data/lib/sass/scss/parser.rb +0 -1180
  79. data/lib/sass/scss/rx.rb +0 -133
  80. data/lib/sass/scss/script_lexer.rb +0 -15
  81. data/lib/sass/scss/script_parser.rb +0 -25
  82. data/lib/sass/scss/static_parser.rb +0 -54
  83. data/lib/sass/scss.rb +0 -16
  84. data/lib/sass/selector/abstract_sequence.rb +0 -94
  85. data/lib/sass/selector/comma_sequence.rb +0 -92
  86. data/lib/sass/selector/sequence.rb +0 -507
  87. data/lib/sass/selector/simple.rb +0 -119
  88. data/lib/sass/selector/simple_sequence.rb +0 -215
  89. data/lib/sass/selector.rb +0 -452
  90. data/lib/sass/shared.rb +0 -76
  91. data/lib/sass/supports.rb +0 -229
  92. data/lib/sass/tree/charset_node.rb +0 -22
  93. data/lib/sass/tree/comment_node.rb +0 -82
  94. data/lib/sass/tree/content_node.rb +0 -9
  95. data/lib/sass/tree/css_import_node.rb +0 -60
  96. data/lib/sass/tree/debug_node.rb +0 -18
  97. data/lib/sass/tree/directive_node.rb +0 -42
  98. data/lib/sass/tree/each_node.rb +0 -24
  99. data/lib/sass/tree/extend_node.rb +0 -36
  100. data/lib/sass/tree/for_node.rb +0 -36
  101. data/lib/sass/tree/function_node.rb +0 -34
  102. data/lib/sass/tree/if_node.rb +0 -52
  103. data/lib/sass/tree/import_node.rb +0 -75
  104. data/lib/sass/tree/media_node.rb +0 -58
  105. data/lib/sass/tree/mixin_def_node.rb +0 -38
  106. data/lib/sass/tree/mixin_node.rb +0 -39
  107. data/lib/sass/tree/node.rb +0 -196
  108. data/lib/sass/tree/prop_node.rb +0 -152
  109. data/lib/sass/tree/return_node.rb +0 -18
  110. data/lib/sass/tree/root_node.rb +0 -78
  111. data/lib/sass/tree/rule_node.rb +0 -132
  112. data/lib/sass/tree/supports_node.rb +0 -51
  113. data/lib/sass/tree/trace_node.rb +0 -32
  114. data/lib/sass/tree/variable_node.rb +0 -30
  115. data/lib/sass/tree/visitors/base.rb +0 -75
  116. data/lib/sass/tree/visitors/check_nesting.rb +0 -147
  117. data/lib/sass/tree/visitors/convert.rb +0 -316
  118. data/lib/sass/tree/visitors/cssize.rb +0 -241
  119. data/lib/sass/tree/visitors/deep_copy.rb +0 -102
  120. data/lib/sass/tree/visitors/extend.rb +0 -68
  121. data/lib/sass/tree/visitors/perform.rb +0 -446
  122. data/lib/sass/tree/visitors/set_options.rb +0 -125
  123. data/lib/sass/tree/visitors/to_css.rb +0 -228
  124. data/lib/sass/tree/warn_node.rb +0 -18
  125. data/lib/sass/tree/while_node.rb +0 -18
  126. data/lib/sass/util/multibyte_string_scanner.rb +0 -155
  127. data/lib/sass/util/subset_map.rb +0 -109
  128. data/lib/sass/util/test.rb +0 -10
  129. data/lib/sass/util.rb +0 -948
  130. data/lib/sass/version.rb +0 -126
  131. data/lib/sass.rb +0 -95
  132. data/rails/init.rb +0 -1
  133. data/test/Gemfile +0 -3
  134. data/test/Gemfile.lock +0 -10
  135. data/test/sass/cache_test.rb +0 -89
  136. data/test/sass/callbacks_test.rb +0 -61
  137. data/test/sass/conversion_test.rb +0 -1760
  138. data/test/sass/css2sass_test.rb +0 -458
  139. data/test/sass/data/hsl-rgb.txt +0 -319
  140. data/test/sass/engine_test.rb +0 -3244
  141. data/test/sass/exec_test.rb +0 -86
  142. data/test/sass/extend_test.rb +0 -1482
  143. data/test/sass/fixtures/test_staleness_check_across_importers.css +0 -1
  144. data/test/sass/fixtures/test_staleness_check_across_importers.scss +0 -1
  145. data/test/sass/functions_test.rb +0 -1139
  146. data/test/sass/importer_test.rb +0 -192
  147. data/test/sass/logger_test.rb +0 -58
  148. data/test/sass/mock_importer.rb +0 -49
  149. data/test/sass/more_results/more1.css +0 -9
  150. data/test/sass/more_results/more1_with_line_comments.css +0 -26
  151. data/test/sass/more_results/more_import.css +0 -29
  152. data/test/sass/more_templates/_more_partial.sass +0 -2
  153. data/test/sass/more_templates/more1.sass +0 -23
  154. data/test/sass/more_templates/more_import.sass +0 -11
  155. data/test/sass/plugin_test.rb +0 -564
  156. data/test/sass/results/alt.css +0 -4
  157. data/test/sass/results/basic.css +0 -9
  158. data/test/sass/results/cached_import_option.css +0 -3
  159. data/test/sass/results/compact.css +0 -5
  160. data/test/sass/results/complex.css +0 -86
  161. data/test/sass/results/compressed.css +0 -1
  162. data/test/sass/results/expanded.css +0 -19
  163. data/test/sass/results/filename_fn.css +0 -3
  164. data/test/sass/results/if.css +0 -3
  165. data/test/sass/results/import.css +0 -31
  166. data/test/sass/results/import_charset.css +0 -5
  167. data/test/sass/results/import_charset_1_8.css +0 -5
  168. data/test/sass/results/import_charset_ibm866.css +0 -5
  169. data/test/sass/results/import_content.css +0 -1
  170. data/test/sass/results/line_numbers.css +0 -49
  171. data/test/sass/results/mixins.css +0 -95
  172. data/test/sass/results/multiline.css +0 -24
  173. data/test/sass/results/nested.css +0 -22
  174. data/test/sass/results/options.css +0 -1
  175. data/test/sass/results/parent_ref.css +0 -13
  176. data/test/sass/results/script.css +0 -16
  177. data/test/sass/results/scss_import.css +0 -31
  178. data/test/sass/results/scss_importee.css +0 -2
  179. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +0 -1
  180. data/test/sass/results/subdir/subdir.css +0 -3
  181. data/test/sass/results/units.css +0 -11
  182. data/test/sass/results/warn_imported.css +0 -0
  183. data/test/sass/script_conversion_test.rb +0 -299
  184. data/test/sass/script_test.rb +0 -622
  185. data/test/sass/scss/css_test.rb +0 -1100
  186. data/test/sass/scss/rx_test.rb +0 -156
  187. data/test/sass/scss/scss_test.rb +0 -2106
  188. data/test/sass/scss/test_helper.rb +0 -37
  189. data/test/sass/templates/_cached_import_option_partial.scss +0 -1
  190. data/test/sass/templates/_double_import_loop2.sass +0 -1
  191. data/test/sass/templates/_filename_fn_import.scss +0 -11
  192. data/test/sass/templates/_imported_charset_ibm866.sass +0 -4
  193. data/test/sass/templates/_imported_charset_utf8.sass +0 -4
  194. data/test/sass/templates/_imported_content.sass +0 -3
  195. data/test/sass/templates/_partial.sass +0 -2
  196. data/test/sass/templates/_same_name_different_partiality.scss +0 -1
  197. data/test/sass/templates/alt.sass +0 -16
  198. data/test/sass/templates/basic.sass +0 -23
  199. data/test/sass/templates/bork1.sass +0 -2
  200. data/test/sass/templates/bork2.sass +0 -2
  201. data/test/sass/templates/bork3.sass +0 -2
  202. data/test/sass/templates/bork4.sass +0 -2
  203. data/test/sass/templates/bork5.sass +0 -3
  204. data/test/sass/templates/cached_import_option.scss +0 -3
  205. data/test/sass/templates/compact.sass +0 -17
  206. data/test/sass/templates/complex.sass +0 -305
  207. data/test/sass/templates/compressed.sass +0 -15
  208. data/test/sass/templates/double_import_loop1.sass +0 -1
  209. data/test/sass/templates/expanded.sass +0 -17
  210. data/test/sass/templates/filename_fn.scss +0 -18
  211. data/test/sass/templates/if.sass +0 -11
  212. data/test/sass/templates/import.sass +0 -12
  213. data/test/sass/templates/import_charset.sass +0 -9
  214. data/test/sass/templates/import_charset_1_8.sass +0 -6
  215. data/test/sass/templates/import_charset_ibm866.sass +0 -11
  216. data/test/sass/templates/import_content.sass +0 -4
  217. data/test/sass/templates/importee.less +0 -2
  218. data/test/sass/templates/importee.sass +0 -19
  219. data/test/sass/templates/line_numbers.sass +0 -13
  220. data/test/sass/templates/mixin_bork.sass +0 -5
  221. data/test/sass/templates/mixins.sass +0 -76
  222. data/test/sass/templates/multiline.sass +0 -20
  223. data/test/sass/templates/nested.sass +0 -25
  224. data/test/sass/templates/nested_bork1.sass +0 -2
  225. data/test/sass/templates/nested_bork2.sass +0 -2
  226. data/test/sass/templates/nested_bork3.sass +0 -2
  227. data/test/sass/templates/nested_bork4.sass +0 -2
  228. data/test/sass/templates/nested_import.sass +0 -2
  229. data/test/sass/templates/nested_mixin_bork.sass +0 -6
  230. data/test/sass/templates/options.sass +0 -2
  231. data/test/sass/templates/parent_ref.sass +0 -25
  232. data/test/sass/templates/same_name_different_ext.sass +0 -2
  233. data/test/sass/templates/same_name_different_ext.scss +0 -1
  234. data/test/sass/templates/same_name_different_partiality.scss +0 -1
  235. data/test/sass/templates/script.sass +0 -101
  236. data/test/sass/templates/scss_import.scss +0 -11
  237. data/test/sass/templates/scss_importee.scss +0 -1
  238. data/test/sass/templates/single_import_loop.sass +0 -1
  239. data/test/sass/templates/subdir/import_up1.scss +0 -1
  240. data/test/sass/templates/subdir/import_up2.scss +0 -1
  241. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +0 -2
  242. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +0 -3
  243. data/test/sass/templates/subdir/subdir.sass +0 -6
  244. data/test/sass/templates/units.sass +0 -11
  245. data/test/sass/templates/warn.sass +0 -3
  246. data/test/sass/templates/warn_imported.sass +0 -4
  247. data/test/sass/test_helper.rb +0 -8
  248. data/test/sass/util/multibyte_string_scanner_test.rb +0 -147
  249. data/test/sass/util/subset_map_test.rb +0 -91
  250. data/test/sass/util_test.rb +0 -382
  251. data/test/test_helper.rb +0 -80
  252. /data/{test/sass/results/warn.css → template/files/.gitkeep} +0 -0
@@ -1,1543 +0,0 @@
1
- module Sass::Script
2
- # Methods in this module are accessible from the SassScript context.
3
- # For example, you can write
4
- #
5
- # $color: hsl(120deg, 100%, 50%)
6
- #
7
- # and it will call {Sass::Script::Functions#hsl}.
8
- #
9
- # The following functions are provided:
10
- #
11
- # *Note: These functions are described in more detail below.*
12
- #
13
- # ## RGB Functions
14
- #
15
- # \{#rgb rgb($red, $green, $blue)}
16
- # : Creates a {Color} from red, green, and blue values.
17
- #
18
- # \{#rgba rgba($red, $green, $blue, $alpha)}
19
- # : Creates a {Color} from red, green, blue, and alpha values.
20
- #
21
- # \{#red red($color)}
22
- # : Gets the red component of a color.
23
- #
24
- # \{#green green($color)}
25
- # : Gets the green component of a color.
26
- #
27
- # \{#blue blue($color)}
28
- # : Gets the blue component of a color.
29
- #
30
- # \{#mix mix($color-1, $color-2, \[$weight\])}
31
- # : Mixes two colors together.
32
- #
33
- # ## HSL Functions
34
- #
35
- # \{#hsl hsl($hue, $saturation, $lightness)}
36
- # : Creates a {Color} from hue, saturation, and lightness values.
37
- #
38
- # \{#hsla hsla($hue, $saturation, $lightness, $alpha)}
39
- # : Creates a {Color} from hue, saturation, lightness, and alpha
40
- # values.
41
- #
42
- # \{#hue hue($color)}
43
- # : Gets the hue component of a color.
44
- #
45
- # \{#saturation saturation($color)}
46
- # : Gets the saturation component of a color.
47
- #
48
- # \{#lightness lightness($color)}
49
- # : Gets the lightness component of a color.
50
- #
51
- # \{#adjust_hue adjust-hue($color, $degrees)}
52
- # : Changes the hue of a color.
53
- #
54
- # \{#lighten lighten($color, $amount)}
55
- # : Makes a color lighter.
56
- #
57
- # \{#darken darken($color, $amount)}
58
- # : Makes a color darker.
59
- #
60
- # \{#saturate saturate($color, $amount)}
61
- # : Makes a color more saturated.
62
- #
63
- # \{#desaturate desaturate($color, $amount)}
64
- # : Makes a color less saturated.
65
- #
66
- # \{#grayscale grayscale($color)}
67
- # : Converts a color to grayscale.
68
- #
69
- # \{#complement complement($color)}
70
- # : Returns the complement of a color.
71
- #
72
- # \{#invert invert($color)}
73
- # : Returns the inverse of a color.
74
- #
75
- # ## Opacity Functions
76
- #
77
- # \{#alpha alpha($color)} / \{#opacity opacity($color)}
78
- # : Gets the alpha component (opacity) of a color.
79
- #
80
- # \{#rgba rgba($color, $alpha)}
81
- # : Changes the alpha component for a color.
82
- #
83
- # \{#opacify opacify($color, $amount)} / \{#fade_in fade-in($color, $amount)}
84
- # : Makes a color more opaque.
85
- #
86
- # \{#transparentize transparentize($color, $amount)} / \{#fade_out fade-out($color, $amount)}
87
- # : Makes a color more transparent.
88
- #
89
- # ## Other Color Functions
90
- #
91
- # \{#adjust_color adjust-color($color, \[$red\], \[$green\], \[$blue\], \[$hue\], \[$saturation\], \[$lightness\], \[$alpha\])}
92
- # : Increases or decreases one or more components of a color.
93
- #
94
- # \{#scale_color scale-color($color, \[$red\], \[$green\], \[$blue\], \[$saturation\], \[$lightness\], \[$alpha\])}
95
- # : Fluidly scales one or more properties of a color.
96
- #
97
- # \{#change_color change-color($color, \[$red\], \[$green\], \[$blue\], \[$hue\], \[$saturation\], \[$lightness\], \[$alpha\])}
98
- # : Changes one or more properties of a color.
99
- #
100
- # \{#ie_hex_str ie-hex-str($color)}
101
- # : Converts a color into the format understood by IE filters.
102
- #
103
- # ## String Functions
104
- #
105
- # \{#unquote unquote($string)}
106
- # : Removes quotes from a string.
107
- #
108
- # \{#quote quote($string)}
109
- # : Adds quotes to a string.
110
- #
111
- # ## Number Functions
112
- #
113
- # \{#percentage percentage($value)}
114
- # : Converts a unitless number to a percentage.
115
- #
116
- # \{#round round($value)}
117
- # : Rounds a number to the nearest whole number.
118
- #
119
- # \{#ceil ceil($value)}
120
- # : Rounds a number up to the next whole number.
121
- #
122
- # \{#floor floor($value)}
123
- # : Rounds a number down to the previous whole number.
124
- #
125
- # \{#abs abs($value)}
126
- # : Returns the absolute value of a number.
127
- #
128
- # \{#min min($numbers...)\}
129
- # : Finds the minimum of several numbers.
130
- #
131
- # \{#max max($numbers...)\}
132
- # : Finds the maximum of several numbers.
133
- #
134
- # ## List Functions {#list-functions}
135
- #
136
- # \{#length length($list)}
137
- # : Returns the length of a list.
138
- #
139
- # \{#nth nth($list, $n)}
140
- # : Returns a specific item in a list.
141
- #
142
- # \{#join join($list1, $list2, \[$separator\])}
143
- # : Joins together two lists into one.
144
- #
145
- # \{#append append($list1, $val, \[$separator\])}
146
- # : Appends a single value onto the end of a list.
147
- #
148
- # \{#zip zip($lists...)}
149
- # : Combines several lists into a single multidimensional list.
150
- #
151
- # \{#index index($list, $value)}
152
- # : Returns the position of a value within a list.
153
- #
154
- # ## Introspection Functions
155
- #
156
- # \{#type_of type-of($value)}
157
- # : Returns the type of a value.
158
- #
159
- # \{#unit unit($number)}
160
- # : Returns the unit(s) associated with a number.
161
- #
162
- # \{#unitless unitless($number)}
163
- # : Returns whether a number has units.
164
- #
165
- # \{#comparable comparable($number-1, $number-2)}
166
- # : Returns whether two numbers can be added, subtracted, or compared.
167
- #
168
- # ## Miscellaneous Functions
169
- #
170
- # \{#if if($condition, $if-true, $if-false)}
171
- # : Returns one of two values, depending on whether or not `$condition` is
172
- # true.
173
- #
174
- # ## Adding Custom Functions
175
- #
176
- # New Sass functions can be added by adding Ruby methods to this module.
177
- # For example:
178
- #
179
- # module Sass::Script::Functions
180
- # def reverse(string)
181
- # assert_type string, :String
182
- # Sass::Script::String.new(string.value.reverse)
183
- # end
184
- # declare :reverse, :args => [:string]
185
- # end
186
- #
187
- # Calling {declare} tells Sass the argument names for your function.
188
- # If omitted, the function will still work, but will not be able to accept keyword arguments.
189
- # {declare} can also allow your function to take arbitrary keyword arguments.
190
- #
191
- # There are a few things to keep in mind when modifying this module.
192
- # First of all, the arguments passed are {Sass::Script::Literal} objects.
193
- # Literal objects are also expected to be returned.
194
- # This means that Ruby values must be unwrapped and wrapped.
195
- #
196
- # Most Literal objects support the {Sass::Script::Literal#value value} accessor
197
- # for getting their Ruby values.
198
- # Color objects, though, must be accessed using {Sass::Script::Color#rgb rgb},
199
- # {Sass::Script::Color#red red}, {Sass::Script::Color#blue green}, or {Sass::Script::Color#blue blue}.
200
- #
201
- # Second, making Ruby functions accessible from Sass introduces the temptation
202
- # to do things like database access within stylesheets.
203
- # This is generally a bad idea;
204
- # since Sass files are by default only compiled once,
205
- # dynamic code is not a great fit.
206
- #
207
- # If you really, really need to compile Sass on each request,
208
- # first make sure you have adequate caching set up.
209
- # Then you can use {Sass::Engine} to render the code,
210
- # using the {file:SASS_REFERENCE.md#custom-option `options` parameter}
211
- # to pass in data that {EvaluationContext#options can be accessed}
212
- # from your Sass functions.
213
- #
214
- # Within one of the functions in this module,
215
- # methods of {EvaluationContext} can be used.
216
- #
217
- # ### Caveats
218
- #
219
- # When creating new {Literal} objects within functions,
220
- # be aware that it's not safe to call {Literal#to_s #to_s}
221
- # (or other methods that use the string representation)
222
- # on those objects without first setting {Node#options= the #options attribute}.
223
- module Functions
224
- @signatures = {}
225
-
226
- # A class representing a Sass function signature.
227
- #
228
- # @attr args [Array<Symbol>] The names of the arguments to the function.
229
- # @attr var_args [Boolean] Whether the function takes a variable number of arguments.
230
- # @attr var_kwargs [Boolean] Whether the function takes an arbitrary set of keyword arguments.
231
- Signature = Struct.new(:args, :var_args, :var_kwargs)
232
-
233
- # Declare a Sass signature for a Ruby-defined function.
234
- # This includes the names of the arguments,
235
- # whether the function takes a variable number of arguments,
236
- # and whether the function takes an arbitrary set of keyword arguments.
237
- #
238
- # It's not necessary to declare a signature for a function.
239
- # However, without a signature it won't support keyword arguments.
240
- #
241
- # A single function can have multiple signatures declared
242
- # as long as each one takes a different number of arguments.
243
- # It's also possible to declare multiple signatures
244
- # that all take the same number of arguments,
245
- # but none of them but the first will be used
246
- # unless the user uses keyword arguments.
247
- #
248
- # @example
249
- # declare :rgba, [:hex, :alpha]
250
- # declare :rgba, [:red, :green, :blue, :alpha]
251
- # declare :accepts_anything, [], :var_args => true, :var_kwargs => true
252
- # declare :some_func, [:foo, :bar, :baz], :var_kwargs => true
253
- #
254
- # @param method_name [Symbol] The name of the method
255
- # whose signature is being declared.
256
- # @param args [Array<Symbol>] The names of the arguments for the function signature.
257
- # @option options :var_args [Boolean] (false)
258
- # Whether the function accepts a variable number of (unnamed) arguments
259
- # in addition to the named arguments.
260
- # @option options :var_kwargs [Boolean] (false)
261
- # Whether the function accepts other keyword arguments
262
- # in addition to those in `:args`.
263
- # If this is true, the Ruby function will be passed a hash from strings
264
- # to {Sass::Script::Literal}s as the last argument.
265
- # In addition, if this is true and `:var_args` is not,
266
- # Sass will ensure that the last argument passed is a hash.
267
- def self.declare(method_name, args, options = {})
268
- @signatures[method_name] ||= []
269
- @signatures[method_name] << Signature.new(
270
- args.map {|s| s.to_s},
271
- options[:var_args],
272
- options[:var_kwargs])
273
- end
274
-
275
- # Determine the correct signature for the number of arguments
276
- # passed in for a given function.
277
- # If no signatures match, the first signature is returned for error messaging.
278
- #
279
- # @param method_name [Symbol] The name of the Ruby function to be called.
280
- # @param arg_arity [Number] The number of unnamed arguments the function was passed.
281
- # @param kwarg_arity [Number] The number of keyword arguments the function was passed.
282
- #
283
- # @return [{Symbol => Object}, nil]
284
- # The signature options for the matching signature,
285
- # or nil if no signatures are declared for this function. See {declare}.
286
- def self.signature(method_name, arg_arity, kwarg_arity)
287
- return unless @signatures[method_name]
288
- @signatures[method_name].each do |signature|
289
- return signature if signature.args.size == arg_arity + kwarg_arity
290
- next unless signature.args.size < arg_arity + kwarg_arity
291
-
292
- # We have enough args.
293
- # Now we need to figure out which args are varargs
294
- # and if the signature allows them.
295
- t_arg_arity, t_kwarg_arity = arg_arity, kwarg_arity
296
- if signature.args.size > t_arg_arity
297
- # we transfer some kwargs arity to args arity
298
- # if it does not have enough args -- assuming the names will work out.
299
- t_kwarg_arity -= (signature.args.size - t_arg_arity)
300
- t_arg_arity = signature.args.size
301
- end
302
-
303
- if ( t_arg_arity == signature.args.size || t_arg_arity > signature.args.size && signature.var_args ) &&
304
- (t_kwarg_arity == 0 || t_kwarg_arity > 0 && signature.var_kwargs)
305
- return signature
306
- end
307
- end
308
- @signatures[method_name].first
309
- end
310
-
311
- # The context in which methods in {Script::Functions} are evaluated.
312
- # That means that all instance methods of {EvaluationContext}
313
- # are available to use in functions.
314
- class EvaluationContext
315
- include Functions
316
-
317
- # The options hash for the {Sass::Engine} that is processing the function call
318
- #
319
- # @return [{Symbol => Object}]
320
- attr_reader :options
321
-
322
- # @param options [{Symbol => Object}] See \{#options}
323
- def initialize(options)
324
- @options = options
325
- end
326
-
327
- # Asserts that the type of a given SassScript value
328
- # is the expected type (designated by a symbol).
329
- #
330
- # Valid types are `:Bool`, `:Color`, `:Number`, and `:String`.
331
- # Note that `:String` will match both double-quoted strings
332
- # and unquoted identifiers.
333
- #
334
- # @example
335
- # assert_type value, :String
336
- # assert_type value, :Number
337
- # @param value [Sass::Script::Literal] A SassScript value
338
- # @param type [Symbol] The name of the type the value is expected to be
339
- # @param name [String, Symbol, nil] The name of the argument.
340
- def assert_type(value, type, name = nil)
341
- return if value.is_a?(Sass::Script.const_get(type))
342
- err = "#{value.inspect} is not a #{type.to_s.downcase}"
343
- err = "$#{name.to_s.gsub('_', '-')}: " + err if name
344
- raise ArgumentError.new(err)
345
- end
346
- end
347
-
348
- class << self
349
- # Returns whether user function with a given name exists.
350
- #
351
- # @param function_name [String]
352
- # @return [Boolean]
353
- alias_method :callable?, :public_method_defined?
354
-
355
- private
356
- def include(*args)
357
- r = super
358
- # We have to re-include ourselves into EvaluationContext to work around
359
- # an icky Ruby restriction.
360
- EvaluationContext.send :include, self
361
- r
362
- end
363
- end
364
-
365
- # Creates a {Color} object from red, green, and blue values.
366
- #
367
- # @see #rgba
368
- # @overload rgb($red, $green, $blue)
369
- # @param $red [Number] The amount of red in the color. Must be between 0 and
370
- # 255 inclusive, or between `0%` and `100%` inclusive
371
- # @param $green [Number] The amount of green in the color. Must be between 0
372
- # and 255 inclusive, or between `0%` and `100%` inclusive
373
- # @param $blue [Number] The amount of blue in the color. Must be between 0
374
- # and 255 inclusive, or between `0%` and `100%` inclusive
375
- # @return [Color]
376
- # @raise [ArgumentError] if any parameter is the wrong type or out of bounds
377
- def rgb(red, green, blue)
378
- assert_type red, :Number, :red
379
- assert_type green, :Number, :green
380
- assert_type blue, :Number, :blue
381
-
382
- Color.new([[red, :red], [green, :green], [blue, :blue]].map do |(c, name)|
383
- v = c.value
384
- if c.numerator_units == ["%"] && c.denominator_units.empty?
385
- v = Sass::Util.check_range("$#{name}: Color value", 0..100, c, '%')
386
- v * 255 / 100.0
387
- else
388
- Sass::Util.check_range("$#{name}: Color value", 0..255, c)
389
- end
390
- end)
391
- end
392
- declare :rgb, [:red, :green, :blue]
393
-
394
- # Creates a {Color} from red, green, blue, and alpha values.
395
- # @see #rgb
396
- #
397
- # @overload rgba($red, $green, $blue, $alpha)
398
- # @param $red [Number] The amount of red in the color. Must be between 0
399
- # and 255 inclusive
400
- # @param $green [Number] The amount of green in the color. Must be between
401
- # 0 and 255 inclusive
402
- # @param $blue [Number] The amount of blue in the color. Must be between 0
403
- # and 255 inclusive
404
- # @param $alpha [Number] The opacity of the color. Must be between 0 and 1
405
- # inclusive
406
- # @return [Color]
407
- # @raise [ArgumentError] if any parameter is the wrong type or out of
408
- # bounds
409
- #
410
- # @overload rgba($color, $alpha)
411
- # Sets the opacity of an existing color.
412
- #
413
- # @example
414
- # rgba(#102030, 0.5) => rgba(16, 32, 48, 0.5)
415
- # rgba(blue, 0.2) => rgba(0, 0, 255, 0.2)
416
- #
417
- # @param $color [Color] The color whose opacity will be changed.
418
- # @param $alpha [Number] The new opacity of the color. Must be between 0
419
- # and 1 inclusive
420
- # @return [Color]
421
- # @raise [ArgumentError] if `$alpha` is out of bounds or either parameter
422
- # is the wrong type
423
- def rgba(*args)
424
- case args.size
425
- when 2
426
- color, alpha = args
427
-
428
- assert_type color, :Color, :color
429
- assert_type alpha, :Number, :alpha
430
-
431
- Sass::Util.check_range('Alpha channel', 0..1, alpha)
432
- color.with(:alpha => alpha.value)
433
- when 4
434
- red, green, blue, alpha = args
435
- rgba(rgb(red, green, blue), alpha)
436
- else
437
- raise ArgumentError.new("wrong number of arguments (#{args.size} for 4)")
438
- end
439
- end
440
- declare :rgba, [:red, :green, :blue, :alpha]
441
- declare :rgba, [:color, :alpha]
442
-
443
- # Creates a {Color} from hue, saturation, and lightness values. Uses the
444
- # algorithm from the [CSS3 spec][].
445
- #
446
- # [CSS3 spec]: http://www.w3.org/TR/css3-color/#hsl-color
447
- #
448
- # @see #hsla
449
- # @overload hsl($hue, $saturation, $lightness)
450
- # @param $hue [Number] The hue of the color. Should be between 0 and 360
451
- # degrees, inclusive
452
- # @param $saturation [Number] The saturation of the color. Must be between
453
- # `0%` and `100%`, inclusive
454
- # @param $lightness [Number] The lightness of the color. Must be between
455
- # `0%` and `100%`, inclusive
456
- # @return [Color]
457
- # @raise [ArgumentError] if `$saturation` or `$lightness` are out of bounds
458
- # or any parameter is the wrong type
459
- def hsl(hue, saturation, lightness)
460
- hsla(hue, saturation, lightness, Number.new(1))
461
- end
462
- declare :hsl, [:hue, :saturation, :lightness]
463
-
464
- # Creates a {Color} from hue, saturation, lightness, and alpha
465
- # values. Uses the algorithm from the [CSS3 spec][].
466
- #
467
- # [CSS3 spec]: http://www.w3.org/TR/css3-color/#hsl-color
468
- #
469
- # @see #hsl
470
- # @overload hsla($hue, $saturation, $lightness, $alpha)
471
- # @param $hue [Number] The hue of the color. Should be between 0 and 360
472
- # degrees, inclusive
473
- # @param $saturation [Number] The saturation of the color. Must be between
474
- # `0%` and `100%`, inclusive
475
- # @param $lightness [Number] The lightness of the color. Must be between
476
- # `0%` and `100%`, inclusive
477
- # @param $alpha [Number] The opacity of the color. Must be between 0 and 1,
478
- # inclusive
479
- # @return [Color]
480
- # @raise [ArgumentError] if `$saturation`, `$lightness`, or `$alpha` are out
481
- # of bounds or any parameter is the wrong type
482
- def hsla(hue, saturation, lightness, alpha)
483
- assert_type hue, :Number, :hue
484
- assert_type saturation, :Number, :saturation
485
- assert_type lightness, :Number, :lightness
486
- assert_type alpha, :Number, :alpha
487
-
488
- Sass::Util.check_range('Alpha channel', 0..1, alpha)
489
-
490
- h = hue.value
491
- s = Sass::Util.check_range('Saturation', 0..100, saturation, '%')
492
- l = Sass::Util.check_range('Lightness', 0..100, lightness, '%')
493
-
494
- Color.new(:hue => h, :saturation => s, :lightness => l, :alpha => alpha.value)
495
- end
496
- declare :hsla, [:hue, :saturation, :lightness, :alpha]
497
-
498
- # Gets the red component of a color. Calculated from HSL where necessary via
499
- # [this algorithm][hsl-to-rgb].
500
- #
501
- # [hsl-to-rgb]: http://www.w3.org/TR/css3-color/#hsl-color
502
- #
503
- # @overload red($color)
504
- # @param $color [Color]
505
- # @return [Number] The red component, between 0 and 255 inclusive
506
- # @raise [ArgumentError] if `$color` isn't a color
507
- def red(color)
508
- assert_type color, :Color, :color
509
- Sass::Script::Number.new(color.red)
510
- end
511
- declare :red, [:color]
512
-
513
- # Gets the green component of a color. Calculated from HSL where necessary
514
- # via [this algorithm][hsl-to-rgb].
515
- #
516
- # [hsl-to-rgb]: http://www.w3.org/TR/css3-color/#hsl-color
517
- #
518
- # @overload green($color)
519
- # @param $color [Color]
520
- # @return [Number] The green component, between 0 and 255 inclusive
521
- # @raise [ArgumentError] if `$color` isn't a color
522
- def green(color)
523
- assert_type color, :Color, :color
524
- Sass::Script::Number.new(color.green)
525
- end
526
- declare :green, [:color]
527
-
528
- # Gets the blue component of a color. Calculated from HSL where necessary
529
- # via [this algorithm][hsl-to-rgb].
530
- #
531
- # [hsl-to-rgb]: http://www.w3.org/TR/css3-color/#hsl-color
532
- #
533
- # @overload blue($color)
534
- # @param $color [Color]
535
- # @return [Number] The blue component, between 0 and 255 inclusive
536
- # @raise [ArgumentError] if `$color` isn't a color
537
- def blue(color)
538
- assert_type color, :Color, :color
539
- Sass::Script::Number.new(color.blue)
540
- end
541
- declare :blue, [:color]
542
-
543
- # Returns the hue component of a color. See [the CSS3 HSL
544
- # specification][hsl]. Calculated from RGB where necessary via [this
545
- # algorithm][rgb-to-hsl].
546
- #
547
- # [hsl]: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
548
- # [rgb-to-hsl]: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
549
- #
550
- # @overload hue($color)
551
- # @param $color [Color]
552
- # @return [Number] The hue component, between 0deg and 360deg
553
- # @raise [ArgumentError] if `$color` isn't a color
554
- def hue(color)
555
- assert_type color, :Color, :color
556
- Sass::Script::Number.new(color.hue, ["deg"])
557
- end
558
- declare :hue, [:color]
559
-
560
- # Returns the saturation component of a color. See [the CSS3 HSL
561
- # specification][hsl]. Calculated from RGB where necessary via [this
562
- # algorithm][rgb-to-hsl].
563
- #
564
- # [hsl]: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
565
- # [rgb-to-hsl]: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
566
- #
567
- # @overload saturation($color)
568
- # @param $color [Color]
569
- # @return [Number] The saturation component, between 0% and 100%
570
- # @raise [ArgumentError] if `$color` isn't a color
571
- def saturation(color)
572
- assert_type color, :Color, :color
573
- Sass::Script::Number.new(color.saturation, ["%"])
574
- end
575
- declare :saturation, [:color]
576
-
577
- # Returns the lightness component of a color. See [the CSS3 HSL
578
- # specification][hsl]. Calculated from RGB where necessary via [this
579
- # algorithm][rgb-to-hsl].
580
- #
581
- # [hsl]: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
582
- # [rgb-to-hsl]: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
583
- #
584
- # @overload lightness($color)
585
- # @param $color [Color]
586
- # @return [Number] The lightness component, between 0% and 100%
587
- # @raise [ArgumentError] if `$color` isn't a color
588
- def lightness(color)
589
- assert_type color, :Color, :color
590
- Sass::Script::Number.new(color.lightness, ["%"])
591
- end
592
- declare :lightness, [:color]
593
-
594
- # Returns the alpha component (opacity) of a color. This is 1 unless
595
- # otherwise specified.
596
- #
597
- # This function also supports the proprietary Microsoft `alpha(opacity=20)`
598
- # syntax as a special case.
599
- #
600
- # @overload alpha($color)
601
- # @param $color [Color]
602
- # @return [Number] The alpha component, between 0 and 1
603
- # @raise [ArgumentError] if `$color` isn't a color
604
- def alpha(*args)
605
- if args.all? do |a|
606
- a.is_a?(Sass::Script::String) && a.type == :identifier &&
607
- a.value =~ /^[a-zA-Z]+\s*=/
608
- end
609
- # Support the proprietary MS alpha() function
610
- return Sass::Script::String.new("alpha(#{args.map {|a| a.to_s}.join(", ")})")
611
- end
612
-
613
- raise ArgumentError.new("wrong number of arguments (#{args.size} for 1)") if args.size != 1
614
-
615
- assert_type args.first, :Color, :color
616
- Sass::Script::Number.new(args.first.alpha)
617
- end
618
- declare :alpha, [:color]
619
-
620
- # Returns the alpha component (opacity) of a color. This is 1 unless
621
- # otherwise specified.
622
- #
623
- # @overload opacity($color)
624
- # @param $color [Color]
625
- # @return [Number] The alpha component, between 0 and 1
626
- # @raise [ArgumentError] if `$color` isn't a color
627
- def opacity(color)
628
- return Sass::Script::String.new("opacity(#{color})") if color.is_a?(Sass::Script::Number)
629
- assert_type color, :Color, :color
630
- Sass::Script::Number.new(color.alpha)
631
- end
632
- declare :opacity, [:color]
633
-
634
- # Makes a color more opaque. Takes a color and a number between 0 and 1, and
635
- # returns a color with the opacity increased by that amount.
636
- #
637
- # @see #transparentize
638
- # @example
639
- # opacify(rgba(0, 0, 0, 0.5), 0.1) => rgba(0, 0, 0, 0.6)
640
- # opacify(rgba(0, 0, 17, 0.8), 0.2) => #001
641
- # @overload opacify($color, $amount)
642
- # @param $color [Color]
643
- # @param $amount [Number] The amount to increase the opacity by, between 0
644
- # and 1
645
- # @return [Color]
646
- # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
647
- # is the wrong type
648
- def opacify(color, amount)
649
- _adjust(color, amount, :alpha, 0..1, :+)
650
- end
651
- declare :opacify, [:color, :amount]
652
-
653
- alias_method :fade_in, :opacify
654
- declare :fade_in, [:color, :amount]
655
-
656
- # Makes a color more transparent. Takes a color and a number between 0 and
657
- # 1, and returns a color with the opacity decreased by that amount.
658
- #
659
- # @see #opacify
660
- # @example
661
- # transparentize(rgba(0, 0, 0, 0.5), 0.1) => rgba(0, 0, 0, 0.4)
662
- # transparentize(rgba(0, 0, 0, 0.8), 0.2) => rgba(0, 0, 0, 0.6)
663
- # @overload transparentize($color, $amount)
664
- # @param $color [Color]
665
- # @param $amount [Number] The amount to decrease the opacity by, between 0
666
- # and 1
667
- # @return [Color]
668
- # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
669
- # is the wrong type
670
- def transparentize(color, amount)
671
- _adjust(color, amount, :alpha, 0..1, :-)
672
- end
673
- declare :transparentize, [:color, :amount]
674
-
675
- alias_method :fade_out, :transparentize
676
- declare :fade_out, [:color, :amount]
677
-
678
- # Makes a color lighter. Takes a color and a number between `0%` and `100%`,
679
- # and returns a color with the lightness increased by that amount.
680
- #
681
- # @see #darken
682
- # @example
683
- # lighten(hsl(0, 0%, 0%), 30%) => hsl(0, 0, 30)
684
- # lighten(#800, 20%) => #e00
685
- # @overload lighten($color, $amount)
686
- # @param $color [Color]
687
- # @param $amount [Number] The amount to increase the lightness by, between
688
- # `0%` and `100%`
689
- # @return [Color]
690
- # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
691
- # is the wrong type
692
- def lighten(color, amount)
693
- _adjust(color, amount, :lightness, 0..100, :+, "%")
694
- end
695
- declare :lighten, [:color, :amount]
696
-
697
- # Makes a color darker. Takes a color and a number between 0% and 100%, and
698
- # returns a color with the lightness decreased by that amount.
699
- #
700
- # @see #lighten
701
- # @example
702
- # darken(hsl(25, 100%, 80%), 30%) => hsl(25, 100%, 50%)
703
- # darken(#800, 20%) => #200
704
- # @overload darken($color, $amount)
705
- # @param $color [Color]
706
- # @param $amount [Number] The amount to dencrease the lightness by, between
707
- # `0%` and `100%`
708
- # @return [Color]
709
- # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
710
- # is the wrong type
711
- def darken(color, amount)
712
- _adjust(color, amount, :lightness, 0..100, :-, "%")
713
- end
714
- declare :darken, [:color, :amount]
715
-
716
- # Makes a color more saturated. Takes a color and a number between 0% and
717
- # 100%, and returns a color with the saturation increased by that amount.
718
- #
719
- # @see #desaturate
720
- # @example
721
- # saturate(hsl(120, 30%, 90%), 20%) => hsl(120, 50%, 90%)
722
- # saturate(#855, 20%) => #9e3f3f
723
- # @overload saturate($color, $amount)
724
- # @param $color [Color]
725
- # @param $amount [Number] The amount to increase the saturation by, between
726
- # `0%` and `100%`
727
- # @return [Color]
728
- # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
729
- # is the wrong type
730
- def saturate(color, amount = nil)
731
- # Support the filter effects definition of saturate.
732
- # https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html
733
- return Sass::Script::String.new("saturate(#{color})") if amount.nil?
734
- _adjust(color, amount, :saturation, 0..100, :+, "%")
735
- end
736
- declare :saturate, [:color, :amount]
737
- declare :saturate, [:amount]
738
-
739
- # Makes a color less saturated. Takes a color and a number between 0% and
740
- # 100%, and returns a color with the saturation decreased by that value.
741
- #
742
- # @see #saturate
743
- # @example
744
- # desaturate(hsl(120, 30%, 90%), 20%) => hsl(120, 10%, 90%)
745
- # desaturate(#855, 20%) => #726b6b
746
- # @overload desaturate($color, $amount)
747
- # @param $color [Color]
748
- # @param $amount [Number] The amount to decrease the saturation by, between
749
- # `0%` and `100%`
750
- # @return [Color]
751
- # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
752
- # is the wrong type
753
- def desaturate(color, amount)
754
- _adjust(color, amount, :saturation, 0..100, :-, "%")
755
- end
756
- declare :desaturate, [:color, :amount]
757
-
758
- # Changes the hue of a color. Takes a color and a number of degrees (usually
759
- # between `-360deg` and `360deg`), and returns a color with the hue rotated
760
- # along the color wheel by that amount.
761
- #
762
- # @example
763
- # adjust-hue(hsl(120, 30%, 90%), 60deg) => hsl(180, 30%, 90%)
764
- # adjust-hue(hsl(120, 30%, 90%), 060deg) => hsl(60, 30%, 90%)
765
- # adjust-hue(#811, 45deg) => #886a11
766
- # @overload adjust_hue($color, $degrees)
767
- # @param $color [Color]
768
- # @param $degrees [Number] The number of degrees to rotate the hue
769
- # @return [Color]
770
- # @raise [ArgumentError] if either parameter is the wrong type
771
- def adjust_hue(color, degrees)
772
- assert_type color, :Color, :color
773
- assert_type degrees, :Number, :degrees
774
- color.with(:hue => color.hue + degrees.value)
775
- end
776
- declare :adjust_hue, [:color, :degrees]
777
-
778
- # Converts a color into the format understood by IE filters.
779
- #
780
- # @example
781
- # ie-hex-str(#abc) => #FFAABBCC
782
- # ie-hex-str(#3322BB) => #FF3322BB
783
- # ie-hex-str(rgba(0, 255, 0, 0.5)) => #8000FF00
784
- # @overload ie_hex_str($color)
785
- # @param $color [Color]
786
- # @return [String] The IE-formatted string representation of the color
787
- # @raise [ArgumentError] if `$color` isn't a color
788
- def ie_hex_str(color)
789
- assert_type color, :Color, :color
790
- alpha = (color.alpha * 255).round.to_s(16).rjust(2, '0')
791
- Sass::Script::String.new("##{alpha}#{color.send(:hex_str)[1..-1]}".upcase)
792
- end
793
- declare :ie_hex_str, [:color]
794
-
795
- # Increases or decreases one or more properties of a color. This can change
796
- # the red, green, blue, hue, saturation, value, and alpha properties. The
797
- # properties are specified as keyword arguments, and are added to or
798
- # subtracted from the color's current value for that property.
799
- #
800
- # All properties are optional. You can't specify both RGB properties
801
- # (`$red`, `$green`, `$blue`) and HSL properties (`$hue`, `$saturation`,
802
- # `$value`) at the same time.
803
- #
804
- # @example
805
- # adjust-color(#102030, $blue: 5) => #102035
806
- # adjust-color(#102030, $red: -5, $blue: 5) => #0b2035
807
- # adjust-color(hsl(25, 100%, 80%), $lightness: -30%, $alpha: -0.4) => hsla(25, 100%, 50%, 0.6)
808
- # @overload adjust_color($color, [$red], [$green], [$blue], [$hue], [$saturation], [$lightness], [$alpha])
809
- # @param $color [Color]
810
- # @param $red [Number] The adjustment to make on the red component, between
811
- # -255 and 255 inclusive
812
- # @param $green [Number] The adjustment to make on the green component,
813
- # between -255 and 255 inclusive
814
- # @param $blue [Number] The adjustment to make on the blue component, between
815
- # -255 and 255 inclusive
816
- # @param $hue [Number] The adjustment to make on the hue component, in
817
- # degrees
818
- # @param $saturation [Number] The adjustment to make on the saturation
819
- # component, between `-100%` and `100%` inclusive
820
- # @param $lightness [Number] The adjustment to make on the lightness
821
- # component, between `-100%` and `100%` inclusive
822
- # @param $alpha [Number] The adjustment to make on the alpha component,
823
- # between -1 and 1 inclusive
824
- # @return [Color]
825
- # @raise [ArgumentError] if any parameter is the wrong type or out-of
826
- # bounds, or if RGB properties and HSL properties are adjusted at the
827
- # same time
828
- def adjust_color(color, kwargs)
829
- assert_type color, :Color, :color
830
- with = Sass::Util.map_hash({
831
- "red" => [-255..255, ""],
832
- "green" => [-255..255, ""],
833
- "blue" => [-255..255, ""],
834
- "hue" => nil,
835
- "saturation" => [-100..100, "%"],
836
- "lightness" => [-100..100, "%"],
837
- "alpha" => [-1..1, ""]
838
- }) do |name, (range, units)|
839
-
840
- next unless val = kwargs.delete(name)
841
- assert_type val, :Number, name
842
- Sass::Util.check_range("$#{name}: Amount", range, val, units) if range
843
- adjusted = color.send(name) + val.value
844
- adjusted = [0, Sass::Util.restrict(adjusted, range)].max if range
845
- [name.to_sym, adjusted]
846
- end
847
-
848
- unless kwargs.empty?
849
- name, val = kwargs.to_a.first
850
- raise ArgumentError.new("Unknown argument $#{name} (#{val})")
851
- end
852
-
853
- color.with(with)
854
- end
855
- declare :adjust_color, [:color], :var_kwargs => true
856
-
857
- # Fluidly scales one or more properties of a color. Unlike
858
- # \{#adjust_color adjust-color}, which changes a color's properties by fixed
859
- # amounts, \{#scale_color scale-color} fluidly changes them based on how
860
- # high or low they already are. That means that lightening an already-light
861
- # color with \{#scale_color scale-color} won't change the lightness much,
862
- # but lightening a dark color by the same amount will change it more
863
- # dramatically. This has the benefit of making `scale-color($color, ...)`
864
- # have a similar effect regardless of what `$color` is.
865
- #
866
- # For example, the lightness of a color can be anywhere between `0%` and
867
- # `100%`. If `scale-color($color, $lightness: 40%)` is called, the resulting
868
- # color's lightness will be 40% of the way between its original lightness
869
- # and 100. If `scale-color($color, $lightness: -40%)` is called instead, the
870
- # lightness will be 40% of the way between the original and 0.
871
- #
872
- # This can change the red, green, blue, saturation, value, and alpha
873
- # properties. The properties are specified as keyword arguments. All
874
- # arguments should be percentages between `0%` and `100%`.
875
- #
876
- # All properties are optional. You can't specify both RGB properties
877
- # (`$red`, `$green`, `$blue`) and HSL properties (`$saturation`, `$value`)
878
- # at the same time.
879
- #
880
- # @example
881
- # scale-color(hsl(120, 70%, 80%), $lightness: 50%) => hsl(120, 70%, 90%)
882
- # scale-color(rgb(200, 150%, 170%), $green: -40%, $blue: 70%) => rgb(200, 90, 229)
883
- # scale-color(hsl(200, 70%, 80%), $saturation: -90%, $alpha: -30%) => hsla(200, 7%, 80%, 0.7)
884
- # @overload scale_color($color, [$red], [$green], [$blue], [$saturation], [$lightness], [$alpha])
885
- # @param $color [Color]
886
- # @param $red [Number]
887
- # @param $green [Number]
888
- # @param $blue [Number]
889
- # @param $saturation [Number]
890
- # @param $lightness [Number]
891
- # @param $alpha [Number]
892
- # @return [Color]
893
- # @raise [ArgumentError] if any parameter is the wrong type or out-of
894
- # bounds, or if RGB properties and HSL properties are adjusted at the
895
- # same time
896
- def scale_color(color, kwargs)
897
- assert_type color, :Color, :color
898
- with = Sass::Util.map_hash({
899
- "red" => 255,
900
- "green" => 255,
901
- "blue" => 255,
902
- "saturation" => 100,
903
- "lightness" => 100,
904
- "alpha" => 1
905
- }) do |name, max|
906
-
907
- next unless val = kwargs.delete(name)
908
- assert_type val, :Number, name
909
- if !(val.numerator_units == ['%'] && val.denominator_units.empty?)
910
- raise ArgumentError.new("$#{name}: Amount #{val} must be a % (e.g. #{val.value}%)")
911
- else
912
- Sass::Util.check_range("$#{name}: Amount", -100..100, val, '%')
913
- end
914
-
915
- current = color.send(name)
916
- scale = val.value/100.0
917
- diff = scale > 0 ? max - current : current
918
- [name.to_sym, current + diff*scale]
919
- end
920
-
921
- unless kwargs.empty?
922
- name, val = kwargs.to_a.first
923
- raise ArgumentError.new("Unknown argument $#{name} (#{val})")
924
- end
925
-
926
- color.with(with)
927
- end
928
- declare :scale_color, [:color], :var_kwargs => true
929
-
930
- # Changes one or more properties of a color. This can change the red, green,
931
- # blue, hue, saturation, value, and alpha properties. The properties are
932
- # specified as keyword arguments, and replace the color's current value for
933
- # that property.
934
- #
935
- # All properties are optional. You can't specify both RGB properties
936
- # (`$red`, `$green`, `$blue`) and HSL properties (`$hue`, `$saturation`,
937
- # `$value`) at the same time.
938
- #
939
- # @example
940
- # change-color(#102030, $blue: 5) => #102005
941
- # change-color(#102030, $red: 120, $blue: 5) => #782005
942
- # change-color(hsl(25, 100%, 80%), $lightness: 40%, $alpha: 0.8) => hsla(25, 100%, 40%, 0.8)
943
- # @overload change_color($color, [$red], [$green], [$blue], [$hue], [$saturation], [$lightness], [$alpha])
944
- # @param $color [Color]
945
- # @param $red [Number] The new red component for the color, within 0 and 255
946
- # inclusive
947
- # @param $green [Number] The new green component for the color, within 0 and
948
- # 255 inclusive
949
- # @param $blue [Number] The new blue component for the color, within 0 and
950
- # 255 inclusive
951
- # @param $hue [Number] The new hue component for the color, in degrees
952
- # @param $saturation [Number] The new saturation component for the color,
953
- # between `0%` and `100%` inclusive
954
- # @param $lightness [Number] The new lightness component for the color,
955
- # within `0%` and `100%` inclusive
956
- # @param $alpha [Number] The new alpha component for the color, within 0 and
957
- # 1 inclusive
958
- # @return [Color]
959
- # @raise [ArgumentError] if any parameter is the wrong type or out-of
960
- # bounds, or if RGB properties and HSL properties are adjusted at the
961
- # same time
962
- def change_color(color, kwargs)
963
- assert_type color, :Color, :color
964
- with = Sass::Util.map_hash(%w[red green blue hue saturation lightness alpha]) do |name, max|
965
- next unless val = kwargs.delete(name)
966
- assert_type val, :Number, name
967
- [name.to_sym, val.value]
968
- end
969
-
970
- unless kwargs.empty?
971
- name, val = kwargs.to_a.first
972
- raise ArgumentError.new("Unknown argument $#{name} (#{val})")
973
- end
974
-
975
- color.with(with)
976
- end
977
- declare :change_color, [:color], :var_kwargs => true
978
-
979
- # Mixes two colors together. Specifically, takes the average of each of the
980
- # RGB components, optionally weighted by the given percentage. The opacity
981
- # of the colors is also considered when weighting the components.
982
- #
983
- # The weight specifies the amount of the first color that should be included
984
- # in the returned color. The default, `50%`, means that half the first color
985
- # and half the second color should be used. `25%` means that a quarter of
986
- # the first color and three quarters of the second color should be used.
987
- #
988
- # @example
989
- # mix(#f00, #00f) => #7f007f
990
- # mix(#f00, #00f, 25%) => #3f00bf
991
- # mix(rgba(255, 0, 0, 0.5), #00f) => rgba(63, 0, 191, 0.75)
992
- # @overload mix($color-1, $color-2, $weight: 50%)
993
- # @param $color-1 [Color]
994
- # @param $color-2 [Color]
995
- # @param $weight [Number] The relative weight of each color. Closer to `0%`
996
- # gives more weight to `$color`, closer to `100%` gives more weight to
997
- # `$color2`
998
- # @return [Color]
999
- # @raise [ArgumentError] if `$weight` is out of bounds or any parameter is
1000
- # the wrong type
1001
- def mix(color_1, color_2, weight = Number.new(50))
1002
- assert_type color_1, :Color, :color_1
1003
- assert_type color_2, :Color, :color_2
1004
- assert_type weight, :Number, :weight
1005
-
1006
- Sass::Util.check_range("Weight", 0..100, weight, '%')
1007
-
1008
- # This algorithm factors in both the user-provided weight (w) and the
1009
- # difference between the alpha values of the two colors (a) to decide how
1010
- # to perform the weighted average of the two RGB values.
1011
- #
1012
- # It works by first normalizing both parameters to be within [-1, 1],
1013
- # where 1 indicates "only use color_1", -1 indicates "only use color_2", and
1014
- # all values in between indicated a proportionately weighted average.
1015
- #
1016
- # Once we have the normalized variables w and a, we apply the formula
1017
- # (w + a)/(1 + w*a) to get the combined weight (in [-1, 1]) of color_1.
1018
- # This formula has two especially nice properties:
1019
- #
1020
- # * When either w or a are -1 or 1, the combined weight is also that number
1021
- # (cases where w * a == -1 are undefined, and handled as a special case).
1022
- #
1023
- # * When a is 0, the combined weight is w, and vice versa.
1024
- #
1025
- # Finally, the weight of color_1 is renormalized to be within [0, 1]
1026
- # and the weight of color_2 is given by 1 minus the weight of color_1.
1027
- p = (weight.value/100.0).to_f
1028
- w = p*2 - 1
1029
- a = color_1.alpha - color_2.alpha
1030
-
1031
- w1 = (((w * a == -1) ? w : (w + a)/(1 + w*a)) + 1)/2.0
1032
- w2 = 1 - w1
1033
-
1034
- rgb = color_1.rgb.zip(color_2.rgb).map {|v1, v2| v1*w1 + v2*w2}
1035
- alpha = color_1.alpha*p + color_2.alpha*(1-p)
1036
- Color.new(rgb + [alpha])
1037
- end
1038
- declare :mix, [:color_1, :color_2]
1039
- declare :mix, [:color_1, :color_2, :weight]
1040
-
1041
- # Converts a color to grayscale. This is identical to `desaturate(color,
1042
- # 100%)`.
1043
- #
1044
- # @see #desaturate
1045
- # @overload grayscale($color)
1046
- # @param $color [Color]
1047
- # @return [Color]
1048
- # @raise [ArgumentError] if `$color` isn't a color
1049
- def grayscale(color)
1050
- return Sass::Script::String.new("grayscale(#{color})") if color.is_a?(Sass::Script::Number)
1051
- desaturate color, Number.new(100)
1052
- end
1053
- declare :grayscale, [:color]
1054
-
1055
- # Returns the complement of a color. This is identical to `adjust-hue(color,
1056
- # 180deg)`.
1057
- #
1058
- # @see #adjust_hue #adjust-hue
1059
- # @overload complement($color)
1060
- # @param $color [Color]
1061
- # @return [Color]
1062
- # @raise [ArgumentError] if `$color` isn't a color
1063
- def complement(color)
1064
- adjust_hue color, Number.new(180)
1065
- end
1066
- declare :complement, [:color]
1067
-
1068
- # Returns the inverse (negative) of a color. The red, green, and blue values
1069
- # are inverted, while the opacity is left alone.
1070
- #
1071
- # @overload invert($color)
1072
- # @param $color [Color]
1073
- # @return [Color]
1074
- # @raise [ArgumentError] if `$color` isn't a color
1075
- def invert(color)
1076
- return Sass::Script::String.new("invert(#{color})") if color.is_a?(Sass::Script::Number)
1077
-
1078
- assert_type color, :Color, :color
1079
- color.with(
1080
- :red => (255 - color.red),
1081
- :green => (255 - color.green),
1082
- :blue => (255 - color.blue))
1083
- end
1084
- declare :invert, [:color]
1085
-
1086
- # Removes quotes from a string. If the string is already unquoted, this will
1087
- # return it unmodified.
1088
- #
1089
- # @see #quote
1090
- # @example
1091
- # unquote("foo") => foo
1092
- # unquote(foo) => foo
1093
- # @overload unquote($string)
1094
- # @param $string [String]
1095
- # @return [String]
1096
- # @raise [ArgumentError] if `$string` isn't a string
1097
- def unquote(string)
1098
- if string.is_a?(Sass::Script::String)
1099
- Sass::Script::String.new(string.value, :identifier)
1100
- else
1101
- string
1102
- end
1103
- end
1104
- declare :unquote, [:string]
1105
-
1106
- # Add quotes to a string if the string isn't quoted,
1107
- # or returns the same string if it is.
1108
- #
1109
- # @see #unquote
1110
- # @example
1111
- # quote("foo") => "foo"
1112
- # quote(foo) => "foo"
1113
- # @overload quote($string)
1114
- # @param $string [String]
1115
- # @return [String]
1116
- # @raise [ArgumentError] if `$string` isn't a string
1117
- def quote(string)
1118
- assert_type string, :String, :string
1119
- Sass::Script::String.new(string.value, :string)
1120
- end
1121
- declare :quote, [:string]
1122
-
1123
- # Returns the type of a value.
1124
- #
1125
- # @example
1126
- # type-of(100px) => number
1127
- # type-of(asdf) => string
1128
- # type-of("asdf") => string
1129
- # type-of(true) => bool
1130
- # type-of(#fff) => color
1131
- # type-of(blue) => color
1132
- # @overload type_of($value)
1133
- # @param $value [Literal] The value to inspect
1134
- # @return [String] The unquoted string name of the value's type
1135
- def type_of(value)
1136
- Sass::Script::String.new(value.class.name.gsub(/Sass::Script::/,'').downcase)
1137
- end
1138
- declare :type_of, [:value]
1139
-
1140
- # Returns the unit(s) associated with a number. Complex units are sorted in
1141
- # alphabetical order by numerator and denominator.
1142
- #
1143
- # @example
1144
- # unit(100) => ""
1145
- # unit(100px) => "px"
1146
- # unit(3em) => "em"
1147
- # unit(10px * 5em) => "em*px"
1148
- # unit(10px * 5em / 30cm / 1rem) => "em*px/cm*rem"
1149
- # @overload unit($number)
1150
- # @param $number [Number]
1151
- # @return [String] The unit(s) of the number, as a quoted string
1152
- # @raise [ArgumentError] if `$number` isn't a number
1153
- def unit(number)
1154
- assert_type number, :Number, :number
1155
- Sass::Script::String.new(number.unit_str, :string)
1156
- end
1157
- declare :unit, [:number]
1158
-
1159
- # Returns whether a number has units.
1160
- #
1161
- # @example
1162
- # unitless(100) => true
1163
- # unitless(100px) => false
1164
- # @overload unitless($number)
1165
- # @param $number [Number]
1166
- # @return [Bool]
1167
- # @raise [ArgumentError] if `$number` isn't a number
1168
- def unitless(number)
1169
- assert_type number, :Number, :number
1170
- Sass::Script::Bool.new(number.unitless?)
1171
- end
1172
- declare :unitless, [:number]
1173
-
1174
- # Returns whether two numbers can added, subtracted, or compared.
1175
- #
1176
- # @example
1177
- # comparable(2px, 1px) => true
1178
- # comparable(100px, 3em) => false
1179
- # comparable(10cm, 3mm) => true
1180
- # @overload comparable($number-1, $number-2)
1181
- # @param $number-1 [Number]
1182
- # @param $number-2 [Number]
1183
- # @return [Bool]
1184
- # @raise [ArgumentError] if either parameter is the wrong type
1185
- def comparable(number_1, number_2)
1186
- assert_type number_1, :Number, :number_1
1187
- assert_type number_2, :Number, :number_2
1188
- Sass::Script::Bool.new(number_1.comparable_to?(number_2))
1189
- end
1190
- declare :comparable, [:number_1, :number_2]
1191
-
1192
- # Converts a unitless number to a percentage.
1193
- #
1194
- # @example
1195
- # percentage(0.2) => 20%
1196
- # percentage(100px / 50px) => 200%
1197
- # @overload percentage($value)
1198
- # @param $value [Number]
1199
- # @return [Number]
1200
- # @raise [ArgumentError] if `$value` isn't a unitless number
1201
- def percentage(value)
1202
- unless value.is_a?(Sass::Script::Number) && value.unitless?
1203
- raise ArgumentError.new("$value: #{value.inspect} is not a unitless number")
1204
- end
1205
- Sass::Script::Number.new(value.value * 100, ['%'])
1206
- end
1207
- declare :percentage, [:value]
1208
-
1209
- # Rounds a number to the nearest whole number.
1210
- #
1211
- # @example
1212
- # round(10.4px) => 10px
1213
- # round(10.6px) => 11px
1214
- # @overload round($value)
1215
- # @param $value [Number]
1216
- # @return [Number]
1217
- # @raise [ArgumentError] if `$value` isn't a number
1218
- def round(value)
1219
- numeric_transformation(value) {|n| n.round}
1220
- end
1221
- declare :round, [:value]
1222
-
1223
- # Rounds a number up to the next whole number.
1224
- #
1225
- # @example
1226
- # ceil(10.4px) => 11px
1227
- # ceil(10.6px) => 11px
1228
- # @overload ceil($value)
1229
- # @param $value [Number]
1230
- # @return [Number]
1231
- # @raise [ArgumentError] if `$value` isn't a number
1232
- def ceil(value)
1233
- numeric_transformation(value) {|n| n.ceil}
1234
- end
1235
- declare :ceil, [:value]
1236
-
1237
- # Rounds a number down to the previous whole number.
1238
- #
1239
- # @example
1240
- # floor(10.4px) => 10px
1241
- # floor(10.6px) => 10px
1242
- # @overload floor($value)
1243
- # @param $value [Number]
1244
- # @return [Number]
1245
- # @raise [ArgumentError] if `$value` isn't a number
1246
- def floor(value)
1247
- numeric_transformation(value) {|n| n.floor}
1248
- end
1249
- declare :floor, [:value]
1250
-
1251
- # Returns the absolute value of a number.
1252
- #
1253
- # @example
1254
- # abs(10px) => 10px
1255
- # abs(-10px) => 10px
1256
- # @overload abs($value)
1257
- # @param $value [Number]
1258
- # @return [Number]
1259
- # @raise [ArgumentError] if `$value` isn't a number
1260
- def abs(value)
1261
- numeric_transformation(value) {|n| n.abs}
1262
- end
1263
- declare :abs, [:value]
1264
-
1265
- # Finds the minimum of several numbers. This function takes any number of
1266
- # arguments.
1267
- #
1268
- # @example
1269
- # min(1px, 4px) => 1px
1270
- # min(5em, 3em, 4em) => 3em
1271
- # @overload min($numbers...)
1272
- # @param $numbers [[Number]]
1273
- # @return [Number]
1274
- # @raise [ArgumentError] if any argument isn't a number, or if not all of
1275
- # the arguments have comparable units
1276
- def min(*numbers)
1277
- numbers.each {|n| assert_type n, :Number}
1278
- numbers.inject {|min, num| min.lt(num).to_bool ? min : num}
1279
- end
1280
- declare :min, [], :var_args => :true
1281
-
1282
- # Finds the maximum of several numbers. This function takes any number of
1283
- # arguments.
1284
- #
1285
- # @example
1286
- # max(1px, 4px) => 4px
1287
- # max(5em, 3em, 4em) => 5em
1288
- # @overload max($numbers...)
1289
- # @param $numbers [[Number]]
1290
- # @return [Number]
1291
- # @raise [ArgumentError] if any argument isn't a number, or if not all of
1292
- # the arguments have comparable units
1293
- def max(*values)
1294
- values.each {|v| assert_type v, :Number}
1295
- values.inject {|max, val| max.gt(val).to_bool ? max : val}
1296
- end
1297
- declare :max, [], :var_args => :true
1298
-
1299
- # Return the length of a list.
1300
- #
1301
- # @example
1302
- # length(10px) => 1
1303
- # length(10px 20px 30px) => 3
1304
- # @overload length($list)
1305
- # @param $list [Literal]
1306
- # @return [Number]
1307
- def length(list)
1308
- Sass::Script::Number.new(list.to_a.size)
1309
- end
1310
- declare :length, [:list]
1311
-
1312
- # Gets the nth item in a list.
1313
- #
1314
- # Note that unlike some languages, the first item in a Sass list is number
1315
- # 1, the second number 2, and so forth.
1316
- #
1317
- # @example
1318
- # nth(10px 20px 30px, 1) => 10px
1319
- # nth((Helvetica, Arial, sans-serif), 3) => sans-serif
1320
- # @overload nth($list, $n)
1321
- # @param $list [Literal]
1322
- # @param $n [Number] The index of the item to get
1323
- # @return [Literal]
1324
- # @raise [ArgumentError] if `$n` isn't an integer between 1 and the length
1325
- # of `$list`
1326
- def nth(list, n)
1327
- assert_type n, :Number, :n
1328
- if !n.int?
1329
- raise ArgumentError.new("List index #{n} must be an integer")
1330
- elsif n.to_i < 1
1331
- raise ArgumentError.new("List index #{n} must be greater than or equal to 1")
1332
- elsif list.to_a.size == 0
1333
- raise ArgumentError.new("List index is #{n} but list has no items")
1334
- elsif n.to_i > (size = list.to_a.size)
1335
- raise ArgumentError.new("List index is #{n} but list is only #{size} item#{'s' if size != 1} long")
1336
- end
1337
-
1338
- list.to_a[n.to_i - 1]
1339
- end
1340
- declare :nth, [:list, :n]
1341
-
1342
- # Joins together two lists into one.
1343
- #
1344
- # Unless `$separator` is passed, if one list is comma-separated and one is
1345
- # space-separated, the first parameter's separator is used for the resulting
1346
- # list. If both lists have fewer than two items, spaces are used for the
1347
- # resulting list.
1348
- #
1349
- # @example
1350
- # join(10px 20px, 30px 40px) => 10px 20px 30px 40px
1351
- # join((blue, red), (#abc, #def)) => blue, red, #abc, #def
1352
- # join(10px, 20px) => 10px 20px
1353
- # join(10px, 20px, comma) => 10px, 20px
1354
- # join((blue, red), (#abc, #def), space) => blue red #abc #def
1355
- # @overload join($list1, $list2, $separator: auto)
1356
- # @param $list1 [Literal]
1357
- # @param $list2 [Literal]
1358
- # @param $separator [String] The list separator to use. If this is `comma`
1359
- # or `space`, that separator will be used. If this is `auto` (the
1360
- # default), the separator is determined as explained above.
1361
- # @return [List]
1362
- def join(list1, list2, separator = Sass::Script::String.new("auto"))
1363
- assert_type separator, :String, :separator
1364
- unless %w[auto space comma].include?(separator.value)
1365
- raise ArgumentError.new("Separator name must be space, comma, or auto")
1366
- end
1367
- sep1 = list1.separator if list1.is_a?(Sass::Script::List) && !list1.value.empty?
1368
- sep2 = list2.separator if list2.is_a?(Sass::Script::List) && !list2.value.empty?
1369
- Sass::Script::List.new(
1370
- list1.to_a + list2.to_a,
1371
- if separator.value == 'auto'
1372
- sep1 || sep2 || :space
1373
- else
1374
- separator.value.to_sym
1375
- end)
1376
- end
1377
- declare :join, [:list1, :list2]
1378
- declare :join, [:list1, :list2, :separator]
1379
-
1380
- # Appends a single value onto the end of a list.
1381
- #
1382
- # Unless the `$separator` argument is passed, if the list had only one item,
1383
- # the resulting list will be space-separated.
1384
- #
1385
- # @example
1386
- # append(10px 20px, 30px) => 10px 20px 30px
1387
- # append((blue, red), green) => blue, red, green
1388
- # append(10px 20px, 30px 40px) => 10px 20px (30px 40px)
1389
- # append(10px, 20px, comma) => 10px, 20px
1390
- # append((blue, red), green, space) => blue red green
1391
- # @overload append($list, $val, $separator: auto)
1392
- # @param $list [Literal]
1393
- # @param $val [Literal]
1394
- # @param $separator [String] The list separator to use. If this is `comma`
1395
- # or `space`, that separator will be used. If this is `auto` (the
1396
- # default), the separator is determined as explained above.
1397
- # @return [List]
1398
- def append(list, val, separator = Sass::Script::String.new("auto"))
1399
- assert_type separator, :String, :separator
1400
- unless %w[auto space comma].include?(separator.value)
1401
- raise ArgumentError.new("Separator name must be space, comma, or auto")
1402
- end
1403
- sep = list.separator if list.is_a?(Sass::Script::List)
1404
- Sass::Script::List.new(
1405
- list.to_a + [val],
1406
- if separator.value == 'auto'
1407
- sep || :space
1408
- else
1409
- separator.value.to_sym
1410
- end)
1411
- end
1412
- declare :append, [:list, :val]
1413
- declare :append, [:list, :val, :separator]
1414
-
1415
- # Combines several lists into a single multidimensional list. The nth value
1416
- # of the resulting list is a space separated list of the source lists' nth
1417
- # values.
1418
- #
1419
- # The length of the resulting list is the length of the
1420
- # shortest list.
1421
- #
1422
- # @example
1423
- # zip(1px 1px 3px, solid dashed solid, red green blue)
1424
- # => 1px solid red, 1px dashed green, 3px solid blue
1425
- # @overload zip($lists...)
1426
- # @param $lists [[Literal]]
1427
- # @return [List]
1428
- def zip(*lists)
1429
- length = nil
1430
- values = []
1431
- lists.each do |list|
1432
- array = list.to_a
1433
- values << array.dup
1434
- length = length.nil? ? array.length : [length, array.length].min
1435
- end
1436
- values.each do |value|
1437
- value.slice!(length)
1438
- end
1439
- new_list_value = values.first.zip(*values[1..-1])
1440
- List.new(new_list_value.map{|list| List.new(list, :space)}, :comma)
1441
- end
1442
- declare :zip, [], :var_args => true
1443
-
1444
-
1445
- # Returns the position of a value within a list. If the value isn't found,
1446
- # returns false instead.
1447
- #
1448
- # Note that unlike some languages, the first item in a Sass list is number
1449
- # 1, the second number 2, and so forth.
1450
- #
1451
- # @example
1452
- # index(1px solid red, solid) => 2
1453
- # index(1px solid red, dashed) => false
1454
- # @overload index($list, $value)
1455
- # @param $list [Literal]
1456
- # @param $value [Literal]
1457
- # @return [Number, Bool] The 1-based index of `$value` in `$list`, or
1458
- # `false`
1459
- def index(list, value)
1460
- index = list.to_a.index {|e| e.eq(value).to_bool }
1461
- if index
1462
- Number.new(index + 1)
1463
- else
1464
- Bool.new(false)
1465
- end
1466
- end
1467
- declare :index, [:list, :value]
1468
-
1469
- # Returns one of two values, depending on whether or not `$condition` is
1470
- # true. Just like in `@if`, all values other than `false` and `null` are
1471
- # considered to be true.
1472
- #
1473
- # @example
1474
- # if(true, 1px, 2px) => 1px
1475
- # if(false, 1px, 2px) => 2px
1476
- # @overload if($condition, $if-true, $if-false)
1477
- # @param $condition [Literal] Whether the `$if-true` or `$if-false` will be
1478
- # returned
1479
- # @param $if-true [Literal]
1480
- # @param $if-false [Literal]
1481
- # @return [Literal] `$if-true` or `$if-false`
1482
- def if(condition, if_true, if_false)
1483
- if condition.to_bool
1484
- if_true
1485
- else
1486
- if_false
1487
- end
1488
- end
1489
- declare :if, [:condition, :if_true, :if_false]
1490
-
1491
- # This function only exists as a workaround for IE7's [`content: counter`
1492
- # bug][bug]. It works identically to any other plain-CSS function, except it
1493
- # avoids adding spaces between the argument commas.
1494
- #
1495
- # [bug]: http://jes.st/2013/ie7s-css-breaking-content-counter-bug/
1496
- #
1497
- # @example
1498
- # counter(item, ".") => counter(item,".")
1499
- # @overload counter($args...)
1500
- # @return [String]
1501
- def counter(*args)
1502
- Sass::Script::String.new("counter(#{args.map {|a| a.to_s(options)}.join(',')})")
1503
- end
1504
- declare :counter, [], :var_args => true
1505
-
1506
- # This function only exists as a workaround for IE7's [`content: counters`
1507
- # bug][bug]. It works identically to any other plain-CSS function, except it
1508
- # avoids adding spaces between the argument commas.
1509
- #
1510
- # [bug]: http://jes.st/2013/ie7s-css-breaking-content-counter-bug/
1511
- #
1512
- # @example
1513
- # counters(item, ".") => counters(item,".")
1514
- # @overload counters($args...)
1515
- # @return [String]
1516
- def counters(*args)
1517
- Sass::Script::String.new("counters(#{args.map {|a| a.to_s(options)}.join(',')})")
1518
- end
1519
- declare :counters, [], :var_args => true
1520
-
1521
- private
1522
-
1523
- # This method implements the pattern of transforming a numeric value into
1524
- # another numeric value with the same units.
1525
- # It yields a number to a block to perform the operation and return a number
1526
- def numeric_transformation(value)
1527
- assert_type value, :Number, :value
1528
- Sass::Script::Number.new(yield(value.value), value.numerator_units, value.denominator_units)
1529
- end
1530
-
1531
- def _adjust(color, amount, attr, range, op, units = "")
1532
- assert_type color, :Color, :color
1533
- assert_type amount, :Number, :amount
1534
- Sass::Util.check_range('Amount', range, amount, units)
1535
-
1536
- # TODO: is it worth restricting here,
1537
- # or should we do so in the Color constructor itself,
1538
- # and allow clipping in rgb() et al?
1539
- color.with(attr => Sass::Util.restrict(
1540
- color.send(attr).send(op, amount.value), range))
1541
- end
1542
- end
1543
- end