oreorenasass 3.4.4 → 3.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +50 -70
  4. data/Rakefile +5 -26
  5. data/VERSION +1 -1
  6. data/VERSION_NAME +1 -1
  7. data/bin/sass +1 -1
  8. data/bin/scss +1 -1
  9. data/lib/sass.rb +12 -19
  10. data/lib/sass/cache_stores/base.rb +2 -2
  11. data/lib/sass/cache_stores/chain.rb +1 -2
  12. data/lib/sass/cache_stores/filesystem.rb +5 -1
  13. data/lib/sass/cache_stores/memory.rb +1 -1
  14. data/lib/sass/cache_stores/null.rb +2 -2
  15. data/lib/sass/callbacks.rb +0 -1
  16. data/lib/sass/css.rb +13 -11
  17. data/lib/sass/engine.rb +173 -424
  18. data/lib/sass/environment.rb +58 -148
  19. data/lib/sass/error.rb +14 -11
  20. data/lib/sass/exec.rb +703 -5
  21. data/lib/sass/importers/base.rb +6 -49
  22. data/lib/sass/importers/filesystem.rb +19 -44
  23. data/lib/sass/logger.rb +4 -1
  24. data/lib/sass/logger/base.rb +4 -2
  25. data/lib/sass/logger/log_level.rb +7 -3
  26. data/lib/sass/media.rb +23 -20
  27. data/lib/sass/plugin.rb +7 -7
  28. data/lib/sass/plugin/compiler.rb +145 -304
  29. data/lib/sass/plugin/configuration.rb +23 -18
  30. data/lib/sass/plugin/merb.rb +1 -1
  31. data/lib/sass/plugin/staleness_checker.rb +3 -3
  32. data/lib/sass/repl.rb +3 -3
  33. data/lib/sass/script.rb +8 -35
  34. data/lib/sass/script/{value/arg_list.rb → arg_list.rb} +25 -9
  35. data/lib/sass/script/bool.rb +18 -0
  36. data/lib/sass/script/color.rb +606 -0
  37. data/lib/sass/script/css_lexer.rb +4 -8
  38. data/lib/sass/script/css_parser.rb +2 -5
  39. data/lib/sass/script/funcall.rb +245 -0
  40. data/lib/sass/script/functions.rb +408 -1491
  41. data/lib/sass/script/interpolation.rb +79 -0
  42. data/lib/sass/script/lexer.rb +68 -172
  43. data/lib/sass/script/list.rb +85 -0
  44. data/lib/sass/script/literal.rb +221 -0
  45. data/lib/sass/script/{tree/node.rb → node.rb} +12 -22
  46. data/lib/sass/script/{value/null.rb → null.rb} +7 -14
  47. data/lib/sass/script/{value/number.rb → number.rb} +75 -152
  48. data/lib/sass/script/{tree/operation.rb → operation.rb} +24 -17
  49. data/lib/sass/script/parser.rb +110 -245
  50. data/lib/sass/script/string.rb +51 -0
  51. data/lib/sass/script/{tree/string_interpolation.rb → string_interpolation.rb} +4 -5
  52. data/lib/sass/script/{tree/unary_operation.rb → unary_operation.rb} +6 -6
  53. data/lib/sass/script/variable.rb +58 -0
  54. data/lib/sass/scss/css_parser.rb +3 -9
  55. data/lib/sass/scss/parser.rb +421 -450
  56. data/lib/sass/scss/rx.rb +11 -19
  57. data/lib/sass/scss/static_parser.rb +7 -321
  58. data/lib/sass/selector.rb +194 -68
  59. data/lib/sass/selector/abstract_sequence.rb +14 -29
  60. data/lib/sass/selector/comma_sequence.rb +25 -108
  61. data/lib/sass/selector/sequence.rb +66 -159
  62. data/lib/sass/selector/simple.rb +25 -23
  63. data/lib/sass/selector/simple_sequence.rb +63 -173
  64. data/lib/sass/shared.rb +1 -1
  65. data/lib/sass/supports.rb +15 -13
  66. data/lib/sass/tree/charset_node.rb +1 -1
  67. data/lib/sass/tree/comment_node.rb +3 -3
  68. data/lib/sass/tree/css_import_node.rb +11 -11
  69. data/lib/sass/tree/debug_node.rb +2 -2
  70. data/lib/sass/tree/directive_node.rb +4 -21
  71. data/lib/sass/tree/each_node.rb +8 -8
  72. data/lib/sass/tree/extend_node.rb +7 -14
  73. data/lib/sass/tree/for_node.rb +4 -4
  74. data/lib/sass/tree/function_node.rb +4 -9
  75. data/lib/sass/tree/if_node.rb +1 -1
  76. data/lib/sass/tree/import_node.rb +5 -4
  77. data/lib/sass/tree/media_node.rb +14 -4
  78. data/lib/sass/tree/mixin_def_node.rb +4 -4
  79. data/lib/sass/tree/mixin_node.rb +8 -21
  80. data/lib/sass/tree/node.rb +12 -54
  81. data/lib/sass/tree/prop_node.rb +20 -39
  82. data/lib/sass/tree/return_node.rb +2 -3
  83. data/lib/sass/tree/root_node.rb +3 -19
  84. data/lib/sass/tree/rule_node.rb +22 -35
  85. data/lib/sass/tree/supports_node.rb +13 -0
  86. data/lib/sass/tree/trace_node.rb +1 -2
  87. data/lib/sass/tree/variable_node.rb +3 -9
  88. data/lib/sass/tree/visitors/base.rb +8 -5
  89. data/lib/sass/tree/visitors/check_nesting.rb +19 -49
  90. data/lib/sass/tree/visitors/convert.rb +56 -74
  91. data/lib/sass/tree/visitors/cssize.rb +74 -202
  92. data/lib/sass/tree/visitors/deep_copy.rb +5 -10
  93. data/lib/sass/tree/visitors/extend.rb +7 -7
  94. data/lib/sass/tree/visitors/perform.rb +185 -278
  95. data/lib/sass/tree/visitors/set_options.rb +6 -20
  96. data/lib/sass/tree/visitors/to_css.rb +81 -234
  97. data/lib/sass/tree/warn_node.rb +2 -2
  98. data/lib/sass/tree/while_node.rb +2 -2
  99. data/lib/sass/util.rb +152 -522
  100. data/lib/sass/util/multibyte_string_scanner.rb +0 -2
  101. data/lib/sass/util/subset_map.rb +3 -4
  102. data/lib/sass/util/test.rb +1 -0
  103. data/lib/sass/version.rb +22 -20
  104. data/test/Gemfile +3 -0
  105. data/test/Gemfile.lock +10 -0
  106. data/test/sass/cache_test.rb +20 -62
  107. data/test/sass/callbacks_test.rb +1 -1
  108. data/test/sass/conversion_test.rb +2 -296
  109. data/test/sass/css2sass_test.rb +4 -23
  110. data/test/sass/engine_test.rb +354 -411
  111. data/test/sass/exec_test.rb +2 -2
  112. data/test/sass/extend_test.rb +145 -324
  113. data/test/sass/functions_test.rb +86 -873
  114. data/test/sass/importer_test.rb +21 -241
  115. data/test/sass/logger_test.rb +1 -1
  116. data/test/sass/more_results/more_import.css +1 -1
  117. data/test/sass/plugin_test.rb +26 -16
  118. data/test/sass/results/compact.css +1 -1
  119. data/test/sass/results/complex.css +4 -4
  120. data/test/sass/results/expanded.css +1 -1
  121. data/test/sass/results/import.css +1 -1
  122. data/test/sass/results/import_charset_ibm866.css +2 -2
  123. data/test/sass/results/mixins.css +17 -17
  124. data/test/sass/results/nested.css +1 -1
  125. data/test/sass/results/parent_ref.css +2 -2
  126. data/test/sass/results/script.css +3 -3
  127. data/test/sass/results/scss_import.css +1 -1
  128. data/test/sass/script_conversion_test.rb +7 -36
  129. data/test/sass/script_test.rb +53 -485
  130. data/test/sass/scss/css_test.rb +28 -143
  131. data/test/sass/scss/rx_test.rb +4 -4
  132. data/test/sass/scss/scss_test.rb +325 -2119
  133. data/test/sass/templates/scss_import.scss +1 -2
  134. data/test/sass/test_helper.rb +1 -1
  135. data/test/sass/util/multibyte_string_scanner_test.rb +1 -1
  136. data/test/sass/util/subset_map_test.rb +2 -2
  137. data/test/sass/util_test.rb +1 -86
  138. data/test/test_helper.rb +8 -37
  139. metadata +19 -66
  140. data/lib/sass/exec/base.rb +0 -187
  141. data/lib/sass/exec/sass_convert.rb +0 -264
  142. data/lib/sass/exec/sass_scss.rb +0 -424
  143. data/lib/sass/features.rb +0 -47
  144. data/lib/sass/script/tree.rb +0 -16
  145. data/lib/sass/script/tree/funcall.rb +0 -306
  146. data/lib/sass/script/tree/interpolation.rb +0 -118
  147. data/lib/sass/script/tree/list_literal.rb +0 -77
  148. data/lib/sass/script/tree/literal.rb +0 -45
  149. data/lib/sass/script/tree/map_literal.rb +0 -64
  150. data/lib/sass/script/tree/selector.rb +0 -26
  151. data/lib/sass/script/tree/variable.rb +0 -57
  152. data/lib/sass/script/value.rb +0 -11
  153. data/lib/sass/script/value/base.rb +0 -240
  154. data/lib/sass/script/value/bool.rb +0 -35
  155. data/lib/sass/script/value/color.rb +0 -680
  156. data/lib/sass/script/value/helpers.rb +0 -262
  157. data/lib/sass/script/value/list.rb +0 -113
  158. data/lib/sass/script/value/map.rb +0 -70
  159. data/lib/sass/script/value/string.rb +0 -97
  160. data/lib/sass/selector/pseudo.rb +0 -256
  161. data/lib/sass/source/map.rb +0 -210
  162. data/lib/sass/source/position.rb +0 -39
  163. data/lib/sass/source/range.rb +0 -41
  164. data/lib/sass/stack.rb +0 -120
  165. data/lib/sass/tree/at_root_node.rb +0 -83
  166. data/lib/sass/tree/error_node.rb +0 -18
  167. data/lib/sass/tree/keyframe_rule_node.rb +0 -15
  168. data/lib/sass/util/cross_platform_random.rb +0 -19
  169. data/lib/sass/util/normalized_map.rb +0 -130
  170. data/lib/sass/util/ordered_hash.rb +0 -192
  171. data/test/sass/compiler_test.rb +0 -232
  172. data/test/sass/encoding_test.rb +0 -219
  173. data/test/sass/source_map_test.rb +0 -977
  174. data/test/sass/superselector_test.rb +0 -191
  175. data/test/sass/util/normalized_map_test.rb +0 -51
  176. data/test/sass/value_helpers_test.rb +0 -179
@@ -12,20 +12,16 @@ module Sass
12
12
 
13
13
  def string(re, *args)
14
14
  if re == :uri
15
- uri = scan(URI)
16
- return unless uri
17
- return [:string, Script::Value::String.new(uri)]
15
+ return unless uri = scan(URI)
16
+ return [:string, Script::String.new(uri)]
18
17
  end
19
18
 
20
19
  return unless scan(STRING)
