sass 3.3.0.alpha.378 → 3.3.0.alpha.380
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.
- 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
|