sass 3.3.0.alpha.378 → 3.3.0.alpha.380
Sign up to get free protection for your applications and to get access to all the features.
- data/REVISION +1 -1
- data/VERSION +1 -1
- data/VERSION_DATE +1 -1
- data/lib/sass/script/parser.rb +9 -10
- data/lib/sass/script/tree/funcall.rb +75 -67
- data/lib/sass/tree/visitors/convert.rb +7 -6
- data/lib/sass/tree/visitors/perform.rb +28 -28
- data/test/sass/conversion_test.rb +4 -0
- data/test/sass/scss/scss_test.rb +210 -0
- metadata +3 -3
data/REVISION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
898bec6bfb7fa4ce8a1ca8e2ff210387c7f98f0e
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.3.0.alpha.
|
1
|
+
3.3.0.alpha.380
|
data/VERSION_DATE
CHANGED
@@ -1 +1 @@
|
|
1
|
-
11 October 2013
|
1
|
+
11 October 2013 22:11:57 GMT
|
data/lib/sass/script/parser.rb
CHANGED
@@ -437,6 +437,7 @@ RUBY
|
|
437
437
|
|
438
438
|
return [args, keywords] unless e
|
439
439
|
|
440
|
+
splat = nil
|
440
441
|
loop do
|
441
442
|
if @lexer.peek && @lexer.peek.type == :colon
|
442
443
|
name = e
|
@@ -450,21 +451,19 @@ RUBY
|
|
450
451
|
|
451
452
|
keywords[name.name] = value
|
452
453
|
else
|
453
|
-
|
454
|
+
if try_tok(:splat)
|
455
|
+
return args, keywords, splat, e if splat
|
456
|
+
splat, e = e, nil
|
457
|
+
elsif splat
|
458
|
+
raise SyntaxError.new("Only keyword arguments may follow variable arguments (...).")
|
459
|
+
elsif !keywords.empty?
|
454
460
|
raise SyntaxError.new("Positional arguments must come before keyword arguments.")
|
455
461
|
end
|
456
462
|
|
457
|
-
if
|
458
|
-
splat = e
|
459
|
-
return args, keywords, splat unless try_tok(:comma)
|
460
|
-
kwarg_splat = assert_expr(subexpr, description)
|
461
|
-
assert_tok(:splat)
|
462
|
-
return args, keywords, splat, kwarg_splat
|
463
|
-
end
|
464
|
-
args << e
|
463
|
+
args << e if e
|
465
464
|
end
|
466
465
|
|
467
|
-
return args, keywords unless try_tok(:comma)
|
466
|
+
return args, keywords, splat unless try_tok(:comma)
|
468
467
|
e = assert_expr(subexpr, description)
|
469
468
|
end
|
470
469
|
end
|
@@ -76,17 +76,18 @@ module Sass::Script::Tree
|
|
76
76
|
sass
|
77
77
|
end
|
78
78
|
|
79
|
-
args = @args.map(&arg_to_sass)
|
79
|
+
args = @args.map(&arg_to_sass)
|
80
80
|
keywords = Sass::Util.hash_to_a(@keywords.as_stored).
|
81
|
-
map {|k, v| "$#{dasherize(k, opts)}: #{arg_to_sass[v]}"}
|
81
|
+
map {|k, v| "$#{dasherize(k, opts)}: #{arg_to_sass[v]}"}
|
82
|
+
|
82
83
|
# rubocop:disable RedundantSelf
|
83
84
|
if self.splat
|
84
|
-
splat =
|
85
|
-
|
86
|
-
splat = "#{splat}, #{arg_to_sass[kwarg_splat]}..." if kwarg_splat
|
85
|
+
splat = "#{arg_to_sass[self.splat]}..."
|
86
|
+
kwarg_splat = "#{arg_to_sass[self.kwarg_splat]}..." if self.kwarg_splat
|
87
87
|
end
|
88
88
|
# rubocop:enable RedundantSelf
|
89
|
-
|
89
|
+
|
90
|
+
arglist = [args, splat, keywords, kwarg_splat].flatten.compact.join(', ')
|
90
91
|
"#{dasherize(name, opts)}(#{arglist})"
|
91
92
|
end
|
92
93
|
|
@@ -121,16 +122,16 @@ module Sass::Script::Tree
|
|
121
122
|
def _perform(environment)
|
122
123
|
args = Sass::Util.enum_with_index(@args).
|
123
124
|
map {|a, i| perform_arg(a, environment, signature && signature.args[i])}
|
124
|
-
splat = Sass::Tree::Visitors::Perform.perform_splat(@splat, @kwarg_splat, environment)
|
125
125
|
keywords = Sass::Util.map_hash(@keywords) do |k, v|
|
126
126
|
[k, perform_arg(v, environment, k.tr('-', '_'))]
|
127
127
|
end
|
128
|
+
splat = Sass::Tree::Visitors::Perform.perform_splat(
|
129
|
+
@splat, keywords, @kwarg_splat, environment)
|
128
130
|
if (fn = environment.function(@name))
|
129
|
-
return perform_sass_fn(fn, args,
|
131
|
+
return perform_sass_fn(fn, args, splat, environment)
|
130
132
|
end
|
131
133
|
|
132
|
-
|
133
|
-
args = construct_ruby_args(ruby_name, args, keywords, splat, environment)
|
134
|
+
args = construct_ruby_args(ruby_name, args, splat, environment)
|
134
135
|
|
135
136
|
if Sass::Script::Functions.callable?(ruby_name)
|
136
137
|
local_environment = Sass::Environment.new(environment.global_env, environment.options)
|
@@ -141,54 +142,7 @@ module Sass::Script::Tree
|
|
141
142
|
opts(to_literal(args))
|
142
143
|
end
|
143
144
|
rescue ArgumentError => e
|
144
|
-
|
145
|
-
|
146
|
-
# If this is a legitimate Ruby-raised argument error, re-raise it.
|
147
|
-
# Otherwise, it's an error in the user's stylesheet, so wrap it.
|
148
|
-
if Sass::Util.rbx?
|
149
|
-
# Rubinius has a different error report string than vanilla Ruby. It
|
150
|
-
# also doesn't put the actual method for which the argument error was
|
151
|
-
# thrown in the backtrace, nor does it include `send`, so we look for
|
152
|
-
# `_perform`.
|
153
|
-
if e.message =~ /^method '([^']+)': given (\d+), expected (\d+)/
|
154
|
-
error_name, given, expected = $1, $2, $3
|
155
|
-
raise e if error_name != ruby_name || e.backtrace[0] !~ /:in `_perform'$/
|
156
|
-
message = "wrong number of arguments (#{given} for #{expected})"
|
157
|
-
end
|
158
|
-
elsif Sass::Util.jruby?
|
159
|
-
if Sass::Util.jruby1_6?
|
160
|
-
should_maybe_raise = e.message =~ /^wrong number of arguments \((\d+) for (\d+)\)/ &&
|
161
|
-
# The one case where JRuby does include the Ruby name of the function
|
162
|
-
# is manually-thrown ArgumentErrors, which are indistinguishable from
|
163
|
-
# legitimate ArgumentErrors. We treat both of these as
|
164
|
-
# Sass::SyntaxErrors even though it can hide Ruby errors.
|
165
|
-
e.backtrace[0] !~ /:in `(block in )?#{ruby_name}'$/
|
166
|
-
else
|
167
|
-
should_maybe_raise =
|
168
|
-
e.message =~ /^wrong number of arguments calling `[^`]+` \((\d+) for (\d+)\)/
|
169
|
-
given, expected = $1, $2
|
170
|
-
end
|
171
|
-
|
172
|
-
if should_maybe_raise
|
173
|
-
# JRuby 1.7 includes __send__ before send and _perform.
|
174
|
-
trace = e.backtrace.dup
|
175
|
-
raise e if !Sass::Util.jruby1_6? && trace.shift !~ /:in `__send__'$/
|
176
|
-
|
177
|
-
# JRuby (as of 1.7.2) doesn't put the actual method
|
178
|
-
# for which the argument error was thrown in the backtrace, so we
|
179
|
-
# detect whether our send threw an argument error.
|
180
|
-
if !(trace[0] =~ /:in `send'$/ && trace[1] =~ /:in `_perform'$/)
|
181
|
-
raise e
|
182
|
-
elsif !Sass::Util.jruby1_6?
|
183
|
-
# JRuby 1.7 doesn't use standard formatting for its ArgumentErrors.
|
184
|
-
message = "wrong number of arguments (#{given} for #{expected})"
|
185
|
-
end
|
186
|
-
end
|
187
|
-
elsif e.message =~ /^wrong number of arguments \(\d+ for \d+\)/ &&
|
188
|
-
e.backtrace[0] !~ /:in `(block in )?#{ruby_name}'$/
|
189
|
-
raise e
|
190
|
-
end
|
191
|
-
raise Sass::SyntaxError.new("#{message} for `#{name}'")
|
145
|
+
reformat_argument_error(e)
|
192
146
|
end
|
193
147
|
|
194
148
|
# Compass historically overrode this before it changed name to {Funcall#to_value}.
|
@@ -206,6 +160,10 @@ module Sass::Script::Tree
|
|
206
160
|
|
207
161
|
private
|
208
162
|
|
163
|
+
def ruby_name
|
164
|
+
@ruby_name ||= @name.tr('-', '_')
|
165
|
+
end
|
166
|
+
|
209
167
|
def perform_arg(argument, environment, name)
|
210
168
|
return argument if signature && signature.delayed_args.include?(name)
|
211
169
|
argument.perform(environment)
|
@@ -215,15 +173,14 @@ module Sass::Script::Tree
|
|
215
173
|
@signature ||= Sass::Script::Functions.signature(name.to_sym, @args.size, @keywords.size)
|
216
174
|
end
|
217
175
|
|
218
|
-
def construct_ruby_args(name, args,
|
176
|
+
def construct_ruby_args(name, args, splat, environment)
|
219
177
|
args += splat.to_a if splat
|
220
178
|
|
221
|
-
#
|
222
|
-
if
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
end
|
179
|
+
# All keywords are contained in splat.keywords for consistency,
|
180
|
+
# even if there were no splats passed in.
|
181
|
+
old_keywords_accessed = splat.keywords_accessed
|
182
|
+
keywords = splat.keywords
|
183
|
+
splat.keywords_accessed = old_keywords_accessed
|
227
184
|
|
228
185
|
unless (signature = Sass::Script::Functions.signature(name.to_sym, args.size, keywords.size))
|
229
186
|
return args if keywords.empty?
|
@@ -267,8 +224,8 @@ module Sass::Script::Tree
|
|
267
224
|
args
|
268
225
|
end
|
269
226
|
|
270
|
-
def perform_sass_fn(function, args,
|
271
|
-
Sass::Tree::Visitors::Perform.perform_arguments(function, args,
|
227
|
+
def perform_sass_fn(function, args, splat, environment)
|
228
|
+
Sass::Tree::Visitors::Perform.perform_arguments(function, args, splat) do |env|
|
272
229
|
env.caller = Sass::Environment.new(environment)
|
273
230
|
|
274
231
|
val = catch :_sass_return do
|
@@ -278,5 +235,56 @@ module Sass::Script::Tree
|
|
278
235
|
val
|
279
236
|
end
|
280
237
|
end
|
238
|
+
|
239
|
+
def reformat_argument_error(e)
|
240
|
+
message = e.message
|
241
|
+
|
242
|
+
# If this is a legitimate Ruby-raised argument error, re-raise it.
|
243
|
+
# Otherwise, it's an error in the user's stylesheet, so wrap it.
|
244
|
+
if Sass::Util.rbx?
|
245
|
+
# Rubinius has a different error report string than vanilla Ruby. It
|
246
|
+
# also doesn't put the actual method for which the argument error was
|
247
|
+
# thrown in the backtrace, nor does it include `send`, so we look for
|
248
|
+
# `_perform`.
|
249
|
+
if e.message =~ /^method '([^']+)': given (\d+), expected (\d+)/
|
250
|
+
error_name, given, expected = $1, $2, $3
|
251
|
+
raise e if error_name != ruby_name || e.backtrace[0] !~ /:in `_perform'$/
|
252
|
+
message = "wrong number of arguments (#{given} for #{expected})"
|
253
|
+
end
|
254
|
+
elsif Sass::Util.jruby?
|
255
|
+
if Sass::Util.jruby1_6?
|
256
|
+
should_maybe_raise = e.message =~ /^wrong number of arguments \((\d+) for (\d+)\)/ &&
|
257
|
+
# The one case where JRuby does include the Ruby name of the function
|
258
|
+
# is manually-thrown ArgumentErrors, which are indistinguishable from
|
259
|
+
# legitimate ArgumentErrors. We treat both of these as
|
260
|
+
# Sass::SyntaxErrors even though it can hide Ruby errors.
|
261
|
+
e.backtrace[0] !~ /:in `(block in )?#{ruby_name}'$/
|
262
|
+
else
|
263
|
+
should_maybe_raise =
|
264
|
+
e.message =~ /^wrong number of arguments calling `[^`]+` \((\d+) for (\d+)\)/
|
265
|
+
given, expected = $1, $2
|
266
|
+
end
|
267
|
+
|
268
|
+
if should_maybe_raise
|
269
|
+
# JRuby 1.7 includes __send__ before send and _perform.
|
270
|
+
trace = e.backtrace.dup
|
271
|
+
raise e if !Sass::Util.jruby1_6? && trace.shift !~ /:in `__send__'$/
|
272
|
+
|
273
|
+
# JRuby (as of 1.7.2) doesn't put the actual method
|
274
|
+
# for which the argument error was thrown in the backtrace, so we
|
275
|
+
# detect whether our send threw an argument error.
|
276
|
+
if !(trace[0] =~ /:in `send'$/ && trace[1] =~ /:in `_perform'$/)
|
277
|
+
raise e
|
278
|
+
elsif !Sass::Util.jruby1_6?
|
279
|
+
# JRuby 1.7 doesn't use standard formatting for its ArgumentErrors.
|
280
|
+
message = "wrong number of arguments (#{given} for #{expected})"
|
281
|
+
end
|
282
|
+
end
|
283
|
+
elsif e.message =~ /^wrong number of arguments \(\d+ for \d+\)/ &&
|
284
|
+
e.backtrace[0] !~ /:in `(block in )?#{ruby_name}'$/
|
285
|
+
raise e
|
286
|
+
end
|
287
|
+
raise Sass::SyntaxError.new("#{message} for `#{name}'")
|
288
|
+
end
|
281
289
|
end
|
282
290
|
end
|
@@ -206,15 +206,16 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
206
206
|
end
|
207
207
|
|
208
208
|
unless node.args.empty? && node.keywords.empty? && node.splat.nil?
|
209
|
-
args = node.args.map(&arg_to_sass)
|
209
|
+
args = node.args.map(&arg_to_sass)
|
210
210
|
keywords = Sass::Util.hash_to_a(node.keywords).
|
211
|
-
map {|k, v| "$#{dasherize(k)}: #{arg_to_sass[v]}"}
|
211
|
+
map {|k, v| "$#{dasherize(k)}: #{arg_to_sass[v]}"}
|
212
|
+
|
212
213
|
if node.splat
|
213
|
-
splat =
|
214
|
-
|
215
|
-
splat = "#{splat}, #{node.kwarg_splat.inspect}..." if node.kwarg_splat
|
214
|
+
splat = "#{arg_to_sass[node.splat]}..."
|
215
|
+
kwarg_splat = "#{arg_to_sass[node.kwarg_splat]}..." if node.kwarg_splat
|
216
216
|
end
|
217
|
-
|
217
|
+
|
218
|
+
arglist = "(#{[args, splat, keywords, kwarg_splat].flatten.compact.join(', ')})"
|
218
219
|
end
|
219
220
|
"#{tab_str}#{@format == :sass ? '+' : '@include '}" +
|
220
221
|
"#{dasherize(node.name)}#{arglist}#{node.has_children ? yield : semi}\n"
|
@@ -11,16 +11,15 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
|
|
11
11
|
# @api private
|
12
12
|
# @comment
|
13
13
|
# rubocop:disable MethodLength
|
14
|
-
def perform_arguments(callable, args,
|
14
|
+
def perform_arguments(callable, args, splat)
|
15
15
|
desc = "#{callable.type.capitalize} #{callable.name}"
|
16
16
|
downcase_desc = "#{callable.type} #{callable.name}"
|
17
17
|
|
18
|
-
#
|
19
|
-
if
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
18
|
+
# All keywords are contained in splat.keywords for consistency,
|
19
|
+
# even if there were no splats passed in.
|
20
|
+
old_keywords_accessed = splat.keywords_accessed
|
21
|
+
keywords = splat.keywords
|
22
|
+
splat.keywords_accessed = old_keywords_accessed
|
24
23
|
|
25
24
|
begin
|
26
25
|
unless keywords.empty?
|
@@ -99,33 +98,34 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
|
|
99
98
|
|
100
99
|
# @api private
|
101
100
|
# @return [Sass::Script::Value::ArgList]
|
102
|
-
def perform_splat(splat, kwarg_splat, environment)
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
101
|
+
def perform_splat(splat, performed_keywords, kwarg_splat, environment)
|
102
|
+
args, kwargs, separator = [], Sass::Util.ordered_hash, :comma
|
103
|
+
|
104
|
+
if splat
|
105
|
+
splat = splat.perform(environment)
|
106
|
+
separator = splat.separator || separator
|
107
|
+
if splat.is_a?(Sass::Script::Value::ArgList)
|
108
|
+
args = splat.to_a
|
109
|
+
kwargs = splat.keywords
|
110
|
+
elsif splat.is_a?(Sass::Script::Value::Map)
|
109
111
|
kwargs = arg_hash(splat)
|
110
112
|
else
|
111
113
|
args = splat.to_a
|
112
|
-
kwargs = {}
|
113
114
|
end
|
114
|
-
return Sass::Script::Value::ArgList.new(args, kwargs, splat.separator || :comma)
|
115
115
|
end
|
116
116
|
|
117
|
-
|
118
|
-
unless kwarg_splat.is_a?(Sass::Script::Value::Map)
|
119
|
-
raise Sass::SyntaxError.new("Variable keyword arguments must be a map " +
|
120
|
-
"(was #{kwarg_splat.inspect}).")
|
121
|
-
end
|
117
|
+
kwargs = kwargs.merge(performed_keywords)
|
122
118
|
|
123
|
-
if
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
119
|
+
if kwarg_splat
|
120
|
+
kwarg_splat = kwarg_splat.perform(environment)
|
121
|
+
unless kwarg_splat.is_a?(Sass::Script::Value::Map)
|
122
|
+
raise Sass::SyntaxError.new("Variable keyword arguments must be a map " +
|
123
|
+
"(was #{kwarg_splat.inspect}).")
|
124
|
+
end
|
125
|
+
kwargs = kwargs.merge(arg_hash(kwarg_splat))
|
128
126
|
end
|
127
|
+
|
128
|
+
Sass::Script::Value::ArgList.new(args, kwargs, separator)
|
129
129
|
end
|
130
130
|
|
131
131
|
private
|
@@ -326,9 +326,9 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
|
|
326
326
|
|
327
327
|
args = node.args.map {|a| a.perform(@environment)}
|
328
328
|
keywords = Sass::Util.map_hash(node.keywords) {|k, v| [k, v.perform(@environment)]}
|
329
|
-
splat = self.class.perform_splat(node.splat, node.kwarg_splat, @environment)
|
329
|
+
splat = self.class.perform_splat(node.splat, keywords, node.kwarg_splat, @environment)
|
330
330
|
|
331
|
-
self.class.perform_arguments(mixin, args,
|
331
|
+
self.class.perform_arguments(mixin, args, splat) do |env|
|
332
332
|
env.caller = Sass::Environment.new(@environment)
|
333
333
|
env.content = [node.children, @environment] if node.has_children
|
334
334
|
|
@@ -1629,6 +1629,7 @@ SCSS
|
|
1629
1629
|
|
1630
1630
|
.foo
|
1631
1631
|
+foo($list..., $map...)
|
1632
|
+
+foo(pos, $list..., $kwd: val, $map...)
|
1632
1633
|
SASS
|
1633
1634
|
@mixin foo($a: b, $c: d) {
|
1634
1635
|
a: $a;
|
@@ -1637,6 +1638,7 @@ SASS
|
|
1637
1638
|
|
1638
1639
|
.foo {
|
1639
1640
|
@include foo($list..., $map...);
|
1641
|
+
@include foo(pos, $list..., $kwd: val, $map...);
|
1640
1642
|
}
|
1641
1643
|
SCSS
|
1642
1644
|
end
|
@@ -1675,6 +1677,7 @@ SCSS
|
|
1675
1677
|
|
1676
1678
|
.foo
|
1677
1679
|
a: foo($list..., $map...)
|
1680
|
+
b: foo(pos, $list..., $kwd: val, $map...)
|
1678
1681
|
SASS
|
1679
1682
|
@function foo($a: b, $c: d) {
|
1680
1683
|
@return foo;
|
@@ -1682,6 +1685,7 @@ SASS
|
|
1682
1685
|
|
1683
1686
|
.foo {
|
1684
1687
|
a: foo($list..., $map...);
|
1688
|
+
b: foo(pos, $list..., $kwd: val, $map...);
|
1685
1689
|
}
|
1686
1690
|
SCSS
|
1687
1691
|
end
|
data/test/sass/scss/scss_test.rb
CHANGED
@@ -1074,6 +1074,108 @@ CSS
|
|
1074
1074
|
SCSS
|
1075
1075
|
end
|
1076
1076
|
|
1077
|
+
def test_mixin_splat_after_keyword_args
|
1078
|
+
assert_equal <<CSS, render(<<SCSS)
|
1079
|
+
.foo {
|
1080
|
+
a: 1;
|
1081
|
+
b: 2;
|
1082
|
+
c: 3; }
|
1083
|
+
CSS
|
1084
|
+
@mixin foo($a, $b, $c) {
|
1085
|
+
a: 1;
|
1086
|
+
b: 2;
|
1087
|
+
c: 3;
|
1088
|
+
}
|
1089
|
+
|
1090
|
+
.foo {
|
1091
|
+
@include foo(1, $c: 3, 2...);
|
1092
|
+
}
|
1093
|
+
SCSS
|
1094
|
+
end
|
1095
|
+
|
1096
|
+
def test_mixin_keyword_args_after_splat
|
1097
|
+
assert_equal <<CSS, render(<<SCSS)
|
1098
|
+
.foo {
|
1099
|
+
a: 1;
|
1100
|
+
b: 2;
|
1101
|
+
c: 3; }
|
1102
|
+
CSS
|
1103
|
+
@mixin foo($a, $b, $c) {
|
1104
|
+
a: 1;
|
1105
|
+
b: 2;
|
1106
|
+
c: 3;
|
1107
|
+
}
|
1108
|
+
|
1109
|
+
.foo {
|
1110
|
+
@include foo(1, 2..., $c: 3);
|
1111
|
+
}
|
1112
|
+
SCSS
|
1113
|
+
end
|
1114
|
+
|
1115
|
+
def test_mixin_keyword_splat_after_keyword_args
|
1116
|
+
assert_equal <<CSS, render(<<SCSS)
|
1117
|
+
.foo {
|
1118
|
+
a: 1;
|
1119
|
+
b: 2;
|
1120
|
+
c: 3; }
|
1121
|
+
CSS
|
1122
|
+
@mixin foo($a, $b, $c) {
|
1123
|
+
a: 1;
|
1124
|
+
b: 2;
|
1125
|
+
c: 3;
|
1126
|
+
}
|
1127
|
+
|
1128
|
+
.foo {
|
1129
|
+
@include foo(1, $b: 2, (c: 3)...);
|
1130
|
+
}
|
1131
|
+
SCSS
|
1132
|
+
end
|
1133
|
+
|
1134
|
+
def test_mixin_triple_keyword_splat_merge
|
1135
|
+
assert_equal <<CSS, render(<<SCSS)
|
1136
|
+
.foo {
|
1137
|
+
foo: 1;
|
1138
|
+
bar: 2;
|
1139
|
+
kwarg: 3;
|
1140
|
+
a: 3;
|
1141
|
+
b: 2;
|
1142
|
+
c: 3; }
|
1143
|
+
CSS
|
1144
|
+
@mixin foo($foo, $bar, $kwarg, $a, $b, $c) {
|
1145
|
+
foo: $foo;
|
1146
|
+
bar: $bar;
|
1147
|
+
kwarg: $kwarg;
|
1148
|
+
a: $a;
|
1149
|
+
b: $b;
|
1150
|
+
c: $c;
|
1151
|
+
}
|
1152
|
+
|
1153
|
+
@mixin bar($args...) {
|
1154
|
+
@include foo($args..., $bar: 2, $a: 2, $b: 2, (kwarg: 3, a: 3, c: 3)...);
|
1155
|
+
}
|
1156
|
+
|
1157
|
+
.foo {
|
1158
|
+
@include bar($foo: 1, $a: 1, $b: 1, $c: 1);
|
1159
|
+
}
|
1160
|
+
SCSS
|
1161
|
+
end
|
1162
|
+
|
1163
|
+
def test_mixin_conflicting_splat_after_keyword_args
|
1164
|
+
assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
|
1165
|
+
Mixin foo was passed argument $b both by position and by name.
|
1166
|
+
MESSAGE
|
1167
|
+
@mixin foo($a, $b, $c) {
|
1168
|
+
a: 1;
|
1169
|
+
b: 2;
|
1170
|
+
c: 3;
|
1171
|
+
}
|
1172
|
+
|
1173
|
+
.foo {
|
1174
|
+
@include foo(1, $b: 2, 3...);
|
1175
|
+
}
|
1176
|
+
SCSS
|
1177
|
+
end
|
1178
|
+
|
1077
1179
|
def test_mixin_keyword_splat_must_have_string_keys
|
1078
1180
|
assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
|
1079
1181
|
Variable keyword argument map must have string keys.
|
@@ -1087,6 +1189,22 @@ MESSAGE
|
|
1087
1189
|
SCSS
|
1088
1190
|
end
|
1089
1191
|
|
1192
|
+
def test_mixin_positional_arg_after_splat
|
1193
|
+
assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
|
1194
|
+
Only keyword arguments may follow variable arguments (...).
|
1195
|
+
MESSAGE
|
1196
|
+
@mixin foo($a, $b, $c) {
|
1197
|
+
a: 1;
|
1198
|
+
b: 2;
|
1199
|
+
c: 3;
|
1200
|
+
}
|
1201
|
+
|
1202
|
+
.foo {
|
1203
|
+
@include foo(1, 2..., 3);
|
1204
|
+
}
|
1205
|
+
SCSS
|
1206
|
+
end
|
1207
|
+
|
1090
1208
|
def test_mixin_var_args_with_keyword
|
1091
1209
|
assert_raise_message(Sass::SyntaxError, "Positional arguments must come before keyword arguments.") {render <<SCSS}
|
1092
1210
|
@mixin foo($a, $b...) {
|
@@ -1397,6 +1515,98 @@ CSS
|
|
1397
1515
|
SCSS
|
1398
1516
|
end
|
1399
1517
|
|
1518
|
+
def test_function_splat_after_keyword_args
|
1519
|
+
assert_equal <<CSS, render(<<SCSS)
|
1520
|
+
.foo {
|
1521
|
+
val: "a: 1, b: 2, c: 3"; }
|
1522
|
+
CSS
|
1523
|
+
@function foo($a, $b, $c) {
|
1524
|
+
@return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
|
1525
|
+
}
|
1526
|
+
|
1527
|
+
.foo {
|
1528
|
+
val: foo(1, $c: 3, 2...);
|
1529
|
+
}
|
1530
|
+
SCSS
|
1531
|
+
end
|
1532
|
+
|
1533
|
+
def test_function_keyword_args_after_splat
|
1534
|
+
assert_equal <<CSS, render(<<SCSS)
|
1535
|
+
.foo {
|
1536
|
+
val: "a: 1, b: 2, c: 3"; }
|
1537
|
+
CSS
|
1538
|
+
@function foo($a, $b, $c) {
|
1539
|
+
@return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
|
1540
|
+
}
|
1541
|
+
|
1542
|
+
.foo {
|
1543
|
+
val: foo(1, 2..., $c: 3);
|
1544
|
+
}
|
1545
|
+
SCSS
|
1546
|
+
end
|
1547
|
+
|
1548
|
+
def test_function_keyword_splat_after_keyword_args
|
1549
|
+
assert_equal <<CSS, render(<<SCSS)
|
1550
|
+
.foo {
|
1551
|
+
val: "a: 1, b: 2, c: 3"; }
|
1552
|
+
CSS
|
1553
|
+
@function foo($a, $b, $c) {
|
1554
|
+
@return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
|
1555
|
+
}
|
1556
|
+
|
1557
|
+
.foo {
|
1558
|
+
val: foo(1, $b: 2, (c: 3)...);
|
1559
|
+
}
|
1560
|
+
SCSS
|
1561
|
+
end
|
1562
|
+
|
1563
|
+
def test_function_triple_keyword_splat_merge
|
1564
|
+
assert_equal <<CSS, render(<<SCSS)
|
1565
|
+
.foo {
|
1566
|
+
val: "foo: 1, bar: 2, kwarg: 3, a: 3, b: 2, c: 3"; }
|
1567
|
+
CSS
|
1568
|
+
@function foo($foo, $bar, $kwarg, $a, $b, $c) {
|
1569
|
+
@return "foo: \#{$foo}, bar: \#{$bar}, kwarg: \#{$kwarg}, a: \#{$a}, b: \#{$b}, c: \#{$c}";
|
1570
|
+
}
|
1571
|
+
|
1572
|
+
@function bar($args...) {
|
1573
|
+
@return foo($args..., $bar: 2, $a: 2, $b: 2, (kwarg: 3, a: 3, c: 3)...);
|
1574
|
+
}
|
1575
|
+
|
1576
|
+
.foo {
|
1577
|
+
val: bar($foo: 1, $a: 1, $b: 1, $c: 1);
|
1578
|
+
}
|
1579
|
+
SCSS
|
1580
|
+
end
|
1581
|
+
|
1582
|
+
def test_function_conflicting_splat_after_keyword_args
|
1583
|
+
assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
|
1584
|
+
Function foo was passed argument $b both by position and by name.
|
1585
|
+
MESSAGE
|
1586
|
+
@function foo($a, $b, $c) {
|
1587
|
+
@return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
|
1588
|
+
}
|
1589
|
+
|
1590
|
+
.foo {
|
1591
|
+
val: foo(1, $b: 2, 3...);
|
1592
|
+
}
|
1593
|
+
SCSS
|
1594
|
+
end
|
1595
|
+
|
1596
|
+
def test_function_positional_arg_after_splat
|
1597
|
+
assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
|
1598
|
+
Only keyword arguments may follow variable arguments (...).
|
1599
|
+
MESSAGE
|
1600
|
+
@function foo($a, $b, $c) {
|
1601
|
+
@return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
|
1602
|
+
}
|
1603
|
+
|
1604
|
+
.foo {
|
1605
|
+
val: foo(1, 2..., 3);
|
1606
|
+
}
|
1607
|
+
SCSS
|
1608
|
+
end
|
1609
|
+
|
1400
1610
|
def test_function_var_args_with_keyword
|
1401
1611
|
assert_raise_message(Sass::SyntaxError, "Positional arguments must come before keyword arguments.") {render <<SCSS}
|
1402
1612
|
@function foo($a, $b...) {
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sass
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 592302581
|
5
5
|
prerelease: 6
|
6
6
|
segments:
|
7
7
|
- 3
|
8
8
|
- 3
|
9
9
|
- 0
|
10
10
|
- alpha
|
11
|
-
-
|
12
|
-
version: 3.3.0.alpha.
|
11
|
+
- 380
|
12
|
+
version: 3.3.0.alpha.380
|
13
13
|
platform: ruby
|
14
14
|
authors:
|
15
15
|
- Nathan Weizenbaum
|