21
- string_value = Sass::Script::Value::String.value(@scanner[1] || @scanner[2])
22
- value = Script::Value::String.new(string_value, :string)
23
- [:string, value]
20
+ [:string, Script::String.new((@scanner[1] || @scanner[2]).gsub(/\\(['"])/, '\1'), :string)]
24
21
  end
25
22
 
26
23
  def important
27
- s = scan(IMPORTANT)
28
- return unless s
24
+ return unless s = scan(IMPORTANT)
29
25
  [:raw, s]
30
26
  end
31
27
  end
@@ -17,11 +17,8 @@ module Sass
17
17
  production :div, :unary_plus, :div
18
18
 
19
19
  def string
20
- tok = try_tok(:string)
21
- return number unless tok
22
- unless @lexer.peek && @lexer.peek.type == :begin_interpolation
23
- return literal_node(tok.value, tok.source_range)
24
- end
20
+ return number unless tok = try_tok(:string)
21
+ return tok.value unless @lexer.peek && @lexer.peek.type == :begin_interpolation
25
22
  end
26
23
 
27
24
  # Short-circuit all the SassScript-only productions
@@ -0,0 +1,245 @@
1
+ require 'sass/script/functions'
2
+
3
+ module Sass
4
+ module Script
5
+ # A SassScript parse node representing a function call.
6
+ #
7
+ # A function call either calls one of the functions in {Script::Functions},
8
+ # or if no function with the given name exists
9
+ # it returns a string representation of the function call.
10
+ class Funcall < Node
11
+ # The name of the function.
12
+ #
13
+ # @return [String]
14
+ attr_reader :name
15
+
16
+ # The arguments to the function.
17
+ #
18
+ # @return [Array<Script::Node>]
19
+ attr_reader :args
20
+
21
+ # The keyword arguments to the function.
22
+ #
23
+ # @return [{String => Script::Node}]
24
+ attr_reader :keywords
25
+
26
+ # The splat argument for this function, if one exists.
27
+ #
28
+ # @return [Script::Node?]
29
+ attr_accessor :splat
30
+
31
+ # @param name [String] See \{#name}
32
+ # @param args [Array<Script::Node>] See \{#args}
33
+ # @param splat [Script::Node] See \{#splat}
34
+ # @param keywords [{String => Script::Node}] See \{#keywords}
35
+ def initialize(name, args, keywords, splat)
36
+ @name = name
37
+ @args = args
38
+ @keywords = keywords
39
+ @splat = splat
40
+ super()
41
+ end
42
+
43
+ # @return [String] A string representation of the function call
44
+ def inspect
45
+ args = @args.map {|a| a.inspect}.join(', ')
46
+ keywords = Sass::Util.hash_to_a(@keywords).
47
+ map {|k, v| "$#{k}: #{v.inspect}"}.join(', ')
48
+ if self.splat
49
+ splat = (args.empty? && keywords.empty?) ? "" : ", "
50
+ splat = "#{splat}#{self.splat.inspect}..."
51
+ end
52
+ "#{name}(#{args}#{', ' unless args.empty? || keywords.empty?}#{keywords}#{splat})"
53
+ end
54
+
55
+ # @see Node#to_sass
56
+ def to_sass(opts = {})
57
+ arg_to_sass = lambda do |arg|
58
+ sass = arg.to_sass(opts)
59
+ sass = "(#{sass})" if arg.is_a?(Sass::Script::List) && arg.separator == :comma
60
+ sass
61
+ end
62
+
63
+ args = @args.map(&arg_to_sass).join(', ')
64
+ keywords = Sass::Util.hash_to_a(@keywords).
65
+ map {|k, v| "$#{dasherize(k, opts)}: #{arg_to_sass[v]}"}.join(', ')
66
+ if self.splat
67
+ splat = (args.empty? && keywords.empty?) ? "" : ", "
68
+ splat = "#{splat}#{arg_to_sass[self.splat]}..."
69
+ end
70
+ "#{dasherize(name, opts)}(#{args}#{', ' unless args.empty? || keywords.empty?}#{keywords}#{splat})"
71
+ end
72
+
73
+ # Returns the arguments to the function.
74
+ #
75
+ # @return [Array<Node>]
76
+ # @see Node#children
77
+ def children
78
+ res = @args + @keywords.values
79
+ res << @splat if @splat
80
+ res
81
+ end
82
+
83
+ # @see Node#deep_copy
84
+ def deep_copy
85
+ node = dup
86
+ node.instance_variable_set('@args', args.map {|a| a.deep_copy})
87
+ node.instance_variable_set('@keywords', Hash[keywords.map {|k, v| [k, v.deep_copy]}])
88
+ node
89
+ end
90
+
91
+ protected
92
+
93
+ # Evaluates the function call.
94
+ #
95
+ # @param environment [Sass::Environment] The environment in which to evaluate the SassScript
96
+ # @return [Literal] The SassScript object that is the value of the function call
97
+ # @raise [Sass::SyntaxError] if the function call raises an ArgumentError
98
+ def _perform(environment)
99
+ args = @args.map {|a| a.perform(environment)}
100
+ splat = @splat.perform(environment) if @splat
101
+ if fn = environment.function(@name)
102
+ keywords = Sass::Util.map_hash(@keywords) {|k, v| [k, v.perform(environment)]}
103
+ return without_original(perform_sass_fn(fn, args, keywords, splat))
104
+ end
105
+
106
+ ruby_name = @name.tr('-', '_')
107
+ args = construct_ruby_args(ruby_name, args, splat, environment)
108
+
109
+ unless Functions.callable?(ruby_name)
110
+ without_original(opts(to_literal(args)))
111
+ else
112
+ without_original(opts(Functions::EvaluationContext.new(environment.options).
113
+ send(ruby_name, *args)))
114
+ end
115
+ rescue ArgumentError => e
116
+ message = e.message
117
+
118
+ # If this is a legitimate Ruby-raised argument error, re-raise it.
119
+ # Otherwise, it's an error in the user's stylesheet, so wrap it.
120
+ if Sass::Util.rbx?
121
+ # Rubinius has a different error report string than vanilla Ruby. It
122
+ # also doesn't put the actual method for which the argument error was
123
+ # thrown in the backtrace, nor does it include `send`, so we look for
124
+ # `_perform`.
125
+ if e.message =~ /^method '([^']+)': given (\d+), expected (\d+)/
126
+ error_name, given, expected = $1, $2, $3
127
+ raise e if error_name != ruby_name || e.backtrace[0] !~ /:in `_perform'$/
128
+ message = "wrong number of arguments (#{given} for #{expected})"
129
+ end
130
+ elsif Sass::Util.jruby?
131
+ if Sass::Util.jruby1_6?
132
+ should_maybe_raise = e.message =~ /^wrong number of arguments \((\d+) for (\d+)\)/ &&
133
+ # The one case where JRuby does include the Ruby name of the function
134
+ # is manually-thrown ArgumentErrors, which are indistinguishable from
135
+ # legitimate ArgumentErrors. We treat both of these as
136
+ # Sass::SyntaxErrors even though it can hide Ruby errors.
137
+ e.backtrace[0] !~ /:in `(block in )?#{ruby_name}'$/
138
+ else
139
+ should_maybe_raise = e.message =~ /^wrong number of arguments calling `[^`]+` \((\d+) for (\d+)\)/
140
+ given, expected = $1, $2
141
+ end
142
+
143
+ if should_maybe_raise
144
+ # JRuby 1.7 includes __send__ before send and _perform.
145
+ trace = e.backtrace.dup
146
+ raise e if !Sass::Util.jruby1_6? && trace.shift !~ /:in `__send__'$/
147
+
148
+ # JRuby (as of 1.7.2) doesn't put the actual method
149
+ # for which the argument error was thrown in the backtrace, so we
150
+ # detect whether our send threw an argument error.
151
+ if !(trace[0] =~ /:in `send'$/ && trace[1] =~ /:in `_perform'$/)
152
+ raise e
153
+ elsif !Sass::Util.jruby1_6?
154
+ # JRuby 1.7 doesn't use standard formatting for its ArgumentErrors.
155
+ message = "wrong number of arguments (#{given} for #{expected})"
156
+ end
157
+ end
158
+ elsif e.message =~ /^wrong number of arguments \(\d+ for \d+\)/ &&
159
+ e.backtrace[0] !~ /:in `(block in )?#{ruby_name}'$/
160
+ raise e
161
+ end
162
+ raise Sass::SyntaxError.new("#{message} for `#{name}'")
163
+ end
164
+
165
+ # This method is factored out from `_perform` so that compass can override
166
+ # it with a cross-browser implementation for functions that require vendor prefixes
167
+ # in the generated css.
168
+ def to_literal(args)
169
+ Script::String.new("#{name}(#{args.join(', ')})")
170
+ end
171
+
172
+ private
173
+
174
+ def without_original(value)
175
+ return value unless value.is_a?(Number)
176
+ value = value.dup
177
+ value.original = nil
178
+ return value
179
+ end
180
+
181
+ def construct_ruby_args(name, args, splat, environment)
182
+ args += splat.to_a if splat
183
+
184
+ # If variable arguments were passed, there won't be any explicit keywords.
185
+ if splat.is_a?(Sass::Script::ArgList)
186
+ kwargs_size = splat.keywords.size
187
+ splat.keywords_accessed = false
188
+ else
189
+ kwargs_size = @keywords.size
190
+ end
191
+
192
+ unless signature = Functions.signature(name.to_sym, args.size, kwargs_size)
193
+ return args if @keywords.empty?
194
+ raise Sass::SyntaxError.new("Function #{name} doesn't support keyword arguments")
195
+ end
196
+ keywords = splat.is_a?(Sass::Script::ArgList) ? splat.keywords :
197
+ Sass::Util.map_hash(@keywords) {|k, v| [k, v.perform(environment)]}
198
+
199
+ # If the user passes more non-keyword args than the function expects,
200
+ # but it does expect keyword args, Ruby's arg handling won't raise an error.
201
+ # Since we don't want to make functions think about this,
202
+ # we'll handle it for them here.
203
+ if signature.var_kwargs && !signature.var_args && args.size > signature.args.size
204
+ raise Sass::SyntaxError.new(
205
+ "#{args[signature.args.size].inspect} is not a keyword argument for `#{name}'")
206
+ elsif keywords.empty?
207
+ return args
208
+ end
209
+
210
+ args = args + signature.args[args.size..-1].map do |argname|
211
+ if keywords.has_key?(argname)
212
+ keywords.delete(argname)
213
+ else
214
+ raise Sass::SyntaxError.new("Function #{name} requires an argument named $#{argname}")
215
+ end
216
+ end
217
+
218
+ if keywords.size > 0
219
+ if signature.var_kwargs
220
+ args << keywords
221
+ else
222
+ argname = keywords.keys.sort.first
223
+ if signature.args.include?(argname)
224
+ raise Sass::SyntaxError.new("Function #{name} was passed argument $#{argname} both by position and by name")
225
+ else
226
+ raise Sass::SyntaxError.new("Function #{name} doesn't have an argument named $#{argname}")
227
+ end
228
+ end
229
+ end
230
+
231
+ args
232
+ end
233
+
234
+ def perform_sass_fn(function, args, keywords, splat)
235
+ Sass::Tree::Visitors::Perform.perform_arguments(function, args, keywords, splat) do |env|
236
+ val = catch :_sass_return do
237
+ function.tree.each {|c| Sass::Tree::Visitors::Perform.visit(c, env)}
238
+ raise Sass::SyntaxError.new("Function #{@name} finished without @return")
239
+ end
240
+ val
241
+ end
242
+ end
243
+ end
244
+ end
245
+ end
@@ -1,15 +1,10 @@
1
- require 'sass/script/value/helpers'
2
-
3
1
  module Sass::Script
4
- # @comment
5
- # YARD can't handle some multiline tags, and we need really long tags for function declarations.
6
- # rubocop:disable LineLength
7
2
  # Methods in this module are accessible from the SassScript context.
8
3
  # For example, you can write
9
4
  #
10
5
  # $color: hsl(120deg, 100%, 50%)
11
6
  #
12
- # and it will call {Functions#hsl}.
7
+ # and it will call {Sass::Script::Functions#hsl}.
13
8
  #
14
9
  # The following functions are provided:
15
10
  #
@@ -18,12 +13,10 @@ module Sass::Script
18
13
  # ## RGB Functions
19
14
  #
20
15
  # \{#rgb rgb($red, $green, $blue)}
21
- # : Creates a {Sass::Script::Value::Color Color} from red, green, and blue
22
- # values.
16
+ # : Creates a {Color} from red, green, and blue values.
23
17
  #
24
18
  # \{#rgba rgba($red, $green, $blue, $alpha)}
25
- # : Creates a {Sass::Script::Value::Color Color} from red, green, blue, and
26
- # alpha values.
19
+ # : Creates a {Color} from red, green, blue, and alpha values.
27
20
  #
28
21
  # \{#red red($color)}
29
22
  # : Gets the red component of a color.
@@ -34,18 +27,17 @@ module Sass::Script
34
27
  # \{#blue blue($color)}
35
28
  # : Gets the blue component of a color.
36
29
  #
37
- # \{#mix mix($color1, $color2, \[$weight\])}
30
+ # \{#mix mix($color-1, $color-2, \[$weight\])}
38
31
  # : Mixes two colors together.
39
32
  #
40
33
  # ## HSL Functions
41
34
  #
42
35
  # \{#hsl hsl($hue, $saturation, $lightness)}
43
- # : Creates a {Sass::Script::Value::Color Color} from hue, saturation, and
44
- # lightness values.
36
+ # : Creates a {Color} from hue, saturation, and lightness values.
45
37
  #
46
38
  # \{#hsla hsla($hue, $saturation, $lightness, $alpha)}
47
- # : Creates a {Sass::Script::Value::Color Color} from hue, saturation,
48
- # lightness, and alpha values.
39
+ # : Creates a {Color} from hue, saturation, lightness, and alpha
40
+ # values.
49
41
  #
50
42
  # \{#hue hue($color)}
51
43
  # : Gets the hue component of a color.
@@ -116,39 +108,21 @@ module Sass::Script
116
108
  # \{#quote quote($string)}
117
109
  # : Adds quotes to a string.
118
110
  #
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
- #
137
111
  # ## Number Functions
138
112
  #
139
- # \{#percentage percentage($number)}
113
+ # \{#percentage percentage($value)}
140
114
  # : Converts a unitless number to a percentage.
141
115
  #
142
- # \{#round round($number)}
116
+ # \{#round round($value)}
143
117
  # : Rounds a number to the nearest whole number.
144
118
  #
145
- # \{#ceil ceil($number)}
119
+ # \{#ceil ceil($value)}
146
120
  # : Rounds a number up to the next whole number.
147
121
  #
148
- # \{#floor floor($number)}
122
+ # \{#floor floor($value)}
149
123
  # : Rounds a number down to the previous whole number.
150
124
  #
151
- # \{#abs abs($number)}
125
+ # \{#abs abs($value)}
152
126
  # : Returns the absolute value of a number.
153
127
  #
154
128
  # \{#min min($numbers...)\}
@@ -157,13 +131,8 @@ module Sass::Script
157
131
  # \{#max max($numbers...)\}
158
132
  # : Finds the maximum of several numbers.
159
133
  #
160
- # \{#random random([$limit])\}
161
- # : Returns a random number.
162
- #
163
134
  # ## List Functions {#list-functions}
164
135
  #
165
- # All list functions work for maps as well, treating them as lists of pairs.
166
- #
167
136
  # \{#length length($list)}
168
137
  # : Returns the length of a list.
169
138
  #
@@ -182,94 +151,8 @@ module Sass::Script
182
151
  # \{#index index($list, $value)}
183
152
  # : Returns the position of a value within a list.
184
153
  #
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, $keys...)}
197
- # : Returns a new map with keys 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($map, $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
- #
211
- # ## Selector Functions
212
- #
213
- # Selector functions are very liberal in the formats they support
214
- # for selector arguments. They can take a plain string, a list of
215
- # lists as returned by `&` or anything in between:
216
- #
217
- # * A plain sring, such as `".foo .bar, .baz .bang"`.
218
- # * A space-separated list of strings such as `(".foo" ".bar")`.
219
- # * A comma-separated list of strings such as `(".foo .bar", ".baz .bang")`.
220
- # * A comma-separated list of space-separated lists of strings such
221
- # as `((".foo" ".bar"), (".baz" ".bang"))`.
222
- #
223
- # In general, selector functions allow placeholder selectors
224
- # (`%foo`) but disallow parent-reference selectors (`&`).
225
- #
226
- # \{#selector_nest selector-nest($selectors...)}
227
- # : Nests selector beneath one another like they would be nested in the
228
- # stylesheet.
229
- #
230
- # \{#selector_append selector-append($selectors...)}
231
- # : Appends selectors to one another without spaces in between.
232
- #
233
- # \{#selector_extend selector-extend($selector, $extendee, $extender)}
234
- # : Extends `$extendee` with `$extender` within `$selector`.
235
- #
236
- # \{#selector_replace selector-replace($selector, $original, $replacement)}
237
- # : Replaces `$original` with `$replacement` within `$selector`.
238
- #
239
- # \{#selector_unify selector-unify($selector1, $selector2)}
240
- # : Unifies two selectors to produce a selector that matches
241
- # elements matched by both.
242
- #
243
- # \{#is_superselector is-superselector($super, $sub)}
244
- # : Returns whether `$super` matches all the elements `$sub` does, and
245
- # possibly more.
246
- #
247
- # \{#simple_selectors simple-selectors($selector)}
248
- # : Returns the simple selectors that comprise a compound selector.
249
- #
250
- # \{#selector_parse selector-parse($selector)}
251
- # : Parses a selector into the format returned by `&`.
252
- #
253
154
  # ## Introspection Functions
254
155
  #
255
- # \{#feature_exists feature-exists($feature)}
256
- # : Returns whether a feature exists in the current Sass runtime.
257
- #
258
- # \{#variable_exists variable-exists($name)}
259
- # : Returns whether a variable with the given name exists in the current scope.
260
- #
261
- # \{#global_variable_exists global-variable-exists($name)}
262
- # : Returns whether a variable with the given name exists in the global scope.
263
- #
264
- # \{#function_exists function-exists($name)}
265
- # : Returns whether a function with the given name exists.
266
- #
267
- # \{#mixin_exists mixin-exists($name)}
268
- # : Returns whether a mixin with the given name exists.
269
- #
270
- # \{#inspect inspect($value)}
271
- # : Returns the string representation of a value as it would be represented in Sass.
272
- #
273
156
  # \{#type_of type-of($value)}
274
157
  # : Returns the type of a value.
275
158
  #
@@ -279,21 +162,15 @@ module Sass::Script
279
162
  # \{#unitless unitless($number)}
280
163
  # : Returns whether a number has units.
281
164
  #
282
- # \{#comparable comparable($number1, $number2)}
165
+ # \{#comparable comparable($number-1, $number-2)}
283
166
  # : Returns whether two numbers can be added, subtracted, or compared.
284
167
  #
285
- # \{#call call($name, $args...)}
286
- # : Dynamically calls a Sass function.
287
- #
288
168
  # ## Miscellaneous Functions
289
169
  #
290
170
  # \{#if if($condition, $if-true, $if-false)}
291
171
  # : Returns one of two values, depending on whether or not `$condition` is
292
172
  # true.
293
173
  #
294
- # \{#unique_id unique-id()}
295
- # : Returns a unique CSS identifier.
296
- #
297
174
  # ## Adding Custom Functions
298
175
  #
299
176
  # New Sass functions can be added by adding Ruby methods to this module.
@@ -302,9 +179,9 @@ module Sass::Script
302
179
  # module Sass::Script::Functions
303
180
  # def reverse(string)
304
181
  # assert_type string, :String
305
- # Sass::Script::Value::String.new(string.value.reverse)
182
+ # Sass::Script::String.new(string.value.reverse)
306
183
  # end
307
- # declare :reverse, [:string]
184
+ # declare :reverse, :args => [:string]
308
185
  # end
309
186
  #
310
187
  # Calling {declare} tells Sass the argument names for your function.
@@ -312,15 +189,14 @@ module Sass::Script
312
189
  # {declare} can also allow your function to take arbitrary keyword arguments.
313
190
  #
314
191
  # There are a few things to keep in mind when modifying this module.
315
- # First of all, the arguments passed are {Value} objects.
316
- # Value objects are also expected to be returned.
192
+ # First of all, the arguments passed are {Sass::Script::Literal} objects.
193
+ # Literal objects are also expected to be returned.
317
194
  # This means that Ruby values must be unwrapped and wrapped.
318
195
  #
319
- # Most Value objects support the {Value::Base#value value} accessor for getting
320
- # their Ruby values. Color objects, though, must be accessed using
321
- # {Sass::Script::Value::Color#rgb rgb}, {Sass::Script::Value::Color#red red},
322
- # {Sass::Script::Value::Color#blue green}, or {Sass::Script::Value::Color#blue
323
- # blue}.
196
+ # Most Literal objects support the {Sass::Script::Literal#value value} accessor
197
+ # for getting their Ruby values.
198
+ # Color objects, though, must be accessed using {Sass::Script::Color#rgb rgb},
199
+ # {Sass::Script::Color#red red}, {Sass::Script::Color#blue green}, or {Sass::Script::Color#blue blue}.
324
200
  #
325
201
  # Second, making Ruby functions accessible from Sass introduces the temptation
326
202
  # to do things like database access within stylesheets.
@@ -340,24 +216,19 @@ module Sass::Script
340
216
  #
341
217
  # ### Caveats
342
218
  #
343
- # When creating new {Value} objects within functions, be aware that it's not
344
- # safe to call {Value::Base#to_s #to_s} (or other methods that use the string
345
- # representation) on those objects without first setting {Tree::Node#options=
346
- # the #options attribute}.
347
- #
348
- # @comment
349
- # rubocop:enable LineLength
219
+ # When creating new {Literal} objects within functions,
220
+ # be aware that it's not safe to call {Literal#to_s #to_s}
221
+ # (or other methods that use the string representation)
222
+ # on those objects without first setting {Node#options= the #options attribute}.
350
223
  module Functions
351
224
  @signatures = {}
352
225
 
353
226
  # A class representing a Sass function signature.
354
227
  #
355
- # @attr args [Array<String>] The names of the arguments to the function.
356
- # @attr delayed_args [Array<String>] The names of the arguments whose evaluation should be
357
- # delayed.
228
+ # @attr args [Array<Symbol>] The names of the arguments to the function.
358
229
  # @attr var_args [Boolean] Whether the function takes a variable number of arguments.
359
230
  # @attr var_kwargs [Boolean] Whether the function takes an arbitrary set of keyword arguments.
360
- Signature = Struct.new(:args, :delayed_args, :var_args, :var_kwargs, :deprecated)
231
+ Signature = Struct.new(:args, :var_args, :var_kwargs)
361
232
 
362
233
  # Declare a Sass signature for a Ruby-defined function.
363
234
  # This includes the names of the arguments,
@@ -390,30 +261,15 @@ module Sass::Script
390
261
  # Whether the function accepts other keyword arguments
391
262
  # in addition to those in `:args`.
392
263
  # If this is true, the Ruby function will be passed a hash from strings
393
- # to {Value}s as the last argument.
264
+ # to {Sass::Script::Literal}s as the last argument.
394
265
  # In addition, if this is true and `:var_args` is not,
395
266
  # Sass will ensure that the last argument passed is a hash.
396
267
  def self.declare(method_name, args, options = {})
397
- delayed_args = []
398
- args = args.map do |a|
399
- a = a.to_s
400
- if a[0] == ?&
401
- a = a[1..-1]
402
- delayed_args << a
403
- end
404
- a
405
- end
406
- # We don't expose this functionality except to certain builtin methods.
407
- if delayed_args.any? && method_name != :if
408
- raise ArgumentError.new("Delayed arguments are not allowed for method #{method_name}")
409
- end
410
268
  @signatures[method_name] ||= []
411
269
  @signatures[method_name] << Signature.new(
412
- args,
413
- delayed_args,
270
+ args.map {|s| s.to_s},
414
271
  options[:var_args],
415
- options[:var_kwargs],
416
- options[:deprecated] && options[:deprecated].map {|a| a.to_s})
272
+ options[:var_kwargs])
417
273
  end
418
274
 
419
275
  # Determine the correct signature for the number of arguments
@@ -421,8 +277,8 @@ module Sass::Script
421
277
  # If no signatures match, the first signature is returned for error messaging.
422
278
  #
423
279
  # @param method_name [Symbol] The name of the Ruby function to be called.
424
- # @param arg_arity [Fixnum] The number of unnamed arguments the function was passed.
425
- # @param kwarg_arity [Fixnum] The number of keyword arguments the function was passed.
280
+ # @param arg_arity [Number] The number of unnamed arguments the function was passed.
281
+ # @param kwarg_arity [Number] The number of keyword arguments the function was passed.
426
282
  #
427
283
  # @return [{Symbol => Object}, nil]
428
284
  # The signature options for the matching signature,
@@ -430,76 +286,42 @@ module Sass::Script
430
286
  def self.signature(method_name, arg_arity, kwarg_arity)
431
287
  return unless @signatures[method_name]
432
288
  @signatures[method_name].each do |signature|
433
- sig_arity = signature.args.size
434
- return signature if sig_arity == arg_arity + kwarg_arity
435
- next unless sig_arity < arg_arity + kwarg_arity
289
+ return signature if signature.args.size == arg_arity + kwarg_arity
290
+ next unless signature.args.size < arg_arity + kwarg_arity
436
291
 
437
292
  # We have enough args.
438
293
  # Now we need to figure out which args are varargs
439
294
  # and if the signature allows them.
440
295
  t_arg_arity, t_kwarg_arity = arg_arity, kwarg_arity
