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.
- checksums.yaml +7 -0
- data/CONTRIBUTING +1 -1
- data/MIT-LICENSE +2 -2
- data/README.md +29 -17
- data/Rakefile +43 -9
- data/VERSION +1 -1
- data/VERSION_DATE +1 -0
- data/VERSION_NAME +1 -1
- data/bin/sass +6 -1
- data/bin/sass-convert +6 -1
- data/bin/scss +6 -1
- data/ext/mkrf_conf.rb +27 -0
- data/lib/sass/cache_stores/base.rb +7 -3
- data/lib/sass/cache_stores/chain.rb +3 -2
- data/lib/sass/cache_stores/filesystem.rb +5 -7
- data/lib/sass/cache_stores/memory.rb +1 -1
- data/lib/sass/cache_stores/null.rb +2 -2
- data/lib/sass/callbacks.rb +2 -1
- data/lib/sass/css.rb +168 -53
- data/lib/sass/engine.rb +502 -174
- data/lib/sass/environment.rb +151 -111
- data/lib/sass/error.rb +7 -7
- data/lib/sass/exec.rb +176 -60
- data/lib/sass/features.rb +40 -0
- data/lib/sass/importers/base.rb +46 -7
- data/lib/sass/importers/deprecated_path.rb +51 -0
- data/lib/sass/importers/filesystem.rb +113 -30
- data/lib/sass/importers.rb +1 -0
- data/lib/sass/logger/base.rb +30 -0
- data/lib/sass/logger/log_level.rb +45 -0
- data/lib/sass/logger.rb +12 -0
- data/lib/sass/media.rb +213 -0
- data/lib/sass/plugin/compiler.rb +194 -104
- data/lib/sass/plugin/configuration.rb +18 -25
- data/lib/sass/plugin/merb.rb +1 -1
- data/lib/sass/plugin/staleness_checker.rb +37 -11
- data/lib/sass/plugin.rb +10 -13
- data/lib/sass/railtie.rb +2 -1
- data/lib/sass/repl.rb +5 -6
- data/lib/sass/script/css_lexer.rb +8 -4
- data/lib/sass/script/css_parser.rb +5 -2
- data/lib/sass/script/functions.rb +1547 -618
- data/lib/sass/script/lexer.rb +122 -72
- data/lib/sass/script/parser.rb +304 -135
- data/lib/sass/script/tree/funcall.rb +306 -0
- data/lib/sass/script/{interpolation.rb → tree/interpolation.rb} +43 -13
- data/lib/sass/script/tree/list_literal.rb +77 -0
- data/lib/sass/script/tree/literal.rb +45 -0
- data/lib/sass/script/tree/map_literal.rb +64 -0
- data/lib/sass/script/{node.rb → tree/node.rb} +30 -12
- data/lib/sass/script/{operation.rb → tree/operation.rb} +33 -21
- data/lib/sass/script/{string_interpolation.rb → tree/string_interpolation.rb} +14 -4
- data/lib/sass/script/{unary_operation.rb → tree/unary_operation.rb} +21 -9
- data/lib/sass/script/tree/variable.rb +57 -0
- data/lib/sass/script/tree.rb +15 -0
- data/lib/sass/script/value/arg_list.rb +36 -0
- data/lib/sass/script/value/base.rb +238 -0
- data/lib/sass/script/value/bool.rb +40 -0
- data/lib/sass/script/{color.rb → value/color.rb} +256 -74
- data/lib/sass/script/value/deprecated_false.rb +55 -0
- data/lib/sass/script/value/helpers.rb +155 -0
- data/lib/sass/script/value/list.rb +128 -0
- data/lib/sass/script/value/map.rb +70 -0
- data/lib/sass/script/value/null.rb +49 -0
- data/lib/sass/script/{number.rb → value/number.rb} +115 -62
- data/lib/sass/script/{string.rb → value/string.rb} +9 -11
- data/lib/sass/script/value.rb +12 -0
- data/lib/sass/script.rb +35 -9
- data/lib/sass/scss/css_parser.rb +2 -12
- data/lib/sass/scss/parser.rb +657 -230
- data/lib/sass/scss/rx.rb +17 -12
- data/lib/sass/scss/static_parser.rb +37 -6
- data/lib/sass/scss.rb +0 -1
- data/lib/sass/selector/abstract_sequence.rb +35 -3
- data/lib/sass/selector/comma_sequence.rb +29 -14
- data/lib/sass/selector/sequence.rb +371 -74
- data/lib/sass/selector/simple.rb +28 -13
- data/lib/sass/selector/simple_sequence.rb +163 -36
- data/lib/sass/selector.rb +138 -36
- data/lib/sass/shared.rb +3 -5
- data/lib/sass/source/map.rb +196 -0
- data/lib/sass/source/position.rb +39 -0
- data/lib/sass/source/range.rb +41 -0
- data/lib/sass/stack.rb +126 -0
- data/lib/sass/supports.rb +228 -0
- data/lib/sass/tree/at_root_node.rb +82 -0
- data/lib/sass/tree/comment_node.rb +34 -29
- data/lib/sass/tree/content_node.rb +9 -0
- data/lib/sass/tree/css_import_node.rb +60 -0
- data/lib/sass/tree/debug_node.rb +3 -3
- data/lib/sass/tree/directive_node.rb +33 -3
- data/lib/sass/tree/each_node.rb +9 -9
- data/lib/sass/tree/extend_node.rb +20 -6
- data/lib/sass/tree/for_node.rb +6 -6
- data/lib/sass/tree/function_node.rb +12 -4
- data/lib/sass/tree/if_node.rb +2 -15
- data/lib/sass/tree/import_node.rb +11 -5
- data/lib/sass/tree/media_node.rb +27 -11
- data/lib/sass/tree/mixin_def_node.rb +15 -4
- data/lib/sass/tree/mixin_node.rb +27 -7
- data/lib/sass/tree/node.rb +69 -35
- data/lib/sass/tree/prop_node.rb +47 -31
- data/lib/sass/tree/return_node.rb +4 -3
- data/lib/sass/tree/root_node.rb +20 -4
- data/lib/sass/tree/rule_node.rb +37 -26
- data/lib/sass/tree/supports_node.rb +38 -0
- data/lib/sass/tree/trace_node.rb +33 -0
- data/lib/sass/tree/variable_node.rb +10 -4
- data/lib/sass/tree/visitors/base.rb +5 -8
- data/lib/sass/tree/visitors/check_nesting.rb +67 -52
- data/lib/sass/tree/visitors/convert.rb +134 -53
- data/lib/sass/tree/visitors/cssize.rb +245 -51
- data/lib/sass/tree/visitors/deep_copy.rb +102 -0
- data/lib/sass/tree/visitors/extend.rb +68 -0
- data/lib/sass/tree/visitors/perform.rb +331 -105
- data/lib/sass/tree/visitors/set_options.rb +125 -0
- data/lib/sass/tree/visitors/to_css.rb +259 -95
- data/lib/sass/tree/warn_node.rb +3 -3
- data/lib/sass/tree/while_node.rb +3 -3
- data/lib/sass/util/cross_platform_random.rb +19 -0
- data/lib/sass/util/multibyte_string_scanner.rb +157 -0
- data/lib/sass/util/normalized_map.rb +130 -0
- data/lib/sass/util/ordered_hash.rb +192 -0
- data/lib/sass/util/subset_map.rb +11 -2
- data/lib/sass/util/test.rb +9 -0
- data/lib/sass/util.rb +565 -39
- data/lib/sass/version.rb +27 -15
- data/lib/sass.rb +39 -4
- data/test/sass/cache_test.rb +15 -0
- data/test/sass/compiler_test.rb +223 -0
- data/test/sass/conversion_test.rb +901 -107
- data/test/sass/css2sass_test.rb +94 -0
- data/test/sass/engine_test.rb +1059 -164
- data/test/sass/exec_test.rb +86 -0
- data/test/sass/extend_test.rb +933 -837
- data/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
- data/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
- data/test/sass/functions_test.rb +995 -136
- data/test/sass/importer_test.rb +338 -18
- data/test/sass/logger_test.rb +58 -0
- data/test/sass/more_results/more_import.css +2 -2
- data/test/sass/plugin_test.rb +114 -30
- data/test/sass/results/cached_import_option.css +3 -0
- data/test/sass/results/filename_fn.css +3 -0
- data/test/sass/results/import.css +2 -2
- data/test/sass/results/import_charset.css +1 -0
- data/test/sass/results/import_charset_1_8.css +1 -0
- data/test/sass/results/import_charset_ibm866.css +1 -0
- data/test/sass/results/import_content.css +1 -0
- data/test/sass/results/script.css +1 -1
- data/test/sass/results/scss_import.css +2 -2
- data/test/sass/results/units.css +2 -2
- data/test/sass/script_conversion_test.rb +43 -1
- data/test/sass/script_test.rb +380 -36
- data/test/sass/scss/css_test.rb +257 -75
- data/test/sass/scss/scss_test.rb +2322 -110
- data/test/sass/source_map_test.rb +887 -0
- data/test/sass/templates/_cached_import_option_partial.scss +1 -0
- data/test/sass/templates/_double_import_loop2.sass +1 -0
- data/test/sass/templates/_filename_fn_import.scss +11 -0
- data/test/sass/templates/_imported_content.sass +3 -0
- data/test/sass/templates/_same_name_different_partiality.scss +1 -0
- data/test/sass/templates/bork5.sass +3 -0
- data/test/sass/templates/cached_import_option.scss +3 -0
- data/test/sass/templates/double_import_loop1.sass +1 -0
- data/test/sass/templates/filename_fn.scss +18 -0
- data/test/sass/templates/import_charset.sass +2 -0
- data/test/sass/templates/import_charset_1_8.sass +2 -0
- data/test/sass/templates/import_charset_ibm866.sass +2 -0
- data/test/sass/templates/import_content.sass +4 -0
- data/test/sass/templates/same_name_different_ext.sass +2 -0
- data/test/sass/templates/same_name_different_ext.scss +1 -0
- data/test/sass/templates/same_name_different_partiality.scss +1 -0
- data/test/sass/templates/single_import_loop.sass +1 -0
- data/test/sass/templates/subdir/import_up1.scss +1 -0
- data/test/sass/templates/subdir/import_up2.scss +1 -0
- data/test/sass/test_helper.rb +1 -1
- data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
- data/test/sass/util/normalized_map_test.rb +51 -0
- data/test/sass/util_test.rb +183 -0
- data/test/sass/value_helpers_test.rb +181 -0
- data/test/test_helper.rb +45 -5
- data/vendor/listen/CHANGELOG.md +228 -0
- data/vendor/listen/CONTRIBUTING.md +38 -0
- data/vendor/listen/Gemfile +30 -0
- data/vendor/listen/Guardfile +8 -0
- data/vendor/{fssm → listen}/LICENSE +1 -1
- data/vendor/listen/README.md +315 -0
- data/vendor/listen/Rakefile +47 -0
- data/vendor/listen/Vagrantfile +96 -0
- data/vendor/listen/lib/listen/adapter.rb +214 -0
- data/vendor/listen/lib/listen/adapters/bsd.rb +112 -0
- data/vendor/listen/lib/listen/adapters/darwin.rb +85 -0
- data/vendor/listen/lib/listen/adapters/linux.rb +113 -0
- data/vendor/listen/lib/listen/adapters/polling.rb +67 -0
- data/vendor/listen/lib/listen/adapters/windows.rb +87 -0
- data/vendor/listen/lib/listen/dependency_manager.rb +126 -0
- data/vendor/listen/lib/listen/directory_record.rb +371 -0
- data/vendor/listen/lib/listen/listener.rb +225 -0
- data/vendor/listen/lib/listen/multi_listener.rb +143 -0
- data/vendor/listen/lib/listen/turnstile.rb +28 -0
- data/vendor/listen/lib/listen/version.rb +3 -0
- data/vendor/listen/lib/listen.rb +40 -0
- data/vendor/listen/listen.gemspec +22 -0
- data/vendor/listen/spec/listen/adapter_spec.rb +183 -0
- data/vendor/listen/spec/listen/adapters/bsd_spec.rb +36 -0
- data/vendor/listen/spec/listen/adapters/darwin_spec.rb +37 -0
- data/vendor/listen/spec/listen/adapters/linux_spec.rb +47 -0
- data/vendor/listen/spec/listen/adapters/polling_spec.rb +68 -0
- data/vendor/listen/spec/listen/adapters/windows_spec.rb +30 -0
- data/vendor/listen/spec/listen/dependency_manager_spec.rb +107 -0
- data/vendor/listen/spec/listen/directory_record_spec.rb +1225 -0
- data/vendor/listen/spec/listen/listener_spec.rb +169 -0
- data/vendor/listen/spec/listen/multi_listener_spec.rb +174 -0
- data/vendor/listen/spec/listen/turnstile_spec.rb +56 -0
- data/vendor/listen/spec/listen_spec.rb +73 -0
- data/vendor/listen/spec/spec_helper.rb +21 -0
- data/vendor/listen/spec/support/adapter_helper.rb +629 -0
- data/vendor/listen/spec/support/directory_record_helper.rb +55 -0
- data/vendor/listen/spec/support/fixtures_helper.rb +29 -0
- data/vendor/listen/spec/support/listeners_helper.rb +156 -0
- data/vendor/listen/spec/support/platform_helper.rb +15 -0
- metadata +344 -271
- data/lib/sass/less.rb +0 -382
- data/lib/sass/script/bool.rb +0 -18
- data/lib/sass/script/funcall.rb +0 -162
- data/lib/sass/script/list.rb +0 -76
- data/lib/sass/script/literal.rb +0 -245
- data/lib/sass/script/variable.rb +0 -54
- data/lib/sass/scss/sass_parser.rb +0 -11
- data/test/sass/less_conversion_test.rb +0 -653
- data/vendor/fssm/README.markdown +0 -55
- data/vendor/fssm/Rakefile +0 -59
- data/vendor/fssm/VERSION.yml +0 -5
- data/vendor/fssm/example.rb +0 -9
- data/vendor/fssm/fssm.gemspec +0 -77
- data/vendor/fssm/lib/fssm/backends/fsevents.rb +0 -36
- data/vendor/fssm/lib/fssm/backends/inotify.rb +0 -26
- data/vendor/fssm/lib/fssm/backends/polling.rb +0 -25
- data/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +0 -131
- data/vendor/fssm/lib/fssm/monitor.rb +0 -26
- data/vendor/fssm/lib/fssm/path.rb +0 -91
- data/vendor/fssm/lib/fssm/pathname.rb +0 -502
- data/vendor/fssm/lib/fssm/state/directory.rb +0 -57
- data/vendor/fssm/lib/fssm/state/file.rb +0 -24
- data/vendor/fssm/lib/fssm/support.rb +0 -63
- data/vendor/fssm/lib/fssm/tree.rb +0 -176
- data/vendor/fssm/lib/fssm.rb +0 -33
- data/vendor/fssm/profile/prof-cache.rb +0 -40
- data/vendor/fssm/profile/prof-fssm-pathname.html +0 -1231
- data/vendor/fssm/profile/prof-pathname.rb +0 -68
- data/vendor/fssm/profile/prof-plain-pathname.html +0 -988
- data/vendor/fssm/profile/prof.html +0 -2379
- data/vendor/fssm/spec/path_spec.rb +0 -75
- data/vendor/fssm/spec/root/duck/quack.txt +0 -0
- data/vendor/fssm/spec/root/file.css +0 -0
- data/vendor/fssm/spec/root/file.rb +0 -0
- data/vendor/fssm/spec/root/file.yml +0 -0
- data/vendor/fssm/spec/root/moo/cow.txt +0 -0
- 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
|
7
|
+
# $color: hsl(120deg, 100%, 50%)
|
6
8
|
#
|
7
|
-
# and it will call {
|
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
|
-
# :
|
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
|
-
# :
|
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($
|
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
|
-
# :
|
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
|
-
# :
|
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
|
-
# :
|
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\],
|
94
|
-
#
|
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\],
|
97
|
-
#
|
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\],
|
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
|
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($
|
139
|
+
# \{#percentage percentage($number)}
|
113
140
|
# : Converts a unitless number to a percentage.
|
114
141
|
#
|
115
|
-
# \{#round round($
|
142
|
+
# \{#round round($number)}
|
116
143
|
# : Rounds a number to the nearest whole number.
|
117
144
|
#
|
118
|
-
# \{#ceil ceil($
|
119
|
-
# : Rounds a number up to the
|
145
|
+
# \{#ceil ceil($number)}
|
146
|
+
# : Rounds a number up to the next whole number.
|
120
147
|
#
|
121
|
-
# \{#floor floor($
|
122
|
-
# : Rounds a number down to the
|
148
|
+
# \{#floor floor($number)}
|
149
|
+
# : Rounds a number down to the previous whole number.
|
123
150
|
#
|
124
|
-
# \{#abs abs($
|
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
|
235
|
+
# : Returns the unit(s) associated with a number.
|
145
236
|
#
|
146
237
|
# \{#unitless unitless($number)}
|
147
|
-
# : Returns whether a number has units
|
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
|
-
# \{#
|
150
|
-
# :
|
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
|
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,
|
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 {
|
176
|
-
#
|
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
|
180
|
-
#
|
181
|
-
# Color
|
182
|
-
# {Sass::Script::
|
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 {
|
203
|
-
#
|
204
|
-
#
|
205
|
-
#
|
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<
|
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 {
|
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
|
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 [
|
264
|
-
# @param kwarg_arity [
|
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
|
-
|
273
|
-
|
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
|
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 -= (
|
283
|
-
t_arg_arity =
|
399
|
+
t_kwarg_arity -= (sig_arity - t_arg_arity)
|
400
|
+
t_arg_arity = sig_arity
|
284
401
|
end
|
285
402
|
|
286
|
-
if
|
287
|
-
(t_kwarg_arity == 0
|
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
|
306
|
-
def initialize(
|
307
|
-
@
|
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::
|
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
|
-
|
325
|
-
|
326
|
-
|
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
|
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
|
-
# @
|
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
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
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
|
-
#
|
381
|
-
#
|
382
|
-
#
|
383
|
-
#
|
384
|
-
# @param
|
385
|
-
#
|
386
|
-
# @param
|
387
|
-
#
|
388
|
-
# @param
|
389
|
-
#
|
390
|
-
# @
|
391
|
-
#
|
392
|
-
#
|
393
|
-
#
|
394
|
-
# @overload rgba(color, alpha)
|
395
|
-
# Sets the opacity of
|
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
|
-
#
|
403
|
-
#
|
404
|
-
#
|
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}
|
429
|
-
# Uses the algorithm from the [CSS3 spec]
|
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
|
-
# @
|
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,
|
666
|
+
hsla(hue, saturation, lightness, number(1))
|
442
667
|
end
|
443
668
|
declare :hsl, [:hue, :saturation, :lightness]
|
444
669
|
|
445
|
-
# Creates a {Color}
|
446
|
-
#
|
447
|
-
#
|
448
|
-
#
|
449
|
-
#
|
450
|
-
#
|
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
|
-
# @
|
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
|
-
|
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
|
-
|
471
|
-
|
472
|
-
|
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(
|
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
|
-
#
|
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
|
-
# @
|
484
|
-
# @
|
485
|
-
# @
|
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
|
-
|
717
|
+
assert_type color, :Color, :color
|
718
|
+
number(color.red)
|
489
719
|
end
|
490
720
|
declare :red, [:color]
|
491
721
|
|
492
|
-
#
|
722
|
+
# Gets the green component of a color. Calculated from HSL where necessary
|
723
|
+
# via [this algorithm][hsl-to-rgb].
|
493
724
|
#
|
494
|
-
#
|
495
|
-
#
|
496
|
-
# @
|
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
|
-
|
733
|
+
assert_type color, :Color, :color
|
734
|
+
number(color.green)
|
500
735
|
end
|
501
736
|
declare :green, [:color]
|
502
737
|
|
503
|
-
#
|
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
|
-
# @
|
506
|
-
# @
|
507
|
-
# @
|
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
|
-
|
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
|
-
#
|
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
|
-
#
|
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
|
-
# @
|
521
|
-
# @
|
522
|
-
# @
|
523
|
-
#
|
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
|
-
|
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
|
-
#
|
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
|
-
#
|
535
|
-
#
|
536
|
-
# @
|
537
|
-
#
|
538
|
-
# @
|
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
|
-
|
785
|
+
assert_type color, :Color, :color
|
786
|
+
number(color.saturation, "%")
|
544
787
|
end
|
545
788
|
declare :saturation, [:color]
|
546
789
|
|
547
|
-
# Returns the
|
548
|
-
#
|
549
|
-
#
|
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
|
-
#
|
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
|
-
# @
|
554
|
-
# @
|
555
|
-
# @
|
556
|
-
#
|
557
|
-
# @raise [ArgumentError] if
|
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
|
-
|
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
|
-
#
|
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
|
-
#
|
811
|
+
# This function also supports the proprietary Microsoft `alpha(opacity=20)`
|
812
|
+
# syntax as a special case.
|
569
813
|
#
|
570
|
-
# @overload
|
571
|
-
# @param color [Color]
|
572
|
-
# @return [Number]
|
573
|
-
# @
|
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
|
-
|
579
|
-
|
580
|
-
|
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
|
824
|
+
return identifier("alpha(#{args.map {|a| a.to_s}.join(", ")})")
|
583
825
|
end
|
584
826
|
|
585
|
-
|
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
|
-
#
|
834
|
+
# Returns the alpha component (opacity) of a color. This is 1 unless
|
835
|
+
# otherwise specified.
|
591
836
|
#
|
592
|
-
# @
|
593
|
-
# @
|
594
|
-
# @
|
595
|
-
# @
|
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
|
-
|
599
|
-
|
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
|
-
#
|
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
|
-
# @
|
611
|
-
# @param
|
612
|
-
# @
|
613
|
-
#
|
614
|
-
# @
|
615
|
-
#
|
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
|
-
#
|
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
|
-
# @
|
632
|
-
# @param
|
633
|
-
# @
|
634
|
-
#
|
635
|
-
# @
|
636
|
-
#
|
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
|
-
#
|
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
|
-
# @
|
653
|
-
# @param
|
654
|
-
# @
|
655
|
-
#
|
656
|
-
# @
|
657
|
-
#
|
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
|
-
#
|
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
|
-
# @
|
671
|
-
# @param
|
672
|
-
# @
|
673
|
-
#
|
674
|
-
# @
|
675
|
-
#
|
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
|
-
#
|
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
|
-
# @
|
689
|
-
# @param
|
690
|
-
# @
|
691
|
-
#
|
692
|
-
# @
|
693
|
-
#
|
694
|
-
|
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
|
-
#
|
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
|
-
# @
|
707
|
-
# @param
|
708
|
-
# @
|
709
|
-
#
|
710
|
-
# @
|
711
|
-
#
|
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
|
718
|
-
#
|
719
|
-
#
|
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
|
-
# @
|
726
|
-
# @param
|
727
|
-
# @
|
728
|
-
#
|
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
|
-
#
|
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
|
-
#
|
742
|
-
#
|
743
|
-
#
|
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
|
-
#
|
747
|
-
#
|
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
|
-
# @
|
754
|
-
#
|
755
|
-
# @param
|
756
|
-
# @param
|
757
|
-
#
|
758
|
-
# @param
|
759
|
-
#
|
760
|
-
# @param
|
761
|
-
#
|
762
|
-
# @
|
763
|
-
#
|
764
|
-
#
|
765
|
-
#
|
766
|
-
#
|
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
|
-
|
1057
|
+
) do |name, (range, units)|
|
778
1058
|
|
779
|
-
|
1059
|
+
val = kwargs.delete(name)
|
1060
|
+
next unless val
|
780
1061
|
assert_type val, :Number, name
|
781
|
-
|
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
|
-
#
|
799
|
-
#
|
800
|
-
# \{#scale_color scale-color} fluidly changes them based on how
|
801
|
-
# That means that lightening an already-light
|
802
|
-
# won't change the lightness much,
|
803
|
-
# but lightening a dark color by the same amount will change it more
|
804
|
-
# This has the benefit of making `scale-color($color, ...)`
|
805
|
-
# regardless of what `$color` is.
|
806
|
-
#
|
807
|
-
# For example, the lightness of a color can be anywhere between 0 and
|
808
|
-
# If `scale-color($color, $lightness: 40%)` is called, the resulting
|
809
|
-
# will be 40% of the way between its original lightness
|
810
|
-
# If `scale-color($color, $lightness: -40%)` is called instead,
|
811
|
-
#
|
812
|
-
#
|
813
|
-
# This can change the red, green, blue, saturation, value, and alpha
|
814
|
-
# The properties are specified as keyword arguments.
|
815
|
-
#
|
816
|
-
#
|
817
|
-
# All properties are optional.
|
818
|
-
#
|
819
|
-
#
|
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
|
823
|
-
# scale-color(rgb(200, 150
|
824
|
-
# scale-color(hsl(200, 70
|
825
|
-
# @
|
826
|
-
#
|
827
|
-
# @param
|
828
|
-
# @param
|
829
|
-
# @param
|
830
|
-
# @param
|
831
|
-
# @param
|
832
|
-
# @
|
833
|
-
# @
|
834
|
-
#
|
835
|
-
#
|
836
|
-
# or if
|
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
|
-
|
1126
|
+
) do |name, max|
|
847
1127
|
|
848
|
-
|
1128
|
+
val = kwargs.delete(name)
|
1129
|
+
next unless val
|
849
1130
|
assert_type val, :Number, name
|
850
|
-
|
851
|
-
|
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
|
-
#
|
873
|
-
#
|
874
|
-
#
|
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
|
-
#
|
882
|
-
#
|
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
|
-
# @
|
889
|
-
#
|
890
|
-
# @param
|
891
|
-
# @param
|
892
|
-
#
|
893
|
-
# @param
|
894
|
-
#
|
895
|
-
# @param
|
896
|
-
#
|
897
|
-
# @
|
898
|
-
#
|
899
|
-
#
|
900
|
-
#
|
901
|
-
#
|
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.
|
905
|
-
|
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
|
920
|
-
#
|
921
|
-
#
|
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
|
-
#
|
927
|
-
# and
|
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
|
-
#
|
937
|
-
#
|
938
|
-
#
|
939
|
-
#
|
940
|
-
#
|
941
|
-
#
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
assert_type
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
# This algorithm factors in both the user-provided weight
|
952
|
-
#
|
953
|
-
# to
|
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
|
957
|
-
#
|
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
|
-
#
|
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 = ((
|
1253
|
+
w1 = ((w * a == -1 ? w : (w + a) / (1 + w * a)) + 1) / 2.0
|
976
1254
|
w2 = 1 - w1
|
977
1255
|
|
978
|
-
|
979
|
-
|
980
|
-
|
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
|
-
#
|
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
|
-
|
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
|
-
#
|
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,
|
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
|
-
#
|
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
|
-
# @
|
1013
|
-
# @
|
1014
|
-
# @
|
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
|
-
|
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
|
1024
|
-
#
|
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
|
-
|
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
|
-
|
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
|
-
#
|
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
|
-
# @
|
1068
|
-
# @
|
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
|
-
|
1512
|
+
identifier(value.class.name.gsub(/Sass::Script::Value::/, '').downcase)
|
1071
1513
|
end
|
1072
1514
|
declare :type_of, [:value]
|
1073
1515
|
|
1074
|
-
#
|
1075
|
-
#
|
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
|
-
# @
|
1084
|
-
# @
|
1085
|
-
# @
|
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
|
-
|
1547
|
+
assert_type number, :Number, :number
|
1548
|
+
quoted_string(number.unit_str)
|
1089
1549
|
end
|
1090
1550
|
declare :unit, [:number]
|
1091
1551
|
|
1092
|
-
#
|
1552
|
+
# Returns whether a number has units.
|
1093
1553
|
#
|
1094
1554
|
# @example
|
1095
1555
|
# unitless(100) => true
|
1096
1556
|
# unitless(100px) => false
|
1097
|
-
# @
|
1098
|
-
# @
|
1099
|
-
# @
|
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
|
-
|
1562
|
+
assert_type number, :Number, :number
|
1563
|
+
bool(number.unitless?)
|
1103
1564
|
end
|
1104
1565
|
declare :unitless, [:number]
|
1105
1566
|
|
1106
|
-
# Returns
|
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
|
-
# @
|
1113
|
-
# @param
|
1114
|
-
# @
|
1115
|
-
# @
|
1116
|
-
|
1117
|
-
|
1118
|
-
assert_type
|
1119
|
-
|
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
|
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
|
-
# @
|
1128
|
-
# @
|
1129
|
-
# @
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
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
|
-
|
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
|
-
# @
|
1144
|
-
# @
|
1145
|
-
# @
|
1146
|
-
|
1147
|
-
|
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
|
1616
|
+
# Rounds a number up to the next whole number.
|
1152
1617
|
#
|
1153
1618
|
# @example
|
1154
|
-
#
|
1155
|
-
#
|
1156
|
-
# @
|
1157
|
-
# @
|
1158
|
-
# @
|
1159
|
-
|
1160
|
-
|
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
|
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
|
-
# @
|
1170
|
-
# @
|
1171
|
-
# @
|
1172
|
-
|
1173
|
-
|
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
|
-
#
|
1644
|
+
# Returns the absolute value of a number.
|
1178
1645
|
#
|
1179
1646
|
# @example
|
1180
1647
|
# abs(10px) => 10px
|
1181
1648
|
# abs(-10px) => 10px
|
1182
|
-
# @
|
1183
|
-
# @
|
1184
|
-
# @
|
1185
|
-
|
1186
|
-
|
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
|
-
#
|
1196
|
-
# @
|
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
|
-
|
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
|
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
|
-
#
|
1211
|
-
# @
|
1212
|
-
# @
|
1213
|
-
# @
|
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
|
-
|
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
|
-
|
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
|
1768
|
+
# Joins together two lists into one.
|
1231
1769
|
#
|
1232
|
-
# Unless
|
1233
|
-
#
|
1234
|
-
#
|
1235
|
-
#
|
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
|
-
#
|
1245
|
-
#
|
1246
|
-
#
|
1247
|
-
#
|
1248
|
-
#
|
1249
|
-
|
1250
|
-
|
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
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
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
|
-
#
|
1278
|
-
#
|
1279
|
-
# @overload
|
1280
|
-
#
|
1281
|
-
#
|
1282
|
-
#
|
1283
|
-
#
|
1284
|
-
#
|
1285
|
-
|
1286
|
-
|
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 =
|
1291
|
-
|
1292
|
-
|
1293
|
-
|
1294
|
-
|
1295
|
-
|
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
|
-
#
|
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
|
-
# @
|
1308
|
-
# @param
|
1309
|
-
#
|
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
|
-
|
2228
|
+
number(generator.rand)
|
1315
2229
|
end
|
1316
2230
|
end
|
1317
|
-
declare :
|
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(
|
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
|
-
|
1331
|
-
assert_type
|
1332
|
-
|
1333
|
-
|
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
|