441
- if sig_arity > t_arg_arity
296
+ if signature.args.size > t_arg_arity
442
297
  # we transfer some kwargs arity to args arity
443
298
  # if it does not have enough args -- assuming the names will work out.
444
- t_kwarg_arity -= (sig_arity - t_arg_arity)
445
- t_arg_arity = sig_arity
299
+ t_kwarg_arity -= (signature.args.size - t_arg_arity)
300
+ t_arg_arity = signature.args.size
446
301
  end
447
302
 
448
- if (t_arg_arity == sig_arity || t_arg_arity > sig_arity && signature.var_args) &&
449
- (t_kwarg_arity == 0 || t_kwarg_arity > 0 && signature.var_kwargs)
303
+ if ( t_arg_arity == signature.args.size || t_arg_arity > signature.args.size && signature.var_args ) &&
304
+ (t_kwarg_arity == 0 || t_kwarg_arity > 0 && signature.var_kwargs)
450
305
  return signature
451
306
  end
452
307
  end
453
308
  @signatures[method_name].first
454
309
  end
455
310
 
456
- # Sets the random seed used by Sass's internal random number generator.
457
- #
458
- # This can be used to ensure consistent random number sequences which
459
- # allows for consistent results when testing, etc.
460
- #
461
- # @param seed [Integer]
462
- # @return [Integer] The same seed.
463
- def self.random_seed=(seed)
464
- @random_number_generator = Sass::Util::CrossPlatformRandom.new(seed)
465
- end
466
-
467
- # Get Sass's internal random number generator.
468
- #
469
- # @return [Random]
470
- def self.random_number_generator
471
- @random_number_generator ||= Sass::Util::CrossPlatformRandom.new
472
- end
473
-
474
311
  # The context in which methods in {Script::Functions} are evaluated.
475
312
  # That means that all instance methods of {EvaluationContext}
476
313
  # are available to use in functions.
477
314
  class EvaluationContext
478
315
  include Functions
479
- include Value::Helpers
480
-
481
- # The human-readable names for [Sass::Script::Value::Base]. The default is
482
- # just the downcased name of the type. The default is the downcased type
483
- # name.
484
- TYPE_NAMES = {:ArgList => 'variable argument list'}
485
-
486
- # The environment for this function. This environment's
487
- # {Environment#parent} is the global environment, and its
488
- # {Environment#caller} is a read-only view of the local environment of the
489
- # caller of this function.
490
- #
491
- # @return [Environment]
492
- attr_reader :environment
493
316
 
494
317
  # The options hash for the {Sass::Engine} that is processing the function call
495
318
  #
496
319
  # @return [{Symbol => Object}]
497
320
  attr_reader :options
498
321
 
499
- # @param environment [Environment] See \{#environment}
500
- def initialize(environment)
501
- @environment = environment
502
- @options = environment.options
322
+ # @param options [{Symbol => Object}] See \{#options}
323
+ def initialize(options)
324
+ @options = options
503
325
  end
504
326
 
505
327
  # Asserts that the type of a given SassScript value
@@ -512,79 +334,15 @@ module Sass::Script
512
334
  # @example
513
335
  # assert_type value, :String
514
336
  # assert_type value, :Number
515
- # @param value [Sass::Script::Value::Base] A SassScript value
337
+ # @param value [Sass::Script::Literal] A SassScript value
516
338
  # @param type [Symbol] The name of the type the value is expected to be
517
339
  # @param name [String, Symbol, nil] The name of the argument.
518
- # @raise [ArgumentError] if value is not of the correct type.
519
340
  def assert_type(value, type, name = nil)
520
- klass = Sass::Script::Value.const_get(type)
521
- return if value.is_a?(klass)
522
- return if value.is_a?(Sass::Script::Value::List) && type == :Map && value.value.empty?
523
- err = "#{value.inspect} is not a #{TYPE_NAMES[type] || type.to_s.downcase}"
341
+ return if value.is_a?(Sass::Script.const_get(type))
342
+ err = "#{value.inspect} is not a #{type.to_s.downcase}"
524
343
  err = "$#{name.to_s.gsub('_', '-')}: " + err if name
525
344
  raise ArgumentError.new(err)
526
345
  end
527
-
528
- # Asserts that the unit of the number is as expected.
529
- #
530
- # @example
531
- # assert_unit number, "px"
532
- # assert_unit number, nil
533
- # @param number [Sass::Script::Value::Number] The number to be validated.
534
- # @param unit [::String]
535
- # The unit that the number must have.
536
- # If nil, the number must be unitless.
537
- # @param name [::String] The name of the parameter being validated.
538
- # @raise [ArgumentError] if number is not of the correct unit or is not a number.
539
- def assert_unit(number, unit, name = nil)
540
- assert_type number, :Number, name
541
- return if number.is_unit?(unit)
542
- expectation = unit ? "have a unit of #{unit}" : "be unitless"
543
- if name
544
- raise ArgumentError.new("Expected $#{name} to #{expectation} but got #{number}")
545
- else
546
- raise ArgumentError.new("Expected #{number} to #{expectation}")
547
- end
548
- end
549
-
550
- # Asserts that the value is an integer.
551
- #
552
- # @example
553
- # assert_integer 2px
554
- # assert_integer 2.5px
555
- # => SyntaxError: "Expected 2.5px to be an integer"
556
- # assert_integer 2.5px, "width"
557
- # => SyntaxError: "Expected width to be an integer but got 2.5px"
558
- # @param number [Sass::Script::Value::Base] The value to be validated.
559
- # @param name [::String] The name of the parameter being validated.
560
- # @raise [ArgumentError] if number is not an integer or is not a number.
561
- def assert_integer(number, name = nil)
562
- assert_type number, :Number, name
563
- return if number.int?
564
- if name
565
- raise ArgumentError.new("Expected $#{name} to be an integer but got #{number}")
566
- else
567
- raise ArgumentError.new("Expected #{number} to be an integer")
568
- end
569
- end
570
-
571
- # Performs a node that has been delayed for execution.
572
- #
573
- # @private
574
- # @param node [Sass::Script::Tree::Node,
575
- # Sass::Script::Value::Base] When this is a tree node, it's
576
- # performed in the caller's environment. When it's a value
577
- # (which can happen when the value had to be performed already
578
- # -- like for a splat), it's returned as-is.
579
- # @param env [Sass::Environment] The environment within which to perform the node.
580
- # Defaults to the (read-only) environment of the caller.
581
- def perform(node, env = environment.caller)
582
- if node.is_a?(Sass::Script::Value::Base)
583
- node
584
- else
585
- node.perform(env)
586
- end
587
- end
588
346
  end
589
347
 
590
348
  class << self
@@ -595,7 +353,6 @@ module Sass::Script
595
353
  alias_method :callable?, :public_method_defined?
596
354
 
597
355
  private
598
-
599
356
  def include(*args)
600
357
  r = super
601
358
  # We have to re-include ourselves into EvaluationContext to work around
@@ -605,58 +362,48 @@ module Sass::Script
605
362
  end
606
363
  end
607
364
 
608
- # Creates a {Sass::Script::Value::Color Color} object from red, green, and
609
- # blue values.
365
+ # Creates a {Color} object from red, green, and blue values.
610
366
  #
611
367
  # @see #rgba
612
368
  # @overload rgb($red, $green, $blue)
613
- # @param $red [Sass::Script::Value::Number] The amount of red in the color.
614
- # Must be between 0 and 255 inclusive, or between `0%` and `100%`
615
- # inclusive
616
- # @param $green [Sass::Script::Value::Number] The amount of green in the
617
- # color. Must be between 0 and 255 inclusive, or between `0%` and `100%`
618
- # inclusive
619
- # @param $blue [Sass::Script::Value::Number] The amount of blue in the
620
- # color. Must be between 0 and 255 inclusive, or between `0%` and `100%`
621
- # inclusive
622
- # @return [Sass::Script::Value::Color]
369
+ # @param $red [Number] The amount of red in the color. Must be between 0 and
370
+ # 255 inclusive, or between `0%` and `100%` inclusive
371
+ # @param $green [Number] The amount of green in the color. Must be between 0
372
+ # and 255 inclusive, or between `0%` and `100%` inclusive
373
+ # @param $blue [Number] The amount of blue in the color. Must be between 0
374
+ # and 255 inclusive, or between `0%` and `100%` inclusive
375
+ # @return [Color]
623
376
  # @raise [ArgumentError] if any parameter is the wrong type or out of bounds
624
377
  def rgb(red, green, blue)
625
378
  assert_type red, :Number, :red
626
379
  assert_type green, :Number, :green
627
380
  assert_type blue, :Number, :blue
628
381
 
629
- color_attrs = [[red, :red], [green, :green], [blue, :blue]].map do |(c, name)|
630
- if c.is_unit?("%")
631
- c.value * 255 / 100.0
632
- elsif c.unitless?
633
- c.value
634
- else
635
- raise ArgumentError.new("Expected #{c} to be unitless or have a unit of % but got #{c}")
636
- end
637
- end
638
-
639
- # Don't store the string representation for function-created colors, both
640
- # because it's not very useful and because some functions aren't supported
641
- # on older browsers.
642
- Sass::Script::Value::Color.new(color_attrs)
382
+ Color.new([[red, :red], [green, :green], [blue, :blue]].map do |(c, name)|
383
+ v = c.value
384
+ if c.numerator_units == ["%"] && c.denominator_units.empty?
385
+ v = Sass::Util.check_range("$#{name}: Color value", 0..100, c, '%')
386
+ v * 255 / 100.0
387
+ else
388
+ Sass::Util.check_range("$#{name}: Color value", 0..255, c)
389
+ end
390
+ end)
643
391
  end
644
392
  declare :rgb, [:red, :green, :blue]
645
393
 
646
- # Creates a {Sass::Script::Value::Color Color} from red, green, blue, and
647
- # alpha values.
394
+ # Creates a {Color} from red, green, blue, and alpha values.
648
395
  # @see #rgb
649
396
  #
650
397
  # @overload rgba($red, $green, $blue, $alpha)
651
- # @param $red [Sass::Script::Value::Number] The amount of red in the
652
- # color. Must be between 0 and 255 inclusive
653
- # @param $green [Sass::Script::Value::Number] The amount of green in the
654
- # color. Must be between 0 and 255 inclusive
655
- # @param $blue [Sass::Script::Value::Number] The amount of blue in the
656
- # color. Must be between 0 and 255 inclusive
657
- # @param $alpha [Sass::Script::Value::Number] The opacity of the color.
658
- # Must be between 0 and 1 inclusive
659
- # @return [Sass::Script::Value::Color]
398
+ # @param $red [Number] The amount of red in the color. Must be between 0
399
+ # and 255 inclusive
400
+ # @param $green [Number] The amount of green in the color. Must be between
401
+ # 0 and 255 inclusive
402
+ # @param $blue [Number] The amount of blue in the color. Must be between 0
403
+ # and 255 inclusive
404
+ # @param $alpha [Number] The opacity of the color. Must be between 0 and 1
405
+ # inclusive
406
+ # @return [Color]
660
407
  # @raise [ArgumentError] if any parameter is the wrong type or out of
661
408
  # bounds
662
409
  #
@@ -667,11 +414,10 @@ module Sass::Script
667
414
  # rgba(#102030, 0.5) => rgba(16, 32, 48, 0.5)
668
415
  # rgba(blue, 0.2) => rgba(0, 0, 255, 0.2)
669
416
  #
670
- # @param $color [Sass::Script::Value::Color] The color whose opacity will
671
- # be changed.
672
- # @param $alpha [Sass::Script::Value::Number] The new opacity of the
673
- # color. Must be between 0 and 1 inclusive
674
- # @return [Sass::Script::Value::Color]
417
+ # @param $color [Color] The color whose opacity will be changed.
418
+ # @param $alpha [Number] The new opacity of the color. Must be between 0
419
+ # and 1 inclusive
420
+ # @return [Color]
675
421
  # @raise [ArgumentError] if `$alpha` is out of bounds or either parameter
676
422
  # is the wrong type
677
423
  def rgba(*args)
@@ -682,6 +428,7 @@ module Sass::Script
682
428
  assert_type color, :Color, :color
683
429
  assert_type alpha, :Number, :alpha
684
430
 
431
+ Sass::Util.check_range('Alpha channel', 0..1, alpha)
685
432
  color.with(:alpha => alpha.value)
686
433
  when 4
687
434
  red, green, blue, alpha = args
@@ -693,44 +440,43 @@ module Sass::Script
693
440
  declare :rgba, [:red, :green, :blue, :alpha]
694
441
  declare :rgba, [:color, :alpha]
695
442
 
696
- # Creates a {Sass::Script::Value::Color Color} from hue, saturation, and
697
- # lightness values. Uses the algorithm from the [CSS3 spec][].
443
+ # Creates a {Color} from hue, saturation, and lightness values. Uses the
444
+ # algorithm from the [CSS3 spec][].
698
445
  #
699
446
  # [CSS3 spec]: http://www.w3.org/TR/css3-color/#hsl-color
700
447
  #
701
448
  # @see #hsla
702
449
  # @overload hsl($hue, $saturation, $lightness)
703
- # @param $hue [Sass::Script::Value::Number] The hue of the color. Should be
704
- # between 0 and 360 degrees, inclusive
705
- # @param $saturation [Sass::Script::Value::Number] The saturation of the
706
- # color. Must be between `0%` and `100%`, inclusive
707
- # @param $lightness [Sass::Script::Value::Number] The lightness of the
708
- # color. Must be between `0%` and `100%`, inclusive
709
- # @return [Sass::Script::Value::Color]
450
+ # @param $hue [Number] The hue of the color. Should be between 0 and 360
451
+ # degrees, inclusive
452
+ # @param $saturation [Number] The saturation of the color. Must be between
453
+ # `0%` and `100%`, inclusive
454
+ # @param $lightness [Number] The lightness of the color. Must be between
455
+ # `0%` and `100%`, inclusive
456
+ # @return [Color]
710
457
  # @raise [ArgumentError] if `$saturation` or `$lightness` are out of bounds
711
458
  # or any parameter is the wrong type
712
459
  def hsl(hue, saturation, lightness)
713
- hsla(hue, saturation, lightness, number(1))
460
+ hsla(hue, saturation, lightness, Number.new(1))
714
461
  end
715
462
  declare :hsl, [:hue, :saturation, :lightness]
716
463
 
717
- # Creates a {Sass::Script::Value::Color Color} from hue,
718
- # saturation, lightness, and alpha values. Uses the algorithm from
719
- # the [CSS3 spec][].
464
+ # Creates a {Color} from hue, saturation, lightness, and alpha
465
+ # values. Uses the algorithm from the [CSS3 spec][].
720
466
  #
721
467
  # [CSS3 spec]: http://www.w3.org/TR/css3-color/#hsl-color
722
468
  #
723
469
  # @see #hsl
724
470
  # @overload hsla($hue, $saturation, $lightness, $alpha)
725
- # @param $hue [Sass::Script::Value::Number] The hue of the color. Should be
726
- # between 0 and 360 degrees, inclusive
727
- # @param $saturation [Sass::Script::Value::Number] The saturation of the
728
- # color. Must be between `0%` and `100%`, inclusive
729
- # @param $lightness [Sass::Script::Value::Number] The lightness of the
730
- # color. Must be between `0%` and `100%`, inclusive
731
- # @param $alpha [Sass::Script::Value::Number] The opacity of the color. Must
732
- # be between 0 and 1, inclusive
733
- # @return [Sass::Script::Value::Color]
471
+ # @param $hue [Number] The hue of the color. Should be between 0 and 360
472
+ # degrees, inclusive
473
+ # @param $saturation [Number] The saturation of the color. Must be between
474
+ # `0%` and `100%`, inclusive
475
+ # @param $lightness [Number] The lightness of the color. Must be between
476
+ # `0%` and `100%`, inclusive
477
+ # @param $alpha [Number] The opacity of the color. Must be between 0 and 1,
478
+ # inclusive
479
+ # @return [Color]
734
480
  # @raise [ArgumentError] if `$saturation`, `$lightness`, or `$alpha` are out
735
481
  # of bounds or any parameter is the wrong type
736
482
  def hsla(hue, saturation, lightness, alpha)
@@ -739,15 +485,13 @@ module Sass::Script
739
485
  assert_type lightness, :Number, :lightness
740
486
  assert_type alpha, :Number, :alpha
741
487
 
488
+ Sass::Util.check_range('Alpha channel', 0..1, alpha)
489
+
742
490
  h = hue.value
743
- s = saturation.value
744
- l = lightness.value
745
-
746
- # Don't store the string representation for function-created colors, both
747
- # because it's not very useful and because some functions aren't supported
748
- # on older browsers.
749
- Sass::Script::Value::Color.new(
750
- :hue => h, :saturation => s, :lightness => l, :alpha => alpha.value)
491
+ s = Sass::Util.check_range('Saturation', 0..100, saturation, '%')
492
+ l = Sass::Util.check_range('Lightness', 0..100, lightness, '%')
493
+
494
+ Color.new(:hue => h, :saturation => s, :lightness => l, :alpha => alpha.value)
751
495
  end
752
496
  declare :hsla, [:hue, :saturation, :lightness, :alpha]
753
497
 
@@ -757,13 +501,12 @@ module Sass::Script
757
501
  # [hsl-to-rgb]: http://www.w3.org/TR/css3-color/#hsl-color
758
502
  #
759
503
  # @overload red($color)
760
- # @param $color [Sass::Script::Value::Color]
761
- # @return [Sass::Script::Value::Number] The red component, between 0 and 255
762
- # inclusive
504
+ # @param $color [Color]
505
+ # @return [Number] The red component, between 0 and 255 inclusive
763
506
  # @raise [ArgumentError] if `$color` isn't a color
764
507
  def red(color)
765
508
  assert_type color, :Color, :color
766
- number(color.red)
509
+ Sass::Script::Number.new(color.red)
767
510
  end
768
511
  declare :red, [:color]
769
512
 
@@ -773,13 +516,12 @@ module Sass::Script
773
516
  # [hsl-to-rgb]: http://www.w3.org/TR/css3-color/#hsl-color
774
517
  #
775
518
  # @overload green($color)
776
- # @param $color [Sass::Script::Value::Color]
777
- # @return [Sass::Script::Value::Number] The green component, between 0 and
778
- # 255 inclusive
519
+ # @param $color [Color]
520
+ # @return [Number] The green component, between 0 and 255 inclusive
779
521
  # @raise [ArgumentError] if `$color` isn't a color
780
522
  def green(color)
781
523
  assert_type color, :Color, :color
782
- number(color.green)
524
+ Sass::Script::Number.new(color.green)
783
525
  end
784
526
  declare :green, [:color]
785
527
 
@@ -789,13 +531,12 @@ module Sass::Script
789
531
  # [hsl-to-rgb]: http://www.w3.org/TR/css3-color/#hsl-color
790
532
  #
791
533
  # @overload blue($color)
792
- # @param $color [Sass::Script::Value::Color]
793
- # @return [Sass::Script::Value::Number] The blue component, between 0 and
794
- # 255 inclusive
534
+ # @param $color [Color]
535
+ # @return [Number] The blue component, between 0 and 255 inclusive
795
536
  # @raise [ArgumentError] if `$color` isn't a color
796
537
  def blue(color)
797
538
  assert_type color, :Color, :color
798
- number(color.blue)
539
+ Sass::Script::Number.new(color.blue)
799
540
  end
800
541
  declare :blue, [:color]
801
542
 
@@ -807,13 +548,12 @@ module Sass::Script
807
548
  # [rgb-to-hsl]: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
808
549
  #
809
550
  # @overload hue($color)
810
- # @param $color [Sass::Script::Value::Color]
811
- # @return [Sass::Script::Value::Number] The hue component, between 0deg and
812
- # 360deg
551
+ # @param $color [Color]
552
+ # @return [Number] The hue component, between 0deg and 360deg
813
553
  # @raise [ArgumentError] if `$color` isn't a color
814
554
  def hue(color)
815
555
  assert_type color, :Color, :color
816
- number(color.hue, "deg")
556
+ Sass::Script::Number.new(color.hue, ["deg"])
817
557
  end
818
558
  declare :hue, [:color]
819
559
 
@@ -825,13 +565,12 @@ module Sass::Script
825
565
  # [rgb-to-hsl]: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
826
566
  #
827
567
  # @overload saturation($color)
828
- # @param $color [Sass::Script::Value::Color]
829
- # @return [Sass::Script::Value::Number] The saturation component, between 0%
830
- # and 100%
568
+ # @param $color [Color]
569
+ # @return [Number] The saturation component, between 0% and 100%
831
570
  # @raise [ArgumentError] if `$color` isn't a color
832
571
  def saturation(color)
833
572
  assert_type color, :Color, :color
834
- number(color.saturation, "%")
573
+ Sass::Script::Number.new(color.saturation, ["%"])
835
574
  end
836
575
  declare :saturation, [:color]
837
576
 
@@ -843,13 +582,12 @@ module Sass::Script
843
582
  # [rgb-to-hsl]: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
844
583
  #
845
584
  # @overload lightness($color)
846
- # @param $color [Sass::Script::Value::Color]
847
- # @return [Sass::Script::Value::Number] The lightness component, between 0%
848
- # and 100%
585
+ # @param $color [Color]
586
+ # @return [Number] The lightness component, between 0% and 100%
849
587
  # @raise [ArgumentError] if `$color` isn't a color
850
588
  def lightness(color)
851
589
  assert_type color, :Color, :color
852
- number(color.lightness, "%")
590
+ Sass::Script::Number.new(color.lightness, ["%"])
853
591
  end
854
592
  declare :lightness, [:color]
855
593
 
@@ -860,22 +598,22 @@ module Sass::Script
860
598
  # syntax as a special case.
861
599
  #
862
600
  # @overload alpha($color)
863
- # @param $color [Sass::Script::Value::Color]
864
- # @return [Sass::Script::Value::Number] The alpha component, between 0 and 1
601
+ # @param $color [Color]
602
+ # @return [Number] The alpha component, between 0 and 1
865
603
  # @raise [ArgumentError] if `$color` isn't a color
866
604
  def alpha(*args)
867
605
  if args.all? do |a|
868
- a.is_a?(Sass::Script::Value::String) && a.type == :identifier &&
869
- a.value =~ /^[a-zA-Z]+\s*=/
870
- end
606
+ a.is_a?(Sass::Script::String) && a.type == :identifier &&
607
+ a.value =~ /^[a-zA-Z]+\s*=/
608
+ end
871
609
  # Support the proprietary MS alpha() function
872
- return identifier("alpha(#{args.map {|a| a.to_s}.join(", ")})")
610
+ return Sass::Script::String.new("alpha(#{args.map {|a| a.to_s}.join(", ")})")
873
611
  end
874
612
 
875
613
  raise ArgumentError.new("wrong number of arguments (#{args.size} for 1)") if args.size != 1
876
614
 
877
615
  assert_type args.first, :Color, :color
878
- number(args.first.alpha)
616
+ Sass::Script::Number.new(args.first.alpha)
879
617
  end
880
618
  declare :alpha, [:color]
881
619
 
@@ -883,15 +621,13 @@ module Sass::Script
883
621
  # otherwise specified.
884
622
  #
885
623
  # @overload opacity($color)
886
- # @param $color [Sass::Script::Value::Color]
887
- # @return [Sass::Script::Value::Number] The alpha component, between 0 and 1
624
+ # @param $color [Color]
625
+ # @return [Number] The alpha component, between 0 and 1
888
626
  # @raise [ArgumentError] if `$color` isn't a color
889
627
  def opacity(color)
890
- if color.is_a?(Sass::Script::Value::Number)
891
- return identifier("opacity(#{color})")
892
- end
628
+ return Sass::Script::String.new("opacity(#{color})") if color.is_a?(Sass::Script::Number)
893
629
  assert_type color, :Color, :color
894
- number(color.alpha)
630
+ Sass::Script::Number.new(color.alpha)
895
631
  end
896
632
  declare :opacity, [:color]
897
633
 
@@ -903,10 +639,10 @@ module Sass::Script
903
639
  # opacify(rgba(0, 0, 0, 0.5), 0.1) => rgba(0, 0, 0, 0.6)
904
640
  # opacify(rgba(0, 0, 17, 0.8), 0.2) => #001
905
641
  # @overload opacify($color, $amount)
906
- # @param $color [Sass::Script::Value::Color]
907
- # @param $amount [Sass::Script::Value::Number] The amount to increase the
908
- # opacity by, between 0 and 1
909
- # @return [Sass::Script::Value::Color]
642
+ # @param $color [Color]
643
+ # @param $amount [Number] The amount to increase the opacity by, between 0
644
+ # and 1
645
+ # @return [Color]
910
646
  # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
911
647
  # is the wrong type
912
648
  def opacify(color, amount)
@@ -925,10 +661,10 @@ module Sass::Script
925
661
  # transparentize(rgba(0, 0, 0, 0.5), 0.1) => rgba(0, 0, 0, 0.4)
926
662
  # transparentize(rgba(0, 0, 0, 0.8), 0.2) => rgba(0, 0, 0, 0.6)
927
663
  # @overload transparentize($color, $amount)
928
- # @param $color [Sass::Script::Value::Color]
929
- # @param $amount [Sass::Script::Value::Number] The amount to decrease the
930
- # opacity by, between 0 and 1
931
- # @return [Sass::Script::Value::Color]
664
+ # @param $color [Color]
665
+ # @param $amount [Number] The amount to decrease the opacity by, between 0
666
+ # and 1
667
+ # @return [Color]
932
668
  # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
933
669
  # is the wrong type
934
670
  def transparentize(color, amount)
@@ -947,10 +683,10 @@ module Sass::Script
947
683
  # lighten(hsl(0, 0%, 0%), 30%) => hsl(0, 0, 30)
948
684
  # lighten(#800, 20%) => #e00
949
685
  # @overload lighten($color, $amount)
950
- # @param $color [Sass::Script::Value::Color]
951
- # @param $amount [Sass::Script::Value::Number] The amount to increase the
952
- # lightness by, between `0%` and `100%`
953
- # @return [Sass::Script::Value::Color]
686
+ # @param $color [Color]
687
+ # @param $amount [Number] The amount to increase the lightness by, between
688
+ # `0%` and `100%`
689
+ # @return [Color]
954
690
  # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
955
691
  # is the wrong type
956
692
  def lighten(color, amount)
@@ -966,10 +702,10 @@ module Sass::Script
966
702
  # darken(hsl(25, 100%, 80%), 30%) => hsl(25, 100%, 50%)
967
703
  # darken(#800, 20%) => #200
968
704
  # @overload darken($color, $amount)
969
- # @param $color [Sass::Script::Value::Color]
970
- # @param $amount [Sass::Script::Value::Number] The amount to decrease the
971
- # lightness by, between `0%` and `100%`
972
- # @return [Sass::Script::Value::Color]
705
+ # @param $color [Color]
706
+ # @param $amount [Number] The amount to dencrease the lightness by, between
707
+ # `0%` and `100%`
708
+ # @return [Color]
973
709
  # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
974
710
  # is the wrong type
975
711
  def darken(color, amount)
@@ -985,16 +721,16 @@ module Sass::Script
985
721
  # saturate(hsl(120, 30%, 90%), 20%) => hsl(120, 50%, 90%)
986
722
  # saturate(#855, 20%) => #9e3f3f
987
723
  # @overload saturate($color, $amount)
988
- # @param $color [Sass::Script::Value::Color]
989
- # @param $amount [Sass::Script::Value::Number] The amount to increase the
990
- # saturation by, between `0%` and `100%`
991
- # @return [Sass::Script::Value::Color]
724
+ # @param $color [Color]
725
+ # @param $amount [Number] The amount to increase the saturation by, between
726
+ # `0%` and `100%`
727
+ # @return [Color]
992
728
  # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
993
729
  # is the wrong type
994
730
  def saturate(color, amount = nil)
995
731
  # Support the filter effects definition of saturate.
996
732
  # https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html
997
- return identifier("saturate(#{color})") if amount.nil?
733
+ return Sass::Script::String.new("saturate(#{color})") if amount.nil?
998
734
  _adjust(color, amount, :saturation, 0..100, :+, "%")
999
735
  end
1000
736
  declare :saturate, [:color, :amount]
@@ -1008,10 +744,10 @@ module Sass::Script
1008
744
  # desaturate(hsl(120, 30%, 90%), 20%) => hsl(120, 10%, 90%)
1009
745
  # desaturate(#855, 20%) => #726b6b
1010
746
  # @overload desaturate($color, $amount)
1011
- # @param $color [Sass::Script::Value::Color]
1012
- # @param $amount [Sass::Script::Value::Number] The amount to decrease the
1013
- # saturation by, between `0%` and `100%`
1014
- # @return [Sass::Script::Value::Color]
747
+ # @param $color [Color]
748
+ # @param $amount [Number] The amount to decrease the saturation by, between
749
+ # `0%` and `100%`
750
+ # @return [Color]
1015
751
  # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
1016
752
  # is the wrong type
1017
753
  def desaturate(color, amount)
@@ -1025,13 +761,12 @@ module Sass::Script
1025
761
  #
1026
762
  # @example
1027
763
  # adjust-hue(hsl(120, 30%, 90%), 60deg) => hsl(180, 30%, 90%)
1028
- # adjust-hue(hsl(120, 30%, 90%), -60deg) => hsl(60, 30%, 90%)
764
+ # adjust-hue(hsl(120, 30%, 90%), 060deg) => hsl(60, 30%, 90%)
1029
765
  # adjust-hue(#811, 45deg) => #886a11
1030
766
  # @overload adjust_hue($color, $degrees)
1031
- # @param $color [Sass::Script::Value::Color]
1032
- # @param $degrees [Sass::Script::Value::Number] The number of degrees to
1033
- # rotate the hue
1034
- # @return [Sass::Script::Value::Color]
767
+ # @param $color [Color]
768
+ # @param $degrees [Number] The number of degrees to rotate the hue
769
+ # @return [Color]
1035
770
  # @raise [ArgumentError] if either parameter is the wrong type
1036
771
  def adjust_hue(color, degrees)
1037
772
  assert_type color, :Color, :color
@@ -1047,14 +782,13 @@ module Sass::Script
1047
782
  # ie-hex-str(#3322BB) => #FF3322BB
1048
783
  # ie-hex-str(rgba(0, 255, 0, 0.5)) => #8000FF00
1049
784
  # @overload ie_hex_str($color)
1050
- # @param $color [Sass::Script::Value::Color]
1051
- # @return [Sass::Script::Value::String] The IE-formatted string
1052
- # representation of the color
785
+ # @param $color [Color]
786
+ # @return [String] The IE-formatted string representation of the color
1053
787
  # @raise [ArgumentError] if `$color` isn't a color
1054
788
  def ie_hex_str(color)
1055
789
  assert_type color, :Color, :color
1056
790
  alpha = (color.alpha * 255).round.to_s(16).rjust(2, '0')
1057
- identifier("##{alpha}#{color.send(:hex_str)[1..-1]}".upcase)
791
+ Sass::Script::String.new("##{alpha}#{color.send(:hex_str)[1..-1]}".upcase)
1058
792
  end
1059
793
  declare :ie_hex_str, [:color]
1060
794
 
@@ -1071,33 +805,29 @@ module Sass::Script
1071
805
  # adjust-color(#102030, $blue: 5) => #102035
1072
806
  # adjust-color(#102030, $red: -5, $blue: 5) => #0b2035
1073
807
  # adjust-color(hsl(25, 100%, 80%), $lightness: -30%, $alpha: -0.4) => hsla(25, 100%, 50%, 0.6)
1074
- # @comment
1075
- # rubocop:disable LineLength
1076
808
  # @overload adjust_color($color, [$red], [$green], [$blue], [$hue], [$saturation], [$lightness], [$alpha])
1077
- # @comment
1078
- # rubocop:disable LineLength
1079
- # @param $color [Sass::Script::Value::Color]
1080
- # @param $red [Sass::Script::Value::Number] The adjustment to make on the
1081
- # red component, between -255 and 255 inclusive
1082
- # @param $green [Sass::Script::Value::Number] The adjustment to make on the
1083
- # green component, between -255 and 255 inclusive
1084
- # @param $blue [Sass::Script::Value::Number] The adjustment to make on the
1085
- # blue component, between -255 and 255 inclusive
1086
- # @param $hue [Sass::Script::Value::Number] The adjustment to make on the
1087
- # hue component, in degrees
1088
- # @param $saturation [Sass::Script::Value::Number] The adjustment to make on
1089
- # the saturation component, between `-100%` and `100%` inclusive
1090
- # @param $lightness [Sass::Script::Value::Number] The adjustment to make on
1091
- # the lightness component, between `-100%` and `100%` inclusive
1092
- # @param $alpha [Sass::Script::Value::Number] The adjustment to make on the
1093
- # alpha component, between -1 and 1 inclusive
1094
- # @return [Sass::Script::Value::Color]
809
+ # @param $color [Color]
810
+ # @param $red [Number] The adjustment to make on the red component, between
811
+ # -255 and 255 inclusive
812
+ # @param $green [Number] The adjustment to make on the green component,
813
+ # between -255 and 255 inclusive
814
+ # @param $blue [Number] The adjustment to make on the blue component, between
815
+ # -255 and 255 inclusive
816
+ # @param $hue [Number] The adjustment to make on the hue component, in
817
+ # degrees
818
+ # @param $saturation [Number] The adjustment to make on the saturation
819
+ # component, between `-100%` and `100%` inclusive
820
+ # @param $lightness [Number] The adjustment to make on the lightness
821
+ # component, between `-100%` and `100%` inclusive
822
+ # @param $alpha [Number] The adjustment to make on the alpha component,
823
+ # between -1 and 1 inclusive
824
+ # @return [Color]
1095
825
  # @raise [ArgumentError] if any parameter is the wrong type or out-of
1096
826
  # bounds, or if RGB properties and HSL properties are adjusted at the
1097
827
  # same time
1098
828
  def adjust_color(color, kwargs)
1099
829
  assert_type color, :Color, :color
1100
- with = Sass::Util.map_hash(
830
+ with = Sass::Util.map_hash({
1101
831
  "red" => [-255..255, ""],
1102
832
  "green" => [-255..255, ""],
1103
833
  "blue" => [-255..255, ""],
@@ -1105,10 +835,9 @@ module Sass::Script
1105
835
  "saturation" => [-100..100, "%"],
1106
836
  "lightness" => [-100..100, "%"],
1107
837
  "alpha" => [-1..1, ""]
1108
- ) do |name, (range, units)|
838
+ }) do |name, (range, units)|
1109
839
 
1110
- val = kwargs.delete(name)
1111
- next unless val
840
+ next unless val = kwargs.delete(name)
1112
841
  assert_type val, :Number, name
1113
842
  Sass::Util.check_range("$#{name}: Amount", range, val, units) if range
1114
843
  adjusted = color.send(name) + val.value
@@ -1152,43 +881,41 @@ module Sass::Script
1152
881
  # scale-color(hsl(120, 70%, 80%), $lightness: 50%) => hsl(120, 70%, 90%)
1153
882
  # scale-color(rgb(200, 150%, 170%), $green: -40%, $blue: 70%) => rgb(200, 90, 229)
1154
883
  # scale-color(hsl(200, 70%, 80%), $saturation: -90%, $alpha: -30%) => hsla(200, 7%, 80%, 0.7)
1155
- # @comment
1156
- # rubocop:disable LineLength
1157
884
  # @overload scale_color($color, [$red], [$green], [$blue], [$saturation], [$lightness], [$alpha])
1158
- # @comment
1159
- # rubocop:disable LineLength
1160
- # @param $color [Sass::Script::Value::Color]
1161
- # @param $red [Sass::Script::Value::Number]
1162
- # @param $green [Sass::Script::Value::Number]
1163
- # @param $blue [Sass::Script::Value::Number]
1164
- # @param $saturation [Sass::Script::Value::Number]
1165
- # @param $lightness [Sass::Script::Value::Number]
1166
- # @param $alpha [Sass::Script::Value::Number]
1167
- # @return [Sass::Script::Value::Color]
885
+ # @param $color [Color]
886
+ # @param $red [Number]
887
+ # @param $green [Number]
888
+ # @param $blue [Number]
889
+ # @param $saturation [Number]
890
+ # @param $lightness [Number]
891
+ # @param $alpha [Number]
892
+ # @return [Color]
1168
893
  # @raise [ArgumentError] if any parameter is the wrong type or out-of
1169
894
  # bounds, or if RGB properties and HSL properties are adjusted at the
1170
895
  # same time
1171
896
  def scale_color(color, kwargs)
1172
897
  assert_type color, :Color, :color
1173
- with = Sass::Util.map_hash(
898
+ with = Sass::Util.map_hash({
1174
899
  "red" => 255,
1175
900
  "green" => 255,
1176
901
  "blue" => 255,
1177
902
  "saturation" => 100,
1178
903
  "lightness" => 100,
1179
904
  "alpha" => 1
1180
- ) do |name, max|
905
+ }) do |name, max|
1181
906
 
1182
- val = kwargs.delete(name)
1183
- next unless val
907
+ next unless val = kwargs.delete(name)
1184
908
  assert_type val, :Number, name
1185
- assert_unit val, '%', name
1186
- Sass::Util.check_range("$#{name}: Amount", -100..100, val, '%')
909
+ if !(val.numerator_units == ['%'] && val.denominator_units.empty?)
910
+ raise ArgumentError.new("$#{name}: Amount #{val} must be a % (e.g. #{val.value}%)")
911
+ else
912
+ Sass::Util.check_range("$#{name}: Amount", -100..100, val, '%')
913
+ end
1187
914
 
1188
915
  current = color.send(name)
1189
- scale = val.value / 100.0
916
+ scale = val.value/100.0
1190
917
  diff = scale > 0 ? max - current : current
1191
- [name.to_sym, current + diff * scale]
918
+ [name.to_sym, current + diff*scale]
1192
919
  end
1193
920
 
1194
921
  unless kwargs.empty?
@@ -1213,52 +940,31 @@ module Sass::Script
1213
940
  # change-color(#102030, $blue: 5) => #102005
1214
941
  # change-color(#102030, $red: 120, $blue: 5) => #782005
1215
942
  # change-color(hsl(25, 100%, 80%), $lightness: 40%, $alpha: 0.8) => hsla(25, 100%, 40%, 0.8)
1216
- # @comment
1217
- # rubocop:disable LineLength
1218
943
  # @overload change_color($color, [$red], [$green], [$blue], [$hue], [$saturation], [$lightness], [$alpha])
1219
- # @comment
1220
- # rubocop:disable LineLength
1221
- # @param $color [Sass::Script::Value::Color]
1222
- # @param $red [Sass::Script::Value::Number] The new red component for the
1223
- # color, within 0 and 255 inclusive
1224
- # @param $green [Sass::Script::Value::Number] The new green component for
1225
- # the color, within 0 and 255 inclusive
1226
- # @param $blue [Sass::Script::Value::Number] The new blue component for the
1227
- # color, within 0 and 255 inclusive
1228
- # @param $hue [Sass::Script::Value::Number] The new hue component for the
1229
- # color, in degrees
1230
- # @param $saturation [Sass::Script::Value::Number] The new saturation
1231
- # component for the color, between `0%` and `100%` inclusive
1232
- # @param $lightness [Sass::Script::Value::Number] The new lightness
1233
- # component for the color, within `0%` and `100%` inclusive
1234
- # @param $alpha [Sass::Script::Value::Number] The new alpha component for
1235
- # the color, within 0 and 1 inclusive
1236
- # @return [Sass::Script::Value::Color]
944
+ # @param $color [Color]
945
+ # @param $red [Number] The new red component for the color, within 0 and 255
946
+ # inclusive
947
+ # @param $green [Number] The new green component for the color, within 0 and
948
+ # 255 inclusive
949
+ # @param $blue [Number] The new blue component for the color, within 0 and
950
+ # 255 inclusive
951
+ # @param $hue [Number] The new hue component for the color, in degrees
952
+ # @param $saturation [Number] The new saturation component for the color,
953
+ # between `0%` and `100%` inclusive
954
+ # @param $lightness [Number] The new lightness component for the color,
955
+ # within `0%` and `100%` inclusive
956
+ # @param $alpha [Number] The new alpha component for the color, within 0 and
957
+ # 1 inclusive
958
+ # @return [Color]
1237
959
  # @raise [ArgumentError] if any parameter is the wrong type or out-of
1238
960
  # bounds, or if RGB properties and HSL properties are adjusted at the
1239
961
  # same time
1240
962
  def change_color(color, kwargs)
1241
963
  assert_type color, :Color, :color
1242
- with = Sass::Util.map_hash(
1243
- 'red' => ['Red value', 0..255],
1244
- 'green' => ['Green value', 0..255],
1245
- 'blue' => ['Blue value', 0..255],
1246
- 'hue' => [],
1247
- 'saturation' => ['Saturation', 0..100, '%'],
1248
- 'lightness' => ['Lightness', 0..100, '%'],
1249
- 'alpha' => ['Alpha channel', 0..1]
1250
- ) do |name, (desc, range, unit)|
1251
- val = kwargs.delete(name)
1252
- next unless val
964
+ with = Sass::Util.map_hash(%w[red green blue hue saturation lightness alpha]) do |name, max|
965
+ next unless val = kwargs.delete(name)
1253
966
  assert_type val, :Number, name
1254
-
1255
- if range
1256
- val = Sass::Util.check_range(desc, range, val, unit)
1257
- else
1258
- val = val.value
1259
- end
1260
-
1261
- [name.to_sym, val]
967
+ [name.to_sym, val.value]
1262
968
  end
1263
969
 
1264
970
  unless kwargs.empty?
@@ -1283,18 +989,18 @@ module Sass::Script
1283
989
  # mix(#f00, #00f) => #7f007f
1284
990
  # mix(#f00, #00f, 25%) => #3f00bf
1285
991
  # mix(rgba(255, 0, 0, 0.5), #00f) => rgba(63, 0, 191, 0.75)
1286
- # @overload mix($color1, $color2, $weight: 50%)
1287
- # @param $color1 [Sass::Script::Value::Color]
1288
- # @param $color2 [Sass::Script::Value::Color]
1289
- # @param $weight [Sass::Script::Value::Number] The relative weight of each
1290
- # color. Closer to `0%` gives more weight to `$color`, closer to `100%`
1291
- # gives more weight to `$color2`
1292
- # @return [Sass::Script::Value::Color]
992
+ # @overload mix($color-1, $color-2, $weight: 50%)
993
+ # @param $color-1 [Color]
994
+ # @param $color-2 [Color]
995
+ # @param $weight [Number] The relative weight of each color. Closer to `0%`
996
+ # gives more weight to `$color`, closer to `100%` gives more weight to
997
+ # `$color2`
998
+ # @return [Color]
1293
999
  # @raise [ArgumentError] if `$weight` is out of bounds or any parameter is
1294
1000
  # the wrong type
1295
- def mix(color1, color2, weight = number(50))
1296
- assert_type color1, :Color, :color1
1297
- assert_type color2, :Color, :color2
1001
+ def mix(color_1, color_2, weight = Number.new(50))
1002
+ assert_type color_1, :Color, :color_1
1003
+ assert_type color_2, :Color, :color_2
1298
1004
  assert_type weight, :Number, :weight
1299
1005
 
1300
1006
  Sass::Util.check_range("Weight", 0..100, weight, '%')
@@ -1304,11 +1010,11 @@ module Sass::Script
1304
1010
  # to perform the weighted average of the two RGB values.
1305
1011
  #
1306
1012
  # It works by first normalizing both parameters to be within [-1, 1],
1307
- # where 1 indicates "only use color1", -1 indicates "only use color2", and
1013
+ # where 1 indicates "only use color_1", -1 indicates "only use color_2", and
1308
1014
  # all values in between indicated a proportionately weighted average.
1309
1015
  #
1310
1016
  # Once we have the normalized variables w and a, we apply the formula
1311
- # (w + a)/(1 + w*a) to get the combined weight (in [-1, 1]) of color1.
1017
+ # (w + a)/(1 + w*a) to get the combined weight (in [-1, 1]) of color_1.
1312
1018
  # This formula has two especially nice properties:
1313
1019
  #
1314
1020
  # * When either w or a are -1 or 1, the combined weight is also that number
@@ -1316,35 +1022,33 @@ module Sass::Script
1316
1022
  #
1317
1023
  # * When a is 0, the combined weight is w, and vice versa.
1318
1024
  #
1319
- # Finally, the weight of color1 is renormalized to be within [0, 1]
1320
- # and the weight of color2 is given by 1 minus the weight of color1.
1321
- p = (weight.value / 100.0).to_f
1322
- w = p * 2 - 1
1323
- a = color1.alpha - color2.alpha
1025
+ # Finally, the weight of color_1 is renormalized to be within [0, 1]
1026
+ # and the weight of color_2 is given by 1 minus the weight of color_1.
1027
+ p = (weight.value/100.0).to_f
1028
+ w = p*2 - 1
1029
+ a = color_1.alpha - color_2.alpha
1324
1030
 
1325
- w1 = ((w * a == -1 ? w : (w + a) / (1 + w * a)) + 1) / 2.0
1031
+ w1 = (((w * a == -1) ? w : (w + a)/(1 + w*a)) + 1)/2.0
1326
1032
  w2 = 1 - w1
1327
1033
 
1328
- rgba = color1.rgb.zip(color2.rgb).map {|v1, v2| v1 * w1 + v2 * w2}
1329
- rgba << color1.alpha * p + color2.alpha * (1 - p)
1330
- rgb_color(*rgba)
1034
+ rgb = color_1.rgb.zip(color_2.rgb).map {|v1, v2| v1*w1 + v2*w2}
1035
+ alpha = color_1.alpha*p + color_2.alpha*(1-p)
1036
+ Color.new(rgb + [alpha])
1331
1037
  end
1332
- declare :mix, [:color1, :color2]
1333
- declare :mix, [:color1, :color2, :weight]
1038
+ declare :mix, [:color_1, :color_2]
1039
+ declare :mix, [:color_1, :color_2, :weight]
1334
1040
 
1335
1041
  # Converts a color to grayscale. This is identical to `desaturate(color,
1336
1042
  # 100%)`.
1337
1043
  #
1338
1044
  # @see #desaturate
1339
1045
  # @overload grayscale($color)
1340
- # @param $color [Sass::Script::Value::Color]
1341
- # @return [Sass::Script::Value::Color]
1046
+ # @param $color [Color]
1047
+ # @return [Color]
1342
1048
  # @raise [ArgumentError] if `$color` isn't a color
1343
1049
  def grayscale(color)
1344
- if color.is_a?(Sass::Script::Value::Number)
1345
- return identifier("grayscale(#{color})")
1346
- end
1347
- desaturate color, number(100)
1050
+ return Sass::Script::String.new("grayscale(#{color})") if color.is_a?(Sass::Script::Number)
1051
+ desaturate color, Number.new(100)
1348
1052
  end
1349
1053
  declare :grayscale, [:color]
1350
1054
 
@@ -1353,11 +1057,11 @@ module Sass::Script
1353
1057
  #
1354
1058
  # @see #adjust_hue #adjust-hue
1355
1059
  # @overload complement($color)
1356
- # @param $color [Sass::Script::Value::Color]
1357
- # @return [Sass::Script::Value::Color]
1060
+ # @param $color [Color]
1061
+ # @return [Color]
1358
1062
  # @raise [ArgumentError] if `$color` isn't a color
1359
1063
  def complement(color)
1360
- adjust_hue color, number(180)
1064
+ adjust_hue color, Number.new(180)
1361
1065
  end
1362
1066
  declare :complement, [:color]
1363
1067
 
@@ -1365,13 +1069,11 @@ module Sass::Script
1365
1069
  # are inverted, while the opacity is left alone.
1366
1070
  #
1367
1071
  # @overload invert($color)
1368
- # @param $color [Sass::Script::Value::Color]
1369
- # @return [Sass::Script::Value::Color]
1072
+ # @param $color [Color]
1073
+ # @return [Color]
1370
1074
  # @raise [ArgumentError] if `$color` isn't a color
1371
1075
  def invert(color)
1372
- if color.is_a?(Sass::Script::Value::Number)
1373
- return identifier("invert(#{color})")
1374
- end
1076
+ return Sass::Script::String.new("invert(#{color})") if color.is_a?(Sass::Script::Number)
1375
1077
 
1376
1078
  assert_type color, :Color, :color
1377
1079
  color.with(
@@ -1389,12 +1091,12 @@ module Sass::Script
1389
1091
  # unquote("foo") => foo
1390
1092
  # unquote(foo) => foo
1391
1093
  # @overload unquote($string)
1392
- # @param $string [Sass::Script::Value::String]
1393
- # @return [Sass::Script::Value::String]
1094
+ # @param $string [String]
1095
+ # @return [String]
1394
1096
  # @raise [ArgumentError] if `$string` isn't a string
1395
1097
  def unquote(string)
1396
- if string.is_a?(Sass::Script::Value::String) && string.type != :identifier
1397
- identifier(string.value)
1098
+ if string.is_a?(Sass::Script::String)
1099
+ Sass::Script::String.new(string.value, :identifier)
1398
1100
  else
1399
1101
  string
1400
1102
  end
@@ -1409,165 +1111,15 @@ module Sass::Script
1409
1111
  # quote("foo") => "foo"
1410
1112
  # quote(foo) => "foo"
1411
1113
  # @overload quote($string)
1412
- # @param $string [Sass::Script::Value::String]
1413
- # @return [Sass::Script::Value::String]
1114
+ # @param $string [String]
1115
+ # @return [String]
1414
1116
  # @raise [ArgumentError] if `$string` isn't a string
1415
1117
  def quote(string)
1416
1118
  assert_type string, :String, :string
1417
- if string.type != :string
1418
- quoted_string(string.value)
1419
- else
1420
- string
1421
- end
1119
+ Sass::Script::String.new(string.value, :string)
1422
1120
  end
1423
1121
  declare :quote, [:string]
1424
1122
 
1425
- # Returns the number of characters in a string.
1426
- #
1427
- # @example
1428
- # str-length("foo") => 3
1429
- # @overload str_length($string)
1430
- # @param $string [Sass::Script::Value::String]
1431
- # @return [Sass::Script::Value::Number]
1432
- # @raise [ArgumentError] if `$string` isn't a string
1433
- def str_length(string)
1434
- assert_type string, :String, :string
1435
- number(string.value.size)
1436
- end
1437
- declare :str_length, [:string]
1438
-
1439
- # Inserts `$insert` into `$string` at `$index`.
1440
- #
1441
- # Note that unlike some languages, the first character in a Sass string is
1442
- # number 1, the second number 2, and so forth.
1443
- #
1444
- # @example
1445
- # str-insert("abcd", "X", 1) => "Xabcd"
1446
- # str-insert("abcd", "X", 4) => "abcXd"
1447
- # str-insert("abcd", "X", 5) => "abcdX"
1448
- #
1449
- # @overload str_insert($string, $insert, $index)
1450
- # @param $string [Sass::Script::Value::String]
1451
- # @param $insert [Sass::Script::Value::String]
1452
- # @param $index [Sass::Script::Value::Number] The position at which
1453
- # `$insert` will be inserted. Negative indices count from the end of
1454
- # `$string`. An index that's outside the bounds of the string will insert
1455
- # `$insert` at the front or back of the string
1456
- # @return [Sass::Script::Value::String] The result string. This will be
1457
- # quoted if and only if `$string` was quoted
1458
- # @raise [ArgumentError] if any parameter is the wrong type
1459
- def str_insert(original, insert, index)
1460
- assert_type original, :String, :string
1461
- assert_type insert, :String, :insert
1462
- assert_integer index, :index
1463
- assert_unit index, nil, :index
1464
- insertion_point = if index.value > 0
1465
- [index.value - 1, original.value.size].min
1466
- else
1467
- [index.value, -original.value.size - 1].max
1468
- end
1469
- result = original.value.dup.insert(insertion_point, insert.value)
1470
- Sass::Script::Value::String.new(result, original.type)
1471
- end
1472
- declare :str_insert, [:string, :insert, :index]
1473
-
1474
- # Returns the index of the first occurrence of `$substring` in `$string`. If
1475
- # there is no such occurrence, returns `null`.
1476
- #
1477
- # Note that unlike some languages, the first character in a Sass string is
1478
- # number 1, the second number 2, and so forth.
1479
- #
1480
- # @example
1481
- # str-index(abcd, a) => 1
1482
- # str-index(abcd, ab) => 1
1483
- # str-index(abcd, X) => null
1484
- # str-index(abcd, c) => 3
1485
- #
1486
- # @overload str_index($string, $substring)
1487
- # @param $string [Sass::Script::Value::String]
1488
- # @param $substring [Sass::Script::Value::String]
1489
- # @return [Sass::Script::Value::Number, Sass::Script::Value::Null]
1490
- # @raise [ArgumentError] if any parameter is the wrong type
1491
- def str_index(string, substring)
1492
- assert_type string, :String, :string
1493
- assert_type substring, :String, :substring
1494
- index = string.value.index(substring.value)
1495
- index ? number(index + 1) : null
1496
- end
1497
- declare :str_index, [:string, :substring]
1498
-
1499
- # Extracts a substring from `$string`. The substring will begin at index
1500
- # `$start-at` and ends at index `$end-at`.
1501
- #
1502
- # Note that unlike some languages, the first character in a Sass string is
1503
- # number 1, the second number 2, and so forth.
1504
- #
1505
- # @example
1506
- # str-slice("abcd", 2, 3) => "bc"
1507
- # str-slice("abcd", 2) => "bcd"
1508
- # str-slice("abcd", -3, -2) => "bc"
1509
- # str-slice("abcd", 2, -2) => "bc"
1510
- #
1511
- # @overload str_slice($string, $start-at, $end-at: -1)
1512
- # @param $start-at [Sass::Script::Value::Number] The index of the first
1513
- # character of the substring. If this is negative, it counts from the end
1514
- # of `$string`
1515
- # @param $end-before [Sass::Script::Value::Number] The index of the last
1516
- # character of the substring. If this is negative, it counts from the end
1517
- # of `$string`. Defaults to -1
1518
- # @return [Sass::Script::Value::String] The substring. This will be quoted
1519
- # if and only if `$string` was quoted
1520
- # @raise [ArgumentError] if any parameter is the wrong type
1521
- def str_slice(string, start_at, end_at = nil)
1522
- assert_type string, :String, :string
1523
- assert_unit start_at, nil, "start-at"
1524
-
1525
- end_at = number(-1) if end_at.nil?
1526
- assert_unit end_at, nil, "end-at"
1527
-
1528
- return Sass::Script::Value::String.new("", string.type) if end_at.value == 0
1529
- s = start_at.value > 0 ? start_at.value - 1 : start_at.value
1530
- e = end_at.value > 0 ? end_at.value - 1 : end_at.value
1531
- s = string.value.length + s if s < 0
1532
- s = 0 if s < 0
1533
- e = string.value.length + e if e < 0
1534
- e = 0 if s < 0
1535
- extracted = string.value.slice(s..e)
1536
- Sass::Script::Value::String.new(extracted || "", string.type)
1537
- end
1538
- declare :str_slice, [:string, :start_at]
1539
- declare :str_slice, [:string, :start_at, :end_at]
1540
-
1541
- # Converts a string to upper case.
1542
- #
1543
- # @example
1544
- # to-upper-case(abcd) => ABCD
1545
- #
1546
- # @overload to_upper_case($string)
1547
- # @param $string [Sass::Script::Value::String]
1548
- # @return [Sass::Script::Value::String]
1549
- # @raise [ArgumentError] if `$string` isn't a string
1550
- def to_upper_case(string)
1551
- assert_type string, :String, :string
1552
- Sass::Script::Value::String.new(string.value.upcase, string.type)
1553
- end
1554
- declare :to_upper_case, [:string]
1555
-
1556
- # Convert a string to lower case,
1557
- #
1558
- # @example
1559
- # to-lower-case(ABCD) => abcd
1560
- #
1561
- # @overload to_lower_case($string)
1562
- # @param $string [Sass::Script::Value::String]
1563
- # @return [Sass::Script::Value::String]
1564
- # @raise [ArgumentError] if `$string` isn't a string
1565
- def to_lower_case(string)
1566
- assert_type string, :String, :string
1567
- Sass::Script::Value::String.new(string.value.downcase, string.type)
1568
- end
1569
- declare :to_lower_case, [:string]
1570
-
1571
1123
  # Returns the type of a value.
1572
1124
  #
1573
1125
  # @example
@@ -1578,45 +1130,13 @@ module Sass::Script
1578
1130
  # type-of(#fff) => color
1579
1131
  # type-of(blue) => color
1580
1132
  # @overload type_of($value)
1581
- # @param $value [Sass::Script::Value::Base] The value to inspect
1582
- # @return [Sass::Script::Value::String] The unquoted string name of the
1583
- # value's type
1133
+ # @param $value [Literal] The value to inspect
1134
+ # @return [String] The unquoted string name of the value's type
1584
1135
  def type_of(value)
1585
- identifier(value.class.name.gsub(/Sass::Script::Value::/, '').downcase)
1136
+ Sass::Script::String.new(value.class.name.gsub(/Sass::Script::/,'').downcase)
1586
1137
  end
1587
1138
  declare :type_of, [:value]
1588
1139
 
1589
- # Returns whether a feature exists in the current Sass runtime.
1590
- #
1591
- # The following features are supported:
1592
- #
1593
- # * `global-variable-shadowing` indicates that a local variable will shadow
1594
- # a global variable unless `!global` is used.
1595
- #
1596
- # * `extend-selector-pseudoclass` indicates that `@extend` will reach into
1597
- # selector pseudoclasses like `:not`.
1598
- #
1599
- # * `units-level-3` indicates full support for unit arithmetic using units
1600
- # defined in the [Values and Units Level 3][] spec.
1601
- #
1602
- # [Values and Units Level 3]: http://www.w3.org/TR/css3-values/
1603
- #
1604
- # * `at-error` indicates that the Sass `@error` directive is supported.
1605
- #
1606
- # @example
1607
- # feature-exists(some-feature-that-exists) => true
1608
- # feature-exists(what-is-this-i-dont-know) => false
1609
- #
1610
- # @overload feature_exists($feature)
1611
- # @param $feature [Sass::Script::Value::String] The name of the feature
1612
- # @return [Sass::Script::Value::Bool] Whether the feature is supported in this version of Sass
1613
- # @raise [ArgumentError] if `$feature` isn't a string
1614
- def feature_exists(feature)
1615
- assert_type feature, :String, :feature
1616
- bool(Sass.has_feature?(feature.value))
1617
- end
1618
- declare :feature_exists, [:feature]
1619
-
1620
1140
  # Returns the unit(s) associated with a number. Complex units are sorted in
1621
1141
  # alphabetical order by numerator and denominator.
1622
1142
  #
@@ -1627,13 +1147,12 @@ module Sass::Script
1627
1147
  # unit(10px * 5em) => "em*px"
1628
1148
  # unit(10px * 5em / 30cm / 1rem) => "em*px/cm*rem"
1629
1149
  # @overload unit($number)
1630
- # @param $number [Sass::Script::Value::Number]
1631
- # @return [Sass::Script::Value::String] The unit(s) of the number, as a
1632
- # quoted string
1150
+ # @param $number [Number]
1151
+ # @return [String] The unit(s) of the number, as a quoted string
1633
1152
  # @raise [ArgumentError] if `$number` isn't a number
1634
1153
  def unit(number)
1635
1154
  assert_type number, :Number, :number
1636
- quoted_string(number.unit_str)
1155
+ Sass::Script::String.new(number.unit_str, :string)
1637
1156
  end
1638
1157
  declare :unit, [:number]
1639
1158
 
@@ -1643,12 +1162,12 @@ module Sass::Script
1643
1162
  # unitless(100) => true
1644
1163
  # unitless(100px) => false
1645
1164
  # @overload unitless($number)
1646
- # @param $number [Sass::Script::Value::Number]
1647
- # @return [Sass::Script::Value::Bool]
1165
+ # @param $number [Number]
1166
+ # @return [Bool]
1648
1167
  # @raise [ArgumentError] if `$number` isn't a number
1649
1168
  def unitless(number)
1650
1169
  assert_type number, :Number, :number
1651
- bool(number.unitless?)
1170
+ Sass::Script::Bool.new(number.unitless?)
1652
1171
  end
1653
1172
  declare :unitless, [:number]
1654
1173
 
@@ -1658,90 +1177,90 @@ module Sass::Script
1658
1177
  # comparable(2px, 1px) => true
1659
1178
  # comparable(100px, 3em) => false
1660
1179
  # comparable(10cm, 3mm) => true
1661
- # @overload comparable($number1, $number2)
1662
- # @param $number1 [Sass::Script::Value::Number]
1663
- # @param $number2 [Sass::Script::Value::Number]
1664
- # @return [Sass::Script::Value::Bool]
1180
+ # @overload comparable($number-1, $number-2)
1181
+ # @param $number-1 [Number]
1182
+ # @param $number-2 [Number]
1183
+ # @return [Bool]
1665
1184
  # @raise [ArgumentError] if either parameter is the wrong type
1666
- def comparable(number1, number2)
1667
- assert_type number1, :Number, :number1
1668
- assert_type number2, :Number, :number2
1669
- bool(number1.comparable_to?(number2))
1185
+ def comparable(number_1, number_2)
1186
+ assert_type number_1, :Number, :number_1
1187
+ assert_type number_2, :Number, :number_2
1188
+ Sass::Script::Bool.new(number_1.comparable_to?(number_2))
1670
1189
  end
1671
- declare :comparable, [:number1, :number2]
1190
+ declare :comparable, [:number_1, :number_2]
1672
1191
 
1673
1192
  # Converts a unitless number to a percentage.
1674
1193
  #
1675
1194
  # @example
1676
1195
  # percentage(0.2) => 20%
1677
1196
  # percentage(100px / 50px) => 200%
1678
- # @overload percentage($number)
1679
- # @param $number [Sass::Script::Value::Number]
1680
- # @return [Sass::Script::Value::Number]
1681
- # @raise [ArgumentError] if `$number` isn't a unitless number
1682
- def percentage(number)
1683
- unless number.is_a?(Sass::Script::Value::Number) && number.unitless?
1684
- raise ArgumentError.new("$number: #{number.inspect} is not a unitless number")
1197
+ # @overload percentage($value)
1198
+ # @param $value [Number]
1199
+ # @return [Number]
1200
+ # @raise [ArgumentError] if `$value` isn't a unitless number
1201
+ def percentage(value)
1202
+ unless value.is_a?(Sass::Script::Number) && value.unitless?
1203
+ raise ArgumentError.new("$value: #{value.inspect} is not a unitless number")
1685
1204
  end
1686
- number(number.value * 100, '%')
1205
+ Sass::Script::Number.new(value.value * 100, ['%'])
1687
1206
  end
1688
- declare :percentage, [:number]
1207
+ declare :percentage, [:value]
1689
1208
 
1690
1209
  # Rounds a number to the nearest whole number.
1691
1210
  #
1692
1211
  # @example
1693
1212
  # round(10.4px) => 10px
1694
1213
  # round(10.6px) => 11px
1695
- # @overload round($number)
1696
- # @param $number [Sass::Script::Value::Number]
1697
- # @return [Sass::Script::Value::Number]
1698
- # @raise [ArgumentError] if `$number` isn't a number
1699
- def round(number)
1700
- numeric_transformation(number) {|n| n.round}
1214
+ # @overload round($value)
1215
+ # @param $value [Number]
1216
+ # @return [Number]
1217
+ # @raise [ArgumentError] if `$value` isn't a number
1218
+ def round(value)
1219
+ numeric_transformation(value) {|n| n.round}
1701
1220
  end
1702
- declare :round, [:number]
1221
+ declare :round, [:value]
1703
1222
 
1704
1223
  # Rounds a number up to the next whole number.
1705
1224
  #
1706
1225
  # @example
1707
1226
  # ceil(10.4px) => 11px
1708
1227
  # ceil(10.6px) => 11px
1709
- # @overload ceil($number)
1710
- # @param $number [Sass::Script::Value::Number]
1711
- # @return [Sass::Script::Value::Number]
1712
- # @raise [ArgumentError] if `$number` isn't a number
1713
- def ceil(number)
1714
- numeric_transformation(number) {|n| n.ceil}
1228
+ # @overload ceil($value)
1229
+ # @param $value [Number]
1230
+ # @return [Number]
1231
+ # @raise [ArgumentError] if `$value` isn't a number
1232
+ def ceil(value)
1233
+ numeric_transformation(value) {|n| n.ceil}
1715
1234
  end
1716
- declare :ceil, [:number]
1235
+ declare :ceil, [:value]
1717
1236
 
1718
1237
  # Rounds a number down to the previous whole number.
1719
1238
  #
1720
1239
  # @example
1721
1240
  # floor(10.4px) => 10px
1722
1241
  # floor(10.6px) => 10px
1723
- # @overload floor($number)
1724
- # @param $number [Sass::Script::Value::Number]
1725
- # @return [Sass::Script::Value::Number]
1726
- # @raise [ArgumentError] if `$number` isn't a number
1727
- def floor(number)
1728
- numeric_transformation(number) {|n| n.floor}
1242
+ # @overload floor($value)
1243
+ # @param $value [Number]
1244
+ # @return [Number]
1245
+ # @raise [ArgumentError] if `$value` isn't a number
1246
+ def floor(value)
1247
+ numeric_transformation(value) {|n| n.floor}
1729
1248
  end
1730
- declare :floor, [:number]
1249
+ declare :floor, [:value]
1731
1250
 
1732
1251
  # Returns the absolute value of a number.
1733
1252
  #
1734
1253
  # @example
1735
1254
  # abs(10px) => 10px
1736
1255
  # abs(-10px) => 10px
1737
- # @overload abs($number)
1738
- # @param $number [Sass::Script::Value::Number]
1739
- # @return [Sass::Script::Value::Number]
1740
- # @raise [ArgumentError] if `$number` isn't a number
1741
- def abs(number)
1742
- numeric_transformation(number) {|n| n.abs}
1256
+ # @overload abs($value)
1257
+ # @param $value [Number]
1258
+ # @return [Number]
1259
+ # @raise [ArgumentError] if `$value` isn't a number
1260
+ def abs(value)
1261
+ numeric_transformation(value) {|n| n.abs}
1743
1262
  end
1744
- declare :abs, [:number]
1263
+ declare :abs, [:value]
1745
1264
 
1746
1265
  # Finds the minimum of several numbers. This function takes any number of
1747
1266
  # arguments.
@@ -1750,8 +1269,8 @@ module Sass::Script
1750
1269
  # min(1px, 4px) => 1px
1751
1270
  # min(5em, 3em, 4em) => 3em
1752
1271
  # @overload min($numbers...)
1753
- # @param $numbers [[Sass::Script::Value::Number]]
1754
- # @return [Sass::Script::Value::Number]
1272
+ # @param $numbers [[Number]]
1273
+ # @return [Number]
1755
1274
  # @raise [ArgumentError] if any argument isn't a number, or if not all of
1756
1275
  # the arguments have comparable units
1757
1276
  def min(*numbers)
@@ -1767,8 +1286,8 @@ module Sass::Script
1767
1286
  # max(1px, 4px) => 4px
1768
1287
  # max(5em, 3em, 4em) => 5em
1769
1288
  # @overload max($numbers...)
1770
- # @param $numbers [[Sass::Script::Value::Number]]
1771
- # @return [Sass::Script::Value::Number]
1289
+ # @param $numbers [[Number]]
1290
+ # @return [Number]
1772
1291
  # @raise [ArgumentError] if any argument isn't a number, or if not all of
1773
1292
  # the arguments have comparable units
1774
1293
  def max(*values)
@@ -1779,77 +1298,44 @@ module Sass::Script
1779
1298
 
1780
1299
  # Return the length of a list.
1781
1300
  #
1782
- # This can return the number of pairs in a map as well.
1783
- #
1784
1301
  # @example
1785
1302
  # length(10px) => 1
1786
1303
  # length(10px 20px 30px) => 3
1787
- # length((width: 10px, height: 20px)) => 2
1788
1304
  # @overload length($list)
1789
- # @param $list [Sass::Script::Value::Base]
1790
- # @return [Sass::Script::Value::Number]
1305
+ # @param $list [Literal]
1306
+ # @return [Number]
1791
1307
  def length(list)
1792
- number(list.to_a.size)
1308
+ Sass::Script::Number.new(list.to_a.size)
1793
1309
  end
1794
1310
  declare :length, [:list]
1795
1311
 
1796
- # Return a new list, based on the list provided, but with the nth
1797
- # element changed to the value given.
1798
- #
1799
- # Note that unlike some languages, the first item in a Sass list is number
1800
- # 1, the second number 2, and so forth.
1801
- #
1802
- # Negative index values address elements in reverse order, starting with the last element
1803
- # in the list.
1804
- #
1805
- # @example
1806
- # set-nth($list: 10px 20px 30px, $n: 2, $value: -20px) => 10px -20px 30px
1807
- # @overload set-nth($list, $n, $value)
1808
- # @param $list [Sass::Script::Value::Base] The list that will be copied, having the element
1809
- # at index `$n` changed.
1810
- # @param $n [Sass::Script::Value::Number] The index of the item to set.
1811
- # Negative indices count from the end of the list.
1812
- # @param $value [Sass::Script::Value::Base] The new value at index `$n`.
1813
- # @return [Sass::Script::Value::List]
1814
- # @raise [ArgumentError] if `$n` isn't an integer between 1 and the length
1815
- # of `$list`
1816
- def set_nth(list, n, value)
1817
- assert_type n, :Number, :n
1818
- Sass::Script::Value::List.assert_valid_index(list, n)
1819
- index = n.to_i > 0 ? n.to_i - 1 : n.to_i
1820
- new_list = list.to_a.dup
1821
- new_list[index] = value
1822
- Sass::Script::Value::List.new(new_list, list.separator)
1823
- end
1824
- declare :set_nth, [:list, :n, :value]
1825
-
1826
1312
  # Gets the nth item in a list.
1827
1313
  #
1828
1314
  # Note that unlike some languages, the first item in a Sass list is number
1829
1315
  # 1, the second number 2, and so forth.
1830
1316
  #
1831
- # This can return the nth pair in a map as well.
1832
- #
1833
- # Negative index values address elements in reverse order, starting with the last element in
1834
- # the list.
1835
- #
1836
1317
  # @example
1837
1318
  # nth(10px 20px 30px, 1) => 10px
1838
1319
  # nth((Helvetica, Arial, sans-serif), 3) => sans-serif
1839
- # nth((width: 10px, length: 20px), 2) => length, 20px
1840
1320
  # @overload nth($list, $n)
1841
- # @param $list [Sass::Script::Value::Base]
1842
- # @param $n [Sass::Script::Value::Number] The index of the item to get.
1843
- # Negative indices count from the end of the list.
1844
- # @return [Sass::Script::Value::Base]
1321
+ # @param $list [Literal]
1322
+ # @param $n [Number] The index of the item to get
1323
+ # @return [Literal]
1845
1324
  # @raise [ArgumentError] if `$n` isn't an integer between 1 and the length
1846
1325
  # of `$list`
1847
1326
  def nth(list, n)
1848
1327
  assert_type n, :Number, :n
1849
- Sass::Script::Value::List.assert_valid_index(list, n)
1328
+ if !n.int?
1329
+ raise ArgumentError.new("List index #{n} must be an integer")
1330
+ elsif n.to_i < 1
1331
+ raise ArgumentError.new("List index #{n} must be greater than or equal to 1")
1332
+ elsif list.to_a.size == 0
1333
+ raise ArgumentError.new("List index is #{n} but list has no items")
1334
+ elsif n.to_i > (size = list.to_a.size)
1335
+ raise ArgumentError.new("List index is #{n} but list is only #{size} item#{'s' if size != 1} long")
1336
+ end
1850
1337
 
1851
- index = n.to_i > 0 ? n.to_i - 1 : n.to_i
1852
- list.to_a[index]
1338
+ list.to_a[n.to_i - 1]
1853
1339
  end
1854
1340
  declare :nth, [:list, :n]
1855
1341
 
@@ -1867,23 +1353,26 @@ module Sass::Script
1867
1353
  # join(10px, 20px, comma) => 10px, 20px
1868
1354
  # join((blue, red), (#abc, #def), space) => blue red #abc #def
1869
1355
  # @overload join($list1, $list2, $separator: auto)
1870
- # @param $list1 [Sass::Script::Value::Base]
1871
- # @param $list2 [Sass::Script::Value::Base]
1872
- # @param $separator [Sass::Script::Value::String] The list separator to use.
1873
- # If this is `comma` or `space`, that separator will be used. If this is
1874
- # `auto` (the default), the separator is determined as explained above.
1875
- # @return [Sass::Script::Value::List]
1876
- def join(list1, list2, separator = identifier("auto"))
1356
+ # @param $list1 [Literal]
1357
+ # @param $list2 [Literal]
1358
+ # @param $separator [String] The list separator to use. If this is `comma`
1359
+ # or `space`, that separator will be used. If this is `auto` (the
1360
+ # default), the separator is determined as explained above.
1361
+ # @return [List]
1362
+ def join(list1, list2, separator = Sass::Script::String.new("auto"))
1877
1363
  assert_type separator, :String, :separator
1878
1364
  unless %w[auto space comma].include?(separator.value)
1879
1365
  raise ArgumentError.new("Separator name must be space, comma, or auto")
1880
1366
  end
1881
- sep = if separator.value == 'auto'
1882
- list1.separator || list2.separator || :space
1883
- else
1884
- separator.value.to_sym
1885
- end
1886
- list(list1.to_a + list2.to_a, sep)
1367
+ sep1 = list1.separator if list1.is_a?(Sass::Script::List) && !list1.value.empty?
1368
+ sep2 = list2.separator if list2.is_a?(Sass::Script::List) && !list2.value.empty?
1369
+ Sass::Script::List.new(
1370
+ list1.to_a + list2.to_a,
1371
+ if separator.value == 'auto'
1372
+ sep1 || sep2 || :space
1373
+ else
1374
+ separator.value.to_sym
1375
+ end)
1887
1376
  end
1888
1377
  declare :join, [:list1, :list2]
1889
1378
  declare :join, [:list1, :list2, :separator]
@@ -1900,23 +1389,25 @@ module Sass::Script
1900
1389
  # append(10px, 20px, comma) => 10px, 20px
1901
1390
  # append((blue, red), green, space) => blue red green
1902
1391
  # @overload append($list, $val, $separator: auto)
1903
- # @param $list [Sass::Script::Value::Base]
1904
- # @param $val [Sass::Script::Value::Base]
1905
- # @param $separator [Sass::Script::Value::String] The list separator to use.
1906
- # If this is `comma` or `space`, that separator will be used. If this is
1907
- # `auto` (the default), the separator is determined as explained above.
1908
- # @return [Sass::Script::Value::List]
1909
- def append(list, val, separator = identifier("auto"))
1392
+ # @param $list [Literal]
1393
+ # @param $val [Literal]
1394
+ # @param $separator [String] The list separator to use. If this is `comma`
1395
+ # or `space`, that separator will be used. If this is `auto` (the
1396
+ # default), the separator is determined as explained above.
1397
+ # @return [List]
1398
+ def append(list, val, separator = Sass::Script::String.new("auto"))
1910
1399
  assert_type separator, :String, :separator
1911
1400
  unless %w[auto space comma].include?(separator.value)
1912
1401
  raise ArgumentError.new("Separator name must be space, comma, or auto")
1913
1402
  end
1914
- sep = if separator.value == 'auto'
1915
- list.separator || :space
1916
- else
1917
- separator.value.to_sym
1918
- end
1919
- list(list.to_a + [val], sep)
1403
+ sep = list.separator if list.is_a?(Sass::Script::List)
1404
+ Sass::Script::List.new(
1405
+ list.to_a + [val],
1406
+ if separator.value == 'auto'
1407
+ sep || :space
1408
+ else
1409
+ separator.value.to_sym
1410
+ end)
1920
1411
  end
1921
1412
  declare :append, [:list, :val]
1922
1413
  declare :append, [:list, :val, :separator]
@@ -1932,8 +1423,8 @@ module Sass::Script
1932
1423
  # zip(1px 1px 3px, solid dashed solid, red green blue)
1933
1424
  # => 1px solid red, 1px dashed green, 3px solid blue
1934
1425
  # @overload zip($lists...)
1935
- # @param $lists [[Sass::Script::Value::Base]]
1936
- # @return [Sass::Script::Value::List]
1426
+ # @param $lists [[Literal]]
1427
+ # @return [List]
1937
1428
  def zip(*lists)
1938
1429
  length = nil
1939
1430
  values = []
@@ -1946,176 +1437,35 @@ module Sass::Script
1946
1437
  value.slice!(length)
1947
1438
  end
1948
1439
  new_list_value = values.first.zip(*values[1..-1])
1949
- list(new_list_value.map {|list| list(list, :space)}, :comma)
1440
+ List.new(new_list_value.map{|list| List.new(list, :space)}, :comma)
1950
1441
  end
1951
1442
  declare :zip, [], :var_args => true
1952
1443
 
1444
+
1953
1445
  # Returns the position of a value within a list. If the value isn't found,
1954
- # returns `null` instead.
1446
+ # returns false instead.
1955
1447
  #
1956
1448
  # Note that unlike some languages, the first item in a Sass list is number
1957
1449
  # 1, the second number 2, and so forth.
1958
1450
  #
1959
- # This can return the position of a pair in a map as well.
1960
- #
1961
1451
  # @example
1962
1452
  # index(1px solid red, solid) => 2
1963
- # index(1px solid red, dashed) => null
1964
- # index((width: 10px, height: 20px), (height 20px)) => 2
1453
+ # index(1px solid red, dashed) => false
1965
1454
  # @overload index($list, $value)
1966
- # @param $list [Sass::Script::Value::Base]
1967
- # @param $value [Sass::Script::Value::Base]
1968
- # @return [Sass::Script::Value::Number, Sass::Script::Value::Null] The
1969
- # 1-based index of `$value` in `$list`, or `null`
1455
+ # @param $list [Literal]
1456
+ # @param $value [Literal]
1457
+ # @return [Number, Bool] The 1-based index of `$value` in `$list`, or
1458
+ # `false`
1970
1459
  def index(list, value)
1971
- index = list.to_a.index {|e| e.eq(value).to_bool}
1972
- index ? number(index + 1) : null
1460
+ index = list.to_a.index {|e| e.eq(value).to_bool }
1461
+ if index
1462
+ Number.new(index + 1)
1463
+ else
1464
+ Bool.new(false)
1465
+ end
1973
1466
  end
1974
1467
  declare :index, [:list, :value]
1975
1468
 
1976
- # Returns the separator of a list. If the list doesn't have a separator due
1977
- # to having fewer than two elements, returns `space`.
1978
- #
1979
- # @example
1980
- # list-separator(1px 2px 3px) => space
1981
- # list-separator(1px, 2px, 3px) => comma
1982
- # list-separator('foo') => space
1983
- # @overload list_separator($list)
1984
- # @param $list [Sass::Script::Value::Base]
1985
- # @return [Sass::Script::Value::String] `comma` or `space`
1986
- def list_separator(list)
1987
- identifier((list.separator || :space).to_s)
1988
- end
1989
- declare :separator, [:list]
1990
-
1991
- # Returns the value in a map associated with the given key. If the map
1992
- # doesn't have such a key, returns `null`.
1993
- #
1994
- # @example
1995
- # map-get(("foo": 1, "bar": 2), "foo") => 1
1996
- # map-get(("foo": 1, "bar": 2), "bar") => 2
1997
- # map-get(("foo": 1, "bar": 2), "baz") => null
1998
- # @overload map_get($map, $key)
1999
- # @param $map [Sass::Script::Value::Map]
2000
- # @param $key [Sass::Script::Value::Base]
2001
- # @return [Sass::Script::Value::Base] The value indexed by `$key`, or `null`
2002
- # if the map doesn't contain the given key
2003
- # @raise [ArgumentError] if `$map` is not a map
2004
- def map_get(map, key)
2005
- assert_type map, :Map, :map
2006
- map.to_h[key] || null
2007
- end
2008
- declare :map_get, [:map, :key]
2009
-
2010
- # Merges two maps together into a new map. Keys in `$map2` will take
2011
- # precedence over keys in `$map1`.
2012
- #
2013
- # This is the best way to add new values to a map.
2014
- #
2015
- # All keys in the returned map that also appear in `$map1` will have the
2016
- # same order as in `$map1`. New keys from `$map2` will be placed at the end
2017
- # of the map.
2018
- #
2019
- # @example
2020
- # map-merge(("foo": 1), ("bar": 2)) => ("foo": 1, "bar": 2)
2021
- # map-merge(("foo": 1, "bar": 2), ("bar": 3)) => ("foo": 1, "bar": 3)
2022
- # @overload map_merge($map1, $map2)
2023
- # @param $map1 [Sass::Script::Value::Map]
2024
- # @param $map2 [Sass::Script::Value::Map]
2025
- # @return [Sass::Script::Value::Map]
2026
- # @raise [ArgumentError] if either parameter is not a map
2027
- def map_merge(map1, map2)
2028
- assert_type map1, :Map, :map1
2029
- assert_type map2, :Map, :map2
2030
- map(map1.to_h.merge(map2.to_h))
2031
- end
2032
- declare :map_merge, [:map1, :map2]
2033
-
2034
- # Returns a new map with keys removed.
2035
- #
2036
- # @example
2037
- # map-remove(("foo": 1, "bar": 2), "bar") => ("foo": 1)
2038
- # map-remove(("foo": 1, "bar": 2, "baz": 3), "bar", "baz") => ("foo": 1)
2039
- # map-remove(("foo": 1, "bar": 2), "baz") => ("foo": 1, "bar": 2)
2040
- # @overload map_remove($map, $keys...)
2041
- # @param $map [Sass::Script::Value::Map]
2042
- # @param $keys [[Sass::Script::Value::Base]]
2043
- # @return [Sass::Script::Value::Map]
2044
- # @raise [ArgumentError] if `$map` is not a map
2045
- def map_remove(map, *keys)
2046
- assert_type map, :Map, :map
2047
- hash = map.to_h.dup
2048
- hash.delete_if {|key, _| keys.include?(key)}
2049
- map(hash)
2050
- end
2051
- declare :map_remove, [:map, :key], :var_args => true
2052
-
2053
- # Returns a list of all keys in a map.
2054
- #
2055
- # @example
2056
- # map-keys(("foo": 1, "bar": 2)) => "foo", "bar"
2057
- # @overload map_keys($map)
2058
- # @param $map [Map]
2059
- # @return [List] the list of keys, comma-separated
2060
- # @raise [ArgumentError] if `$map` is not a map
2061
- def map_keys(map)
2062
- assert_type map, :Map, :map
2063
- list(map.to_h.keys, :comma)
2064
- end
2065
- declare :map_keys, [:map]
2066
-
2067
- # Returns a list of all values in a map. This list may include duplicate
2068
- # values, if multiple keys have the same value.
2069
- #
2070
- # @example
2071
- # map-values(("foo": 1, "bar": 2)) => 1, 2
2072
- # map-values(("foo": 1, "bar": 2, "baz": 1)) => 1, 2, 1
2073
- # @overload map_values($map)
2074
- # @param $map [Map]
2075
- # @return [List] the list of values, comma-separated
2076
- # @raise [ArgumentError] if `$map` is not a map
2077
- def map_values(map)
2078
- assert_type map, :Map, :map
2079
- list(map.to_h.values, :comma)
2080
- end
2081
- declare :map_values, [:map]
2082
-
2083
- # Returns whether a map has a value associated with a given key.
2084
- #
2085
- # @example
2086
- # map-has-key(("foo": 1, "bar": 2), "foo") => true
2087
- # map-has-key(("foo": 1, "bar": 2), "baz") => false
2088
- # @overload map_has_key($map, $key)
2089
- # @param $map [Sass::Script::Value::Map]
2090
- # @param $key [Sass::Script::Value::Base]
2091
- # @return [Sass::Script::Value::Bool]
2092
- # @raise [ArgumentError] if `$map` is not a map
2093
- def map_has_key(map, key)
2094
- assert_type map, :Map, :map
2095
- bool(map.to_h.has_key?(key))
2096
- end
2097
- declare :map_has_key, [:map, :key]
2098
-
2099
- # Returns the map of named arguments passed to a function or mixin that
2100
- # takes a variable argument list. The argument names are strings, and they
2101
- # do not contain the leading `$`.
2102
- #
2103
- # @example
2104
- # @mixin foo($args...) {
2105
- # @debug keywords($args); //=> (arg1: val, arg2: val)
2106
- # }
2107
- #
2108
- # @include foo($arg1: val, $arg2: val);
2109
- # @overload keywords($args)
2110
- # @param $args [Sass::Script::Value::ArgList]
2111
- # @return [Sass::Script::Value::Map]
2112
- # @raise [ArgumentError] if `$args` isn't a variable argument list
2113
- def keywords(args)
2114
- assert_type args, :ArgList, :args
2115
- map(Sass::Util.map_keys(args.keywords.as_stored) {|k| Sass::Script::Value::String.new(k)})
2116
- end
2117
- declare :keywords, [:args]
2118
-
2119
1469
  # Returns one of two values, depending on whether or not `$condition` is
2120
1470
  # true. Just like in `@if`, all values other than `false` and `null` are
2121
1471
  # considered to be true.
@@ -2124,483 +1474,50 @@ module Sass::Script
2124
1474
  # if(true, 1px, 2px) => 1px
2125
1475
  # if(false, 1px, 2px) => 2px
2126
1476
  # @overload if($condition, $if-true, $if-false)
2127
- # @param $condition [Sass::Script::Value::Base] Whether the `$if-true` or
2128
- # `$if-false` will be returned
2129
- # @param $if-true [Sass::Script::Tree::Node]
2130
- # @param $if-false [Sass::Script::Tree::Node]
2131
- # @return [Sass::Script::Value::Base] `$if-true` or `$if-false`
1477
+ # @param $condition [Literal] Whether the `$if-true` or `$if-false` will be
1478
+ # returned
1479
+ # @param $if-true [Literal]
1480
+ # @param $if-false [Literal]
1481
+ # @return [Literal] `$if-true` or `$if-false`
2132
1482
  def if(condition, if_true, if_false)
2133
1483
  if condition.to_bool
2134
- perform(if_true)
1484
+ if_true
2135
1485
  else
2136
- perform(if_false)
1486
+ if_false
2137
1487
  end
2138
1488
  end
2139
- declare :if, [:condition, :"&if_true", :"&if_false"]
2140
-
2141
- # Returns a unique CSS identifier. The identifier is returned as an unquoted
2142
- # string. The identifier returned is only guaranteed to be unique within the
2143
- # scope of a single Sass run.
2144
- #
2145
- # @overload unique_id()
2146
- # @return [Sass::Script::Value::String]
2147
- def unique_id
2148
- generator = Sass::Script::Functions.random_number_generator
2149
- Thread.current[:sass_last_unique_id] ||= generator.rand(36**8)
2150
- # avoid the temptation of trying to guess the next unique value.
2151
- value = (Thread.current[:sass_last_unique_id] += (generator.rand(10) + 1))
2152
- # the u makes this a legal identifier if it would otherwise start with a number.
2153
- identifier("u" + value.to_s(36).rjust(8, '0'))
2154
- end
2155
- declare :unique_id, []
1489
+ declare :if, [:condition, :if_true, :if_false]
2156
1490
 
2157
- # Dynamically calls a function. This can call user-defined
2158
- # functions, built-in functions, or plain CSS functions. It will
2159
- # pass along all arguments, including keyword arguments, to the
2160
- # called function.
2161
- #
2162
- # @example
2163
- # call(rgb, 10, 100, 255) => #0a64ff
2164
- # call(scale-color, #0a64ff, $lightness: -10%) => #0058ef
2165
- #
2166
- # $fn: nth;
2167
- # call($fn, (a b c), 2) => b
2168
- #
2169
- # @overload call($name, $args...)
2170
- # @param $name [String] The name of the function to call.
2171
- def call(name, *args)
2172
- assert_type name, :String, :name
2173
- kwargs = args.last.is_a?(Hash) ? args.pop : {}
2174
- funcall = Sass::Script::Tree::Funcall.new(
2175
- name.value,
2176
- args.map {|a| Sass::Script::Tree::Literal.new(a)},
2177
- Sass::Util.map_vals(kwargs) {|v| Sass::Script::Tree::Literal.new(v)},
2178
- nil,
2179
- nil)
2180
- funcall.options = options
2181
- perform(funcall)
2182
- end
2183
- declare :call, [:name], :var_args => true, :var_kwargs => true
2184
-
2185
- # This function only exists as a workaround for IE7's [`content:
2186
- # counter` bug](http://jes.st/2013/ie7s-css-breaking-content-counter-bug/).
2187
- # It works identically to any other plain-CSS function, except it
1491
+ # This function only exists as a workaround for IE7's [`content: counter`
1492
+ # bug][bug]. It works identically to any other plain-CSS function, except it
2188
1493
  # avoids adding spaces between the argument commas.
2189
1494
  #
1495
+ # [bug]: http://jes.st/2013/ie7s-css-breaking-content-counter-bug/
1496
+ #
2190
1497
  # @example
2191
1498
  # counter(item, ".") => counter(item,".")
2192
1499
  # @overload counter($args...)
2193
- # @return [Sass::Script::Value::String]
1500
+ # @return [String]
2194
1501
  def counter(*args)
2195
- identifier("counter(#{args.map {|a| a.to_s(options)}.join(',')})")
1502
+ Sass::Script::String.new("counter(#{args.map {|a| a.to_s(options)}.join(',')})")
2196
1503
  end
2197
1504
  declare :counter, [], :var_args => true
2198
1505
 
2199
- # This function only exists as a workaround for IE7's [`content:
2200
- # counter` bug](http://jes.st/2013/ie7s-css-breaking-content-counter-bug/).
2201
- # It works identically to any other plain-CSS function, except it
1506
+ # This function only exists as a workaround for IE7's [`content: counters`
1507
+ # bug][bug]. It works identically to any other plain-CSS function, except it
2202
1508
  # avoids adding spaces between the argument commas.
2203
1509
  #
1510
+ # [bug]: http://jes.st/2013/ie7s-css-breaking-content-counter-bug/
1511
+ #
2204
1512
  # @example
2205
1513
  # counters(item, ".") => counters(item,".")
2206
1514
  # @overload counters($args...)
2207
- # @return [Sass::Script::Value::String]
1515
+ # @return [String]
2208
1516
  def counters(*args)
2209
- identifier("counters(#{args.map {|a| a.to_s(options)}.join(',')})")
1517
+ Sass::Script::String.new("counters(#{args.map {|a| a.to_s(options)}.join(',')})")
2210
1518
  end
2211
1519
  declare :counters, [], :var_args => true
2212
1520
 
2213
- # Check whether a variable with the given name exists in the current
2214
- # scope or in the global scope.
2215
- #
2216
- # @example
2217
- # $a-false-value: false;
2218
- # variable-exists(a-false-value) => true
2219
- #
2220
- # variable-exists(nonexistent) => false
2221
- #
2222
- # @overload variable_exists($name)
2223
- # @param $name [Sass::Script::Value::String] The name of the variable to
2224
- # check. The name should not include the `$`.
2225
- # @return [Sass::Script::Value::Bool] Whether the variable is defined in
2226
- # the current scope.
2227
- def variable_exists(name)
2228
- assert_type name, :String, :name
2229
- bool(environment.caller.var(name.value))
2230
- end
2231
- declare :variable_exists, [:name]
2232
-
2233
- # Check whether a variable with the given name exists in the global
2234
- # scope (at the top level of the file).
2235
- #
2236
- # @example
2237
- # $a-false-value: false;
2238
- # global-variable-exists(a-false-value) => true
2239
- #
2240
- # .foo {
2241
- # $some-var: false;
2242
- # @if global-variable-exists(some-var) { /* false, doesn't run */ }
2243
- # }
2244
- #
2245
- # @overload global_variable_exists($name)
2246
- # @param $name [Sass::Script::Value::String] The name of the variable to
2247
- # check. The name should not include the `$`.
2248
- # @return [Sass::Script::Value::Bool] Whether the variable is defined in
2249
- # the global scope.
2250
- def global_variable_exists(name)
2251
- assert_type name, :String, :name
2252
- bool(environment.global_env.var(name.value))
2253
- end
2254
- declare :global_variable_exists, [:name]
2255
-
2256
- # Check whether a function with the given name exists.
2257
- #
2258
- # @example
2259
- # function-exists(lighten) => true
2260
- #
2261
- # @function myfunc { @return "something"; }
2262
- # function-exists(myfunc) => true
2263
- #
2264
- # @overload function_exists($name)
2265
- # @param name [Sass::Script::Value::String] The name of the function to
2266
- # check.
2267
- # @return [Sass::Script::Value::Bool] Whether the function is defined.
2268
- def function_exists(name)
2269
- assert_type name, :String, :name
2270
- exists = Sass::Script::Functions.callable?(name.value.tr("-", "_"))
2271
- exists ||= environment.function(name.value)
2272
- bool(exists)
2273
- end
2274
- declare :function_exists, [:name]
2275
-
2276
- # Check whether a mixin with the given name exists.
2277
- #
2278
- # @example
2279
- # mixin-exists(nonexistent) => false
2280
- #
2281
- # @mixin red-text { color: red; }
2282
- # mixin-exists(red-text) => true
2283
- #
2284
- # @overload mixin_exists($name)
2285
- # @param name [Sass::Script::Value::String] The name of the mixin to
2286
- # check.
2287
- # @return [Sass::Script::Value::Bool] Whether the mixin is defined.
2288
- def mixin_exists(name)
2289
- assert_type name, :String, :name
2290
- bool(environment.mixin(name.value))
2291
- end
2292
- declare :mixin_exists, [:name]
2293
-
2294
- # Return a string containing the value as its Sass representation.
2295
- #
2296
- # @overload inspect($value)
2297
- # @param $value [Sass::Script::Value::Base] The value to inspect.
2298
- # @return [Sass::Script::Value::String] A representation of the value as
2299
- # it would be written in Sass.
2300
- def inspect(value)
2301
- unquoted_string(value.to_sass)
2302
- end
2303
- declare :inspect, [:value]
2304
-
2305
- # @overload random()
2306
- # Return a decimal between 0 and 1, inclusive of 0 but not 1.
2307
- # @return [Sass::Script::Value::Number] A decimal value.
2308
- # @overload random($limit)
2309
- # Return an integer between 1 and `$limit`, inclusive of 1 but not `$limit`.
2310
- # @param $limit [Sass::Script::Value::Number] The maximum of the random integer to be
2311
- # returned, a positive integer.
2312
- # @return [Sass::Script::Value::Number] An integer.
2313
- # @raise [ArgumentError] if the `$limit` is not 1 or greater
2314
- def random(limit = nil)
2315
- generator = Sass::Script::Functions.random_number_generator
2316
- if limit
2317
- assert_integer limit, "limit"
2318
- if limit.value < 1
2319
- raise ArgumentError.new("$limit #{limit} must be greater than or equal to 1")
2320
- end
2321
- number(1 + generator.rand(limit.value))
2322
- else
2323
- number(generator.rand)
2324
- end
2325
- end
2326
- declare :random, []
2327
- declare :random, [:limit]
2328
-
2329
- # Parses a user-provided selector into a list of lists of strings
2330
- # as returned by `&`.
2331
- #
2332
- # @example
2333
- # selector-parse(".foo .bar, .baz .bang") => ('.foo' '.bar', '.baz' '.bang')
2334
- #
2335
- # @overload selector_parse($selector)
2336
- # @param $selector [Sass::Script::Value::String, Sass::Script::Value::List]
2337
- # The selector to parse. This can be either a string, a list of
2338
- # strings, or a list of lists of strings as returned by `&`.
2339
- # @return [Sass::Script::Value::List]
2340
- # A list of lists of strings representing `$selector`. This is
2341
- # in the same format as a selector returned by `&`.
2342
- def selector_parse(selector)
2343
- parse_selector(selector, :selector).to_sass_script
2344
- end
2345
- declare :selector_parse, [:selector]
2346
-
2347
- # Return a new selector with all selectors in `$selectors` nested beneath
2348
- # one another as though they had been nested in the stylesheet as
2349
- # `$selector1 { $selector2 { ... } }`.
2350
- #
2351
- # Unlike most selector functions, `selector-nest` allows the
2352
- # parent selector `&` to be used in any selector but the first.
2353
- #
2354
- # @example
2355
- # selector-nest(".foo", ".bar", ".baz") => .foo .bar .baz
2356
- # selector-nest(".a .foo", ".b .bar") => .a .foo .b .bar
2357
- # selector-nest(".foo", "&.bar") => .foo.bar
2358
- #
2359
- # @overload selector_nest($selectors...)
2360
- # @param $selectors [[Sass::Script::Value::String, Sass::Script::Value::List]]
2361
- # The selectors to nest. At least one selector must be passed. Each of
2362
- # these can be either a string, a list of strings, or a list of lists of
2363
- # strings as returned by `&`.
2364
- # @return [Sass::Script::Value::List]
2365
- # A list of lists of strings representing the result of nesting
2366
- # `$selectors`. This is in the same format as a selector returned by
2367
- # `&`.
2368
- def selector_nest(*selectors)
2369
- if selectors.empty?
2370
- raise ArgumentError.new("$selectors: At least one selector must be passed")
2371
- end
2372
-
2373
- parsed = [parse_selector(selectors.first, :selectors)]
2374
- parsed += selectors[1..-1].map {|sel| parse_selector(sel, :selectors, !!:parse_parent_ref)}
2375
- parsed.inject {|result, child| child.resolve_parent_refs(result)}.to_sass_script
2376
- end
2377
- declare :selector_nest, [], :var_args => true
2378
-
2379
- # Return a new selector with all selectors in `$selectors` appended one
2380
- # another as though they had been nested in the stylesheet as `$selector1 {
2381
- # &$selector2 { ... } }`.
2382
- #
2383
- # @example
2384
- # selector-append(".foo", ".bar", ".baz") => .foo.bar.baz
2385
- # selector-append(".a .foo", ".b .bar") => "a .foo.b .bar"
2386
- # selector-append(".foo", "-suffix") => ".foo-suffix"
2387
- #
2388
- # @overload selector_append($selectors...)
2389
- # @param $selectors [[Sass::Script::Value::String, Sass::Script::Value::List]]
2390
- # The selectors to append. At least one selector must be passed. Each of
2391
- # these can be either a string, a list of strings, or a list of lists of
2392
- # strings as returned by `&`.
2393
- # @return [Sass::Script::Value::List]
2394
- # A list of lists of strings representing the result of appending
2395
- # `$selectors`. This is in the same format as a selector returned by
2396
- # `&`.
2397
- # @raise [ArgumentError] if a selector could not be appended.
2398
- def selector_append(*selectors)
2399
- if selectors.empty?
2400
- raise ArgumentError.new("$selectors: At least one selector must be passed")
2401
- end
2402
-
2403
- selectors.map {|sel| parse_selector(sel, :selectors)}.inject do |parent, child|
2404
- child.members.each do |seq|
2405
- sseq = seq.members.first
2406
- unless sseq.is_a?(Sass::Selector::SimpleSequence)
2407
- raise ArgumentError.new("Can't append \"#{seq}\" to \"#{parent}\"")
2408
- end
2409
-
2410
- base = sseq.base
2411
- case base
2412
- when Sass::Selector::Universal
2413
- raise ArgumentError.new("Can't append \"#{seq}\" to \"#{parent}\"")
2414
- when Sass::Selector::Element
2415
- unless base.namespace.nil?
2416
- raise ArgumentError.new("Can't append \"#{seq}\" to \"#{parent}\"")
2417
- end
2418
- sseq.members[0] = Sass::Selector::Parent.new(base.name)
2419
- else
2420
- sseq.members.unshift Sass::Selector::Parent.new
2421
- end
2422
- end
2423
- child.resolve_parent_refs(parent)
2424
- end.to_sass_script
2425
- end
2426
- declare :selector_append, [], :var_args => true
2427
-
2428
- # Returns a new version of `$selector` with `$extendee` extended
2429
- # with `$extender`. This works just like the result of
2430
- #
2431
- # $selector { ... }
2432
- # $extender { @extend $extendee }
2433
- #
2434
- # @example
2435
- # selector-extend(".a .b", ".b", ".foo .bar") => .a .b, .a .foo .bar, .foo .a .bar
2436
- #
2437
- # @overload selector_extend($selector, $extendee, $extender)
2438
- # @param $selector [Sass::Script::Value::String, Sass::Script::Value::List]
2439
- # The selector within which `$extendee` is extended with
2440
- # `$extender`. This can be either a string, a list of strings,
2441
- # or a list of lists of strings as returned by `&`.
2442
- # @param $extendee [Sass::Script::Value::String, Sass::Script::Value::List]
2443
- # The selector being extended. This can be either a string, a
2444
- # list of strings, or a list of lists of strings as returned
2445
- # by `&`.
2446
- # @param $extender [Sass::Script::Value::String, Sass::Script::Value::List]
2447
- # The selector being injected into `$selector`. This can be
2448
- # either a string, a list of strings, or a list of lists of
2449
- # strings as returned by `&`.
2450
- # @return [Sass::Script::Value::List]
2451
- # A list of lists of strings representing the result of the
2452
- # extension. This is in the same format as a selector returned
2453
- # by `&`.
2454
- # @raise [ArgumentError] if the extension fails
2455
- def selector_extend(selector, extendee, extender)
2456
- selector = parse_selector(selector, :selector)
2457
- extendee = parse_selector(extendee, :extendee)
2458
- extender = parse_selector(extender, :extender)
2459
-
2460
- extends = Sass::Util::SubsetMap.new
2461
- begin
2462
- extender.populate_extends(extends, extendee)
2463
- selector.do_extend(extends).to_sass_script
2464
- rescue Sass::SyntaxError => e
2465
- raise ArgumentError.new(e.to_s)
2466
- end
2467
- end
2468
- declare :selector_extend, [:selector, :extendee, :extender]
2469
-
2470
- # Replaces all instances of `$original` with `$replacement` in `$selector`
2471
- #
2472
- # This works by using `@extend` and throwing away the original
2473
- # selector. This means that it can be used to do very advanced
2474
- # replacements; see the examples below.
2475
- #
2476
- # @example
2477
- # selector-replace(".foo .bar", ".bar", ".baz") => ".foo .baz"
2478
- # selector-replace(".foo.bar.baz", ".foo.baz", ".qux") => ".bar.qux"
2479
- #
2480
- # @overload selector_replace($selector, $original, $replacement)
2481
- # @param $selector [Sass::Script::Value::String, Sass::Script::Value::List]
2482
- # The selector within which `$original` is replaced with
2483
- # `$replacement`. This can be either a string, a list of
2484
- # strings, or a list of lists of strings as returned by `&`.
2485
- # @param $original [Sass::Script::Value::String, Sass::Script::Value::List]
2486
- # The selector being replaced. This can be either a string, a
2487
- # list of strings, or a list of lists of strings as returned
2488
- # by `&`.
2489
- # @param $replacement [Sass::Script::Value::String, Sass::Script::Value::List]
2490
- # The selector that `$original` is being replaced with. This
2491
- # can be either a string, a list of strings, or a list of
2492
- # lists of strings as returned by `&`.
2493
- # @return [Sass::Script::Value::List]
2494
- # A list of lists of strings representing the result of the
2495
- # extension. This is in the same format as a selector returned
2496
- # by `&`.
2497
- # @raise [ArgumentError] if the replacement fails
2498
- def selector_replace(selector, original, replacement)
2499
- selector = parse_selector(selector, :selector)
2500
- original = parse_selector(original, :original)
2501
- replacement = parse_selector(replacement, :replacement)
2502
-
2503
- extends = Sass::Util::SubsetMap.new
2504
- begin
2505
- replacement.populate_extends(extends, original)
2506
- selector.do_extend(extends, [], !!:replace).to_sass_script
2507
- rescue Sass::SyntaxError => e
2508
- raise ArgumentError.new(e.to_s)
2509
- end
2510
- end
2511
- declare :selector_replace, [:selector, :original, :replacement]
2512
-
2513
- # Unifies two selectors into a single selector that matches only
2514
- # elements matched by both input selectors. Returns `null` if
2515
- # there is no such selector.
2516
- #
2517
- # Like the selector unification done for `@extend`, this doesn't
2518
- # guarantee that the output selector will match *all* elements
2519
- # matched by both input selectors. For example, if `.a .b` is
2520
- # unified with `.x .y`, `.a .x .b.y, .x .a .b.y` will be returned,
2521
- # but `.a.x .b.y` will not. This avoids exponential output size
2522
- # while matching all elements that are likely to exist in
2523
- # practice.
2524
- #
2525
- # @example
2526
- # selector-unify(".a", ".b") => .a.b
2527
- # selector-unify(".a .b", ".x .y") => .a .x .b.y, .x .a .b.y
2528
- # selector-unify(".a.b", ".b.c") => .a.b.c
2529
- # selector-unify("#a", "#b") => null
2530
- #
2531
- # @overload selector_unify($selector1, $selector2)
2532
- # @param $selector1 [Sass::Script::Value::String, Sass::Script::Value::List]
2533
- # The first selector to be unified. This can be either a
2534
- # string, a list of strings, or a list of lists of strings as
2535
- # returned by `&`.
2536
- # @param $selector2 [Sass::Script::Value::String, Sass::Script::Value::List]
2537
- # The second selector to be unified. This can be either a
2538
- # string, a list of strings, or a list of lists of strings as
2539
- # returned by `&`.
2540
- # @return [Sass::Script::Value::List, Sass::Script::Value::Null]
2541
- # A list of lists of strings representing the result of the
2542
- # unification, or null if no unification exists. This is in
2543
- # the same format as a selector returned by `&`.
2544
- def selector_unify(selector1, selector2)
2545
- selector1 = parse_selector(selector1, :selector1)
2546
- selector2 = parse_selector(selector2, :selector2)
2547
- return null unless (unified = selector1.unify(selector2))
2548
- unified.to_sass_script
2549
- end
2550
- declare :selector_unify, [:selector1, :selector2]
2551
-
2552
- # Returns the [simple
2553
- # selectors](http://dev.w3.org/csswg/selectors4/#simple) that
2554
- # comprise the compound selector `$selector`.
2555
- #
2556
- # Note that `$selector` **must be** a [compound
2557
- # selector](http://dev.w3.org/csswg/selectors4/#compound). That
2558
- # means it cannot contain commas or spaces. It also means that
2559
- # unlike other selector functions, this takes only strings, not
2560
- # lists.
2561
- #
2562
- # @example
2563
- # simple-selectors(".foo.bar") => ".foo", ".bar"
2564
- # simple-selectors(".foo.bar.baz") => ".foo", ".bar", ".baz"
2565
- #
2566
- # @overload simple_selectors($selector)
2567
- # @param $selector [Sass::Script::Value::String]
2568
- # The compound selector whose simple selectors will be extracted.
2569
- # @return [Sass::Script::Value::List]
2570
- # A list of simple selectors in the compound selector.
2571
- def simple_selectors(selector)
2572
- selector = parse_compound_selector(selector, :selector)
2573
- list(selector.members.map {|simple| unquoted_string(simple.to_s)}, :comma)
2574
- end
2575
- declare :simple_selectors, [:selector]
2576
-
2577
- # Returns whether `$super` is a superselector of `$sub`. This means that
2578
- # `$super` matches all the elements that `$sub` matches, as well as possibly
2579
- # additional elements. In general, simpler selectors tend to be
2580
- # superselectors of more complex oned.
2581
- #
2582
- # @example
2583
- # is-superselector(".foo", ".foo.bar") => true
2584
- # is-superselector(".foo.bar", ".foo") => false
2585
- # is-superselector(".bar", ".foo .bar") => true
2586
- # is-superselector(".foo .bar", ".bar") => false
2587
- #
2588
- # @overload is_superselector($super, $sub)
2589
- # @param $super [Sass::Script::Value::String, Sass::Script::Value::List]
2590
- # The potential superselector. This can be either a string, a list of
2591
- # strings, or a list of lists of strings as returned by `&`.
2592
- # @param $sub [Sass::Script::Value::String, Sass::Script::Value::List]
2593
- # The potential subselector. This can be either a string, a list of
2594
- # strings, or a list of lists of strings as returned by `&`.
2595
- # @return [Sass::Script::Value::Bool]
2596
- # Whether `$selector1` is a superselector of `$selector2`.
2597
- def is_superselector(sup, sub)
2598
- sup = parse_selector(sup, :super)
2599
- sub = parse_selector(sub, :sub)
2600
- bool(sup.superselector?(sub))
2601
- end
2602
- declare :is_superselector, [:super, :sub]
2603
-
2604
1521
  private
2605
1522
 
2606
1523
  # This method implements the pattern of transforming a numeric value into
@@ -2608,19 +1525,19 @@ module Sass::Script
2608
1525
  # It yields a number to a block to perform the operation and return a number
2609
1526
  def numeric_transformation(value)
2610
1527
  assert_type value, :Number, :value
2611
- Sass::Script::Value::Number.new(
2612
- yield(value.value), value.numerator_units, value.denominator_units)
1528
+ Sass::Script::Number.new(yield(value.value), value.numerator_units, value.denominator_units)
2613
1529
  end
2614
1530
 
2615
- # @comment
2616
- # rubocop:disable ParameterLists
2617
1531
  def _adjust(color, amount, attr, range, op, units = "")
2618
- # rubocop:enable ParameterLists
2619
1532
  assert_type color, :Color, :color
2620
1533
  assert_type amount, :Number, :amount
2621
1534
  Sass::Util.check_range('Amount', range, amount, units)
2622
1535
 
2623
- color.with(attr => color.send(attr).send(op, amount.value))
1536
+ # TODO: is it worth restricting here,
1537
+ # or should we do so in the Color constructor itself,
1538
+ # and allow clipping in rgb() et al?
1539
+ color.with(attr => Sass::Util.restrict(
1540
+ color.send(attr).send(op, amount.value), range))
2624
1541
  end
2625
1542
  end
2626
1543
  end