sass 3.1.0.alpha.15 → 3.1.0.alpha.16
Sign up to get free protection for your applications and to get access to all the features.
- data/EDGE_GEM_VERSION +1 -1
- data/VERSION +1 -1
- data/lib/sass/engine.rb +2 -2
- data/lib/sass/script/funcall.rb +49 -8
- data/lib/sass/script/functions.rb +189 -57
- data/lib/sass/script/node.rb +7 -1
- data/lib/sass/script/parser.rb +52 -17
- data/lib/sass/script/variable.rb +6 -0
- data/lib/sass/scss/parser.rb +2 -2
- data/lib/sass/tree/mixin_node.rb +25 -5
- data/test/sass/conversion_test.rb +14 -0
- data/test/sass/engine_test.rb +75 -0
- data/test/sass/functions_test.rb +87 -0
- data/test/sass/script_conversion_test.rb +5 -0
- data/test/sass/scss/scss_test.rb +63 -0
- metadata +2 -2
data/lib/sass/script/node.rb
CHANGED
@@ -32,7 +32,13 @@ module Sass::Script
|
|
32
32
|
# @param options [{Symbol => Object}] The options
|
33
33
|
def options=(options)
|
34
34
|
@options = options
|
35
|
-
children.each
|
35
|
+
children.each do |c|
|
36
|
+
if c.is_a? Hash
|
37
|
+
c.values.each {|v| v.options = options }
|
38
|
+
else
|
39
|
+
c.options = options
|
40
|
+
end
|
41
|
+
end
|
36
42
|
end
|
37
43
|
|
38
44
|
# Sets the context for this node,
|
data/lib/sass/script/parser.rb
CHANGED
@@ -74,19 +74,21 @@ module Sass
|
|
74
74
|
|
75
75
|
# Parses the argument list for a mixin include.
|
76
76
|
#
|
77
|
-
# @return [Array<Script::Node
|
77
|
+
# @return [(Array<Script::Node>, {String => Script::Note})]
|
78
|
+
# The root nodes of the arguments.
|
79
|
+
# Keyword arguments are in a hash from names to values.
|
78
80
|
# @raise [Sass::SyntaxError] if the argument list isn't valid SassScript
|
79
81
|
def parse_mixin_include_arglist
|
80
|
-
args = []
|
81
|
-
|
82
|
+
args, keywords = [], {}
|
82
83
|
if try_tok(:lparen)
|
83
|
-
args =
|
84
|
+
args, keywords = mixin_arglist || [[], {}]
|
84
85
|
assert_tok(:rparen)
|
85
86
|
end
|
86
87
|
assert_done
|
87
88
|
|
88
89
|
args.each {|a| a.options = @options}
|
89
|
-
|
90
|
+
keywords.each {|k, v| v.options = @options}
|
91
|
+
return args, keywords
|
90
92
|
rescue Sass::SyntaxError => e
|
91
93
|
e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
|
92
94
|
raise e
|
@@ -254,9 +256,9 @@ RUBY
|
|
254
256
|
|
255
257
|
def funcall
|
256
258
|
return raw unless tok = try_tok(:funcall)
|
257
|
-
args = fn_arglist || []
|
259
|
+
args, keywords = fn_arglist || [[], {}]
|
258
260
|
assert_tok(:rparen)
|
259
|
-
node(Script::Funcall.new(tok.value, args))
|
261
|
+
node(Script::Funcall.new(tok.value, args, keywords))
|
260
262
|
end
|
261
263
|
|
262
264
|
def defn_arglist!(must_have_default)
|
@@ -289,15 +291,48 @@ RUBY
|
|
289
291
|
end
|
290
292
|
|
291
293
|
def fn_arglist
|
292
|
-
|
293
|
-
|
294
|
-
|
294
|
+
arglist(:fn_arglist, :equals)
|
295
|
+
end
|
296
|
+
|
297
|
+
def mixin_arglist
|
298
|
+
arglist(:mixin_arglist, :interpolation)
|
299
|
+
end
|
300
|
+
|
301
|
+
def arglist(type, subexpr)
|
302
|
+
return unless e = send(subexpr)
|
303
|
+
if @lexer.peek && @lexer.peek.type == :colon
|
304
|
+
name = e
|
305
|
+
@lexer.expected!("comma") unless name.is_a?(Variable)
|
306
|
+
assert_tok(:colon)
|
307
|
+
keywords = {name.underscored_name => assert_expr(subexpr, EXPR_NAMES[type])}
|
308
|
+
end
|
309
|
+
|
310
|
+
unless try_tok(:comma)
|
311
|
+
return [], keywords if keywords
|
312
|
+
return [e], {}
|
313
|
+
end
|
314
|
+
|
315
|
+
other_args, other_keywords = assert_expr(type)
|
316
|
+
if keywords
|
317
|
+
if other_keywords[name.underscored_name]
|
318
|
+
raise SyntaxError.new("Keyword argument \"#{name.to_sass}\" passed more than once")
|
319
|
+
end
|
320
|
+
return other_args, keywords.merge(other_keywords)
|
321
|
+
else
|
322
|
+
return [e, *other_args], other_keywords
|
323
|
+
end
|
295
324
|
end
|
296
325
|
|
297
|
-
def
|
298
|
-
return unless
|
299
|
-
|
300
|
-
|
326
|
+
def keyword_arglist
|
327
|
+
return unless var = try_tok(:const)
|
328
|
+
unless try_tok(:colon)
|
329
|
+
return_tok!
|
330
|
+
return
|
331
|
+
end
|
332
|
+
name = var[1]
|
333
|
+
value = interpolation
|
334
|
+
return {name => value} unless try_tok(:comma)
|
335
|
+
{name => value}.merge(assert_expr(:keyword_arglist))
|
301
336
|
end
|
302
337
|
|
303
338
|
def raw
|
@@ -359,13 +394,13 @@ RUBY
|
|
359
394
|
EXPR_NAMES = {
|
360
395
|
:string => "string",
|
361
396
|
:default => "expression (e.g. 1px, bold)",
|
362
|
-
:
|
397
|
+
:mixin_arglist => "mixin argument",
|
363
398
|
:fn_arglist => "function argument",
|
364
399
|
}
|
365
400
|
|
366
|
-
def assert_expr(name)
|
401
|
+
def assert_expr(name, expected = nil)
|
367
402
|
(e = send(name)) && (return e)
|
368
|
-
@lexer.expected!(EXPR_NAMES[name] || EXPR_NAMES[:default])
|
403
|
+
@lexer.expected!(expected || EXPR_NAMES[name] || EXPR_NAMES[:default])
|
369
404
|
end
|
370
405
|
|
371
406
|
def assert_tok(*names)
|
data/lib/sass/script/variable.rb
CHANGED
@@ -7,9 +7,15 @@ module Sass
|
|
7
7
|
# @return [String]
|
8
8
|
attr_reader :name
|
9
9
|
|
10
|
+
# The underscored name of the variable.
|
11
|
+
#
|
12
|
+
# @return [String]
|
13
|
+
attr_reader :underscored_name
|
14
|
+
|
10
15
|
# @param name [String] See \{#name}
|
11
16
|
def initialize(name)
|
12
17
|
@name = name
|
18
|
+
@underscored_name = name.gsub(/-/,"_")
|
13
19
|
super()
|
14
20
|
end
|
15
21
|
|
data/lib/sass/scss/parser.rb
CHANGED
@@ -138,9 +138,9 @@ module Sass
|
|
138
138
|
|
139
139
|
def include_directive
|
140
140
|
name = tok! IDENT
|
141
|
-
args = sass_script(:parse_mixin_include_arglist)
|
141
|
+
args, keywords = sass_script(:parse_mixin_include_arglist)
|
142
142
|
ss
|
143
|
-
node(Sass::Tree::MixinNode.new(name, args))
|
143
|
+
node(Sass::Tree::MixinNode.new(name, args, keywords))
|
144
144
|
end
|
145
145
|
|
146
146
|
def debug_directive
|
data/lib/sass/tree/mixin_node.rb
CHANGED
@@ -11,13 +11,16 @@ module Sass::Tree
|
|
11
11
|
def options=(opts)
|
12
12
|
super
|
13
13
|
@args.each {|a| a.context = :equals} if opts[:sass2]
|
14
|
+
@keywords.each {|k, v| v.context = :equals} if opts[:sass2]
|
14
15
|
end
|
15
16
|
|
16
17
|
# @param name [String] The name of the mixin
|
17
18
|
# @param args [Array<Script::Node>] The arguments to the mixin
|
18
|
-
|
19
|
+
# @param keywords [{String => Script::Node}] A hash from keyword argument names to values
|
20
|
+
def initialize(name, args, keywords)
|
19
21
|
@name = name
|
20
22
|
@args = args
|
23
|
+
@keywords = keywords
|
21
24
|
super()
|
22
25
|
end
|
23
26
|
|
@@ -42,8 +45,12 @@ module Sass::Tree
|
|
42
45
|
|
43
46
|
# @see Node#to_src
|
44
47
|
def to_src(tabs, opts, fmt)
|
45
|
-
|
46
|
-
|
48
|
+
unless @args.empty? && @keywords.empty?
|
49
|
+
args = @args.map {|a| a.to_sass(opts)}.join(", ")
|
50
|
+
keywords = @keywords.map {|k, v| "$#{dasherize(k, opts)}: #{v.to_sass(opts)}"}.join(', ')
|
51
|
+
arglist = "(#{args}#{', ' unless args.empty? || keywords.empty?}#{keywords})"
|
52
|
+
end
|
53
|
+
"#{' ' * tabs}#{fmt == :sass ? '+' : '@include '}#{dasherize(@name, opts)}#{arglist}#{semi fmt}\n"
|
47
54
|
end
|
48
55
|
|
49
56
|
# @see Node#_cssize
|
@@ -73,15 +80,28 @@ module Sass::Tree
|
|
73
80
|
original_env.prepare_frame(:mixin => @name)
|
74
81
|
raise Sass::SyntaxError.new("Undefined mixin '#{@name}'.") unless mixin = environment.mixin(@name)
|
75
82
|
|
76
|
-
|
83
|
+
passed_args = @args.dup
|
84
|
+
passed_keywords = @keywords.dup
|
85
|
+
|
86
|
+
raise Sass::SyntaxError.new(<<END.gsub("\n", "")) if mixin.args.size < passed_args.size
|
77
87
|
Mixin #{@name} takes #{mixin.args.size} argument#{'s' if mixin.args.size != 1}
|
78
88
|
but #{@args.size} #{@args.size == 1 ? 'was' : 'were'} passed.
|
79
89
|
END
|
80
|
-
|
90
|
+
|
91
|
+
passed_keywords.each do |name, value|
|
92
|
+
# TODO: Make this fast
|
93
|
+
unless mixin.args.find {|(var, default)| var.underscored_name == name}
|
94
|
+
raise Sass::SyntaxError.new("Mixin #{@name} doesn't have an argument named $#{name}")
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
environment = mixin.args.zip(passed_args).
|
81
99
|
inject(Sass::Environment.new(mixin.environment)) do |env, ((var, default), value)|
|
82
100
|
env.set_local_var(var.name,
|
83
101
|
if value
|
84
102
|
value.perform(environment)
|
103
|
+
elsif kv = passed_keywords[var.underscored_name]
|
104
|
+
kv.perform(env)
|
85
105
|
elsif default
|
86
106
|
val = default.perform(env)
|
87
107
|
if default.context == :equals && val.is_a?(Sass::Script::String)
|
@@ -859,6 +859,20 @@ foo {
|
|
859
859
|
SCSS
|
860
860
|
end
|
861
861
|
|
862
|
+
def test_mixin_include_with_keyword_args
|
863
|
+
assert_renders <<SASS, <<SCSS
|
864
|
+
foo
|
865
|
+
+foo-bar(12px, "blaz", $blip: blap, $bloop: blop)
|
866
|
+
+foo-bar($blip: blap, $bloop: blop)
|
867
|
+
a: blip
|
868
|
+
SASS
|
869
|
+
foo {
|
870
|
+
@include foo-bar(12px, "blaz", $blip: blap, $bloop: blop);
|
871
|
+
@include foo-bar($blip: blap, $bloop: blop);
|
872
|
+
a: blip; }
|
873
|
+
SCSS
|
874
|
+
end
|
875
|
+
|
862
876
|
def test_variable_definition
|
863
877
|
assert_renders <<SASS, <<SCSS
|
864
878
|
$var1: 12px + 15px
|
data/test/sass/engine_test.rb
CHANGED
@@ -94,6 +94,7 @@ MSG
|
|
94
94
|
"a-\#{$b\n c: d" => ['Invalid CSS after "a-#{$b": expected "}", was ""', 1],
|
95
95
|
"=a($b = 1, $c)" => "Required argument $c must come before any optional arguments.",
|
96
96
|
"=a($b = 1)\n a: $b\ndiv\n +a(1,2)" => "Mixin a takes 1 argument but 2 were passed.",
|
97
|
+
"=a($b: 1)\n a: $b\ndiv\n +a(1,$c: 3)" => "Mixin a doesn't have an argument named $c",
|
97
98
|
"=a($b)\n a: $b\ndiv\n +a" => "Mixin a is missing parameter $b.",
|
98
99
|
"@else\n a\n b: c" => ["@else must come after @if.", 1],
|
99
100
|
"@if false\n@else foo" => "Invalid else directive '@else foo': expected 'if <expr>'.",
|
@@ -115,6 +116,16 @@ MSG
|
|
115
116
|
'@warn' => "Invalid warn directive '@warn': expected expression.",
|
116
117
|
%Q{@warn "a message"\n "nested message"} => "Illegal nesting: Nothing may be nested beneath warn directives.",
|
117
118
|
"/* foo\n bar\n baz" => "Inconsistent indentation: previous line was indented by 4 spaces, but this line was indented by 2 spaces.",
|
119
|
+
'+foo(1 + 1: 2)' => 'Invalid CSS after "(1 + 1": expected comma, was ": 2)"',
|
120
|
+
'+foo($var: )' => 'Invalid CSS after "($var: ": expected mixin argument, was ")"',
|
121
|
+
'+foo($var: a, $var: b)' => 'Keyword argument "$var" passed more than once',
|
122
|
+
'+foo($var-var: a, $var_var: b)' => 'Keyword argument "$var-var" passed more than once',
|
123
|
+
'+foo($var_var: a, $var-var: b)' => 'Keyword argument "$var_var" passed more than once',
|
124
|
+
"a\n b: foo(1 + 1: 2)" => 'Invalid CSS after "foo(1 + 1": expected comma, was ": 2)"',
|
125
|
+
"a\n b: foo($var: )" => 'Invalid CSS after "foo($var: ": expected function argument, was ")"',
|
126
|
+
"a\n b: foo($var: a, $var: b)" => 'Keyword argument "$var" passed more than once',
|
127
|
+
"a\n b: foo($var-var: a, $var_var: b)" => 'Keyword argument "$var-var" passed more than once',
|
128
|
+
"a\n b: foo($var_var: a, $var-var: b)" => 'Keyword argument "$var_var" passed more than once',
|
118
129
|
|
119
130
|
# Regression tests
|
120
131
|
"a\n b:\n c\n d" => ["Illegal nesting: Only properties may be nested beneath properties.", 3],
|
@@ -2101,6 +2112,70 @@ CSS
|
|
2101
2112
|
SASS
|
2102
2113
|
end
|
2103
2114
|
|
2115
|
+
def test_mixin_with_keyword_args
|
2116
|
+
assert_equal <<CSS, render(<<SASS)
|
2117
|
+
.mixed {
|
2118
|
+
required: foo;
|
2119
|
+
arg1: default-val1;
|
2120
|
+
arg2: non-default-val2; }
|
2121
|
+
CSS
|
2122
|
+
=a-mixin($required, $arg1: default-val1, $arg2: default-val2)
|
2123
|
+
required: $required
|
2124
|
+
arg1: $arg1
|
2125
|
+
arg2: $arg2
|
2126
|
+
.mixed
|
2127
|
+
+a-mixin(foo, $arg2: non-default-val2)
|
2128
|
+
SASS
|
2129
|
+
end
|
2130
|
+
|
2131
|
+
def test_mixin_keyword_args_handle_variable_underscore_dash_equivalence
|
2132
|
+
assert_equal <<CSS, render(<<SASS)
|
2133
|
+
.mixed {
|
2134
|
+
required: foo;
|
2135
|
+
arg1: non-default-val1;
|
2136
|
+
arg2: non-default-val2; }
|
2137
|
+
CSS
|
2138
|
+
=a-mixin($required, $arg-1: default-val1, $arg_2: default-val2)
|
2139
|
+
required: $required
|
2140
|
+
arg1: $arg_1
|
2141
|
+
arg2: $arg-2
|
2142
|
+
.mixed
|
2143
|
+
+a-mixin(foo, $arg-2: non-default-val2, $arg_1: non-default-val1)
|
2144
|
+
SASS
|
2145
|
+
end
|
2146
|
+
|
2147
|
+
def test_passing_required_args_as_a_keyword_arg
|
2148
|
+
assert_equal <<CSS, render(<<SASS)
|
2149
|
+
.mixed {
|
2150
|
+
required: foo;
|
2151
|
+
arg1: default-val1;
|
2152
|
+
arg2: default-val2; }
|
2153
|
+
CSS
|
2154
|
+
=a-mixin($required, $arg1: default-val1, $arg2: default-val2)
|
2155
|
+
required: $required
|
2156
|
+
arg1: $arg1
|
2157
|
+
arg2: $arg2
|
2158
|
+
.mixed
|
2159
|
+
+a-mixin($required: foo)
|
2160
|
+
SASS
|
2161
|
+
end
|
2162
|
+
|
2163
|
+
def test_passing_all_as_keyword_args_in_opposite_order
|
2164
|
+
assert_equal <<CSS, render(<<SASS)
|
2165
|
+
.mixed {
|
2166
|
+
required: foo;
|
2167
|
+
arg1: non-default-val1;
|
2168
|
+
arg2: non-default-val2; }
|
2169
|
+
CSS
|
2170
|
+
=a-mixin($required, $arg1: default-val1, $arg2: default-val2)
|
2171
|
+
required: $required
|
2172
|
+
arg1: $arg1
|
2173
|
+
arg2: $arg2
|
2174
|
+
.mixed
|
2175
|
+
+a-mixin($arg2: non-default-val2, $arg1: non-default-val1, $required: foo)
|
2176
|
+
SASS
|
2177
|
+
end
|
2178
|
+
|
2104
2179
|
def test_function_output_with_comma
|
2105
2180
|
assert_equal <<CSS, render(<<SASS)
|
2106
2181
|
foo {
|
data/test/sass/functions_test.rb
CHANGED
@@ -3,6 +3,22 @@ require 'test/unit'
|
|
3
3
|
require File.dirname(__FILE__) + '/../test_helper'
|
4
4
|
require 'sass/script'
|
5
5
|
|
6
|
+
module Sass::Script::Functions
|
7
|
+
def no_kw_args
|
8
|
+
Sass::Script::String.new("no-kw-args")
|
9
|
+
end
|
10
|
+
|
11
|
+
def only_var_args(*args)
|
12
|
+
Sass::Script::String.new("only-var-args("+args.map{|a| a.plus(Sass::Script::Number.new(1)).to_s }.join(", ")+")")
|
13
|
+
end
|
14
|
+
declare :only_var_args, [], :var_args => true
|
15
|
+
|
16
|
+
def only_kw_args(kwargs)
|
17
|
+
Sass::Script::String.new("only-kw-args("+kwargs.keys.join(", ")+")")
|
18
|
+
end
|
19
|
+
declare :only_kw_args, [], :var_kwargs => true
|
20
|
+
end
|
21
|
+
|
6
22
|
module Sass::Script::Functions::UserFunctions
|
7
23
|
def call_options_on_new_literal
|
8
24
|
str = Sass::Script::String.new("foo")
|
@@ -50,6 +66,10 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
50
66
|
end
|
51
67
|
end
|
52
68
|
|
69
|
+
def test_hsl_kwargs
|
70
|
+
assert_equal "#33cccc", evaluate("hsl($hue: 180, $saturation: 60%, $lightness: 50%)")
|
71
|
+
end
|
72
|
+
|
53
73
|
def test_hsl_checks_bounds
|
54
74
|
assert_error_message("Saturation -114 must be between 0% and 100% for `hsl'", "hsl(10, -114, 12)");
|
55
75
|
assert_error_message("Lightness 256 must be between 0% and 100% for `hsl'", "hsl(10, 10, 256%)");
|
@@ -65,6 +85,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
65
85
|
assert_equal "rgba(51, 204, 204, 0.4)", evaluate("hsla(180, 60%, 50%, 0.4)")
|
66
86
|
assert_equal "#33cccc", evaluate("hsla(180, 60%, 50%, 1)")
|
67
87
|
assert_equal "rgba(51, 204, 204, 0)", evaluate("hsla(180, 60%, 50%, 0)")
|
88
|
+
assert_equal "rgba(51, 204, 204, 0.4)", evaluate("hsla($hue: 180, $saturation: 60%, $lightness: 50%, $alpha: 0.4)")
|
68
89
|
end
|
69
90
|
|
70
91
|
def test_hsla_checks_bounds
|
@@ -85,6 +106,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
85
106
|
assert_equal("50%", evaluate("percentage(.5)"))
|
86
107
|
assert_equal("100%", evaluate("percentage(1)"))
|
87
108
|
assert_equal("25%", evaluate("percentage(25px / 100px)"))
|
109
|
+
assert_equal("50%", evaluate("percentage($value: 0.5)"))
|
88
110
|
end
|
89
111
|
|
90
112
|
def test_percentage_checks_types
|
@@ -97,6 +119,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
97
119
|
assert_equal("5", evaluate("round(4.8)"))
|
98
120
|
assert_equal("5px", evaluate("round(4.8px)"))
|
99
121
|
assert_equal("5px", evaluate("round(5.49px)"))
|
122
|
+
assert_equal("5px", evaluate("round($value: 5.49px)"))
|
100
123
|
|
101
124
|
assert_error_message("#cccccc is not a number for `round'", "round(#ccc)")
|
102
125
|
end
|
@@ -104,6 +127,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
104
127
|
def test_floor
|
105
128
|
assert_equal("4", evaluate("floor(4.8)"))
|
106
129
|
assert_equal("4px", evaluate("floor(4.8px)"))
|
130
|
+
assert_equal("4px", evaluate("floor($value: 4.8px)"))
|
107
131
|
|
108
132
|
assert_error_message("\"foo\" is not a number for `floor'", "floor(\"foo\")")
|
109
133
|
end
|
@@ -111,6 +135,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
111
135
|
def test_ceil
|
112
136
|
assert_equal("5", evaluate("ceil(4.1)"))
|
113
137
|
assert_equal("5px", evaluate("ceil(4.8px)"))
|
138
|
+
assert_equal("5px", evaluate("ceil($value: 4.8px)"))
|
114
139
|
|
115
140
|
assert_error_message("\"a\" is not a number for `ceil'", "ceil(\"a\")")
|
116
141
|
end
|
@@ -120,6 +145,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
120
145
|
assert_equal("5px", evaluate("abs(-5px)"))
|
121
146
|
assert_equal("5", evaluate("abs(5)"))
|
122
147
|
assert_equal("5px", evaluate("abs(5px)"))
|
148
|
+
assert_equal("5px", evaluate("abs($value: 5px)"))
|
123
149
|
|
124
150
|
assert_error_message("#aaaaaa is not a number for `abs'", "abs(#aaa)")
|
125
151
|
end
|
@@ -128,6 +154,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
128
154
|
assert_equal("#123456", evaluate("rgb(18, 52, 86)"))
|
129
155
|
assert_equal("#beaded", evaluate("rgb(190, 173, 237)"))
|
130
156
|
assert_equal("#00ff7f", evaluate("rgb(0, 255, 127)"))
|
157
|
+
assert_equal("#00ff7f", evaluate("rgb($red: 0, $green: 255, $blue: 127)"))
|
131
158
|
end
|
132
159
|
|
133
160
|
def test_rgb_percent
|
@@ -169,6 +196,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
169
196
|
assert_equal("rgba(18, 52, 86, 0.5)", evaluate("rgba(18, 52, 86, 0.5)"))
|
170
197
|
assert_equal("#beaded", evaluate("rgba(190, 173, 237, 1)"))
|
171
198
|
assert_equal("rgba(0, 255, 127, 0)", evaluate("rgba(0, 255, 127, 0)"))
|
199
|
+
assert_equal("rgba(0, 255, 127, 0)", evaluate("rgba($red: 0, $green: 255, $blue: 127, $alpha: 0)"))
|
172
200
|
end
|
173
201
|
|
174
202
|
def test_rgb_tests_bounds
|
@@ -198,6 +226,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
198
226
|
def test_rgba_with_color
|
199
227
|
assert_equal "rgba(16, 32, 48, 0.5)", evaluate("rgba(#102030, 0.5)")
|
200
228
|
assert_equal "rgba(0, 0, 255, 0.5)", evaluate("rgba(blue, 0.5)")
|
229
|
+
assert_equal "rgba(0, 0, 255, 0.5)", evaluate("rgba($color: blue, $alpha: 0.5)")
|
201
230
|
end
|
202
231
|
|
203
232
|
def test_rgba_with_color_tests_types
|
@@ -214,6 +243,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
214
243
|
|
215
244
|
def test_red
|
216
245
|
assert_equal("18", evaluate("red(#123456)"))
|
246
|
+
assert_equal("18", evaluate("red($color: #123456)"))
|
217
247
|
end
|
218
248
|
|
219
249
|
def test_red_exception
|
@@ -222,6 +252,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
222
252
|
|
223
253
|
def test_green
|
224
254
|
assert_equal("52", evaluate("green(#123456)"))
|
255
|
+
assert_equal("52", evaluate("green($color: #123456)"))
|
225
256
|
end
|
226
257
|
|
227
258
|
def test_green_exception
|
@@ -230,6 +261,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
230
261
|
|
231
262
|
def test_blue
|
232
263
|
assert_equal("86", evaluate("blue(#123456)"))
|
264
|
+
assert_equal("86", evaluate("blue($color: #123456)"))
|
233
265
|
end
|
234
266
|
|
235
267
|
def test_blue_exception
|
@@ -238,6 +270,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
238
270
|
|
239
271
|
def test_hue
|
240
272
|
assert_equal("18deg", evaluate("hue(hsl(18, 50%, 20%))"))
|
273
|
+
assert_equal("18deg", evaluate("hue($color: hsl(18, 50%, 20%))"))
|
241
274
|
end
|
242
275
|
|
243
276
|
def test_hue_exception
|
@@ -247,6 +280,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
247
280
|
def test_saturation
|
248
281
|
assert_equal("52%", evaluate("saturation(hsl(20, 52%, 20%))"))
|
249
282
|
assert_equal("52%", evaluate("saturation(hsl(20, 52, 20%))"))
|
283
|
+
assert_equal("52%", evaluate("saturation($color: hsl(20, 52, 20%))"))
|
250
284
|
end
|
251
285
|
|
252
286
|
def test_saturation_exception
|
@@ -256,6 +290,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
256
290
|
def test_lightness
|
257
291
|
assert_equal("86%", evaluate("lightness(hsl(120, 50%, 86%))"))
|
258
292
|
assert_equal("86%", evaluate("lightness(hsl(120, 50%, 86))"))
|
293
|
+
assert_equal("86%", evaluate("lightness($color: hsl(120, 50%, 86))"))
|
259
294
|
end
|
260
295
|
|
261
296
|
def test_lightness_exception
|
@@ -266,6 +301,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
266
301
|
assert_equal("1", evaluate("alpha(#123456)"))
|
267
302
|
assert_equal("0.34", evaluate("alpha(rgba(0, 1, 2, 0.34))"))
|
268
303
|
assert_equal("0", evaluate("alpha(hsla(0, 1, 2, 0))"))
|
304
|
+
assert_equal("0", evaluate("alpha($color: hsla(0, 1, 2, 0))"))
|
269
305
|
end
|
270
306
|
|
271
307
|
def test_alpha_exception
|
@@ -279,6 +315,8 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
279
315
|
assert_equal("black", evaluate("fade_in(rgba(0, 0, 0, 0.2), 0.8)"))
|
280
316
|
assert_equal("black", evaluate("opacify(rgba(0, 0, 0, 0.2), 1)"))
|
281
317
|
assert_equal("rgba(0, 0, 0, 0.2)", evaluate("opacify(rgba(0, 0, 0, 0.2), 0%)"))
|
318
|
+
assert_equal("rgba(0, 0, 0, 0.2)", evaluate("opacify($color: rgba(0, 0, 0, 0.2), $amount: 0%)"))
|
319
|
+
assert_equal("rgba(0, 0, 0, 0.2)", evaluate("fade-in($color: rgba(0, 0, 0, 0.2), $amount: 0%)"))
|
282
320
|
end
|
283
321
|
|
284
322
|
def test_opacify_tests_bounds
|
@@ -300,6 +338,8 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
300
338
|
assert_equal("rgba(0, 0, 0, 0)", evaluate("fade_out(rgba(0, 0, 0, 0.2), 0.2)"))
|
301
339
|
assert_equal("rgba(0, 0, 0, 0)", evaluate("transparentize(rgba(0, 0, 0, 0.2), 1)"))
|
302
340
|
assert_equal("rgba(0, 0, 0, 0.2)", evaluate("transparentize(rgba(0, 0, 0, 0.2), 0)"))
|
341
|
+
assert_equal("rgba(0, 0, 0, 0.2)", evaluate("transparentize($color: rgba(0, 0, 0, 0.2), $amount: 0)"))
|
342
|
+
assert_equal("rgba(0, 0, 0, 0.2)", evaluate("fade-out($color: rgba(0, 0, 0, 0.2), $amount: 0)"))
|
303
343
|
end
|
304
344
|
|
305
345
|
def test_transparentize_tests_bounds
|
@@ -321,6 +361,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
321
361
|
assert_equal("white", evaluate("lighten(#800, 100%)"))
|
322
362
|
assert_equal("#880000", evaluate("lighten(#800, 0%)"))
|
323
363
|
assert_equal("rgba(238, 0, 0, 0.5)", evaluate("lighten(rgba(136, 0, 0, 0.5), 20%)"))
|
364
|
+
assert_equal("rgba(238, 0, 0, 0.5)", evaluate("lighten($color: rgba(136, 0, 0, 0.5), $amount: 20%)"))
|
324
365
|
end
|
325
366
|
|
326
367
|
def test_lighten_tests_bounds
|
@@ -342,6 +383,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
342
383
|
assert_equal("black", evaluate("darken(#800, 100%)"))
|
343
384
|
assert_equal("#880000", evaluate("darken(#800, 0%)"))
|
344
385
|
assert_equal("rgba(34, 0, 0, 0.5)", evaluate("darken(rgba(136, 0, 0, 0.5), 20%)"))
|
386
|
+
assert_equal("rgba(34, 0, 0, 0.5)", evaluate("darken($color: rgba(136, 0, 0, 0.5), $amount: 20%)"))
|
345
387
|
end
|
346
388
|
|
347
389
|
def test_darken_tests_bounds
|
@@ -364,6 +406,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
364
406
|
assert_equal("#33ff33", evaluate("saturate(#8a8, 100%)"))
|
365
407
|
assert_equal("#88aa88", evaluate("saturate(#8a8, 0%)"))
|
366
408
|
assert_equal("rgba(158, 63, 63, 0.5)", evaluate("saturate(rgba(136, 85, 85, 0.5), 20%)"))
|
409
|
+
assert_equal("rgba(158, 63, 63, 0.5)", evaluate("saturate($color: rgba(136, 85, 85, 0.5), $amount: 20%)"))
|
367
410
|
end
|
368
411
|
|
369
412
|
def test_saturate_tests_bounds
|
@@ -386,6 +429,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
386
429
|
assert_equal("#999999", evaluate("desaturate(#8a8, 100%)"))
|
387
430
|
assert_equal("#88aa88", evaluate("desaturate(#8a8, 0%)"))
|
388
431
|
assert_equal("rgba(114, 107, 107, 0.5)", evaluate("desaturate(rgba(136, 85, 85, 0.5), 20%)"))
|
432
|
+
assert_equal("rgba(114, 107, 107, 0.5)", evaluate("desaturate($color: rgba(136, 85, 85, 0.5), $amount: 20%)"))
|
389
433
|
end
|
390
434
|
|
391
435
|
def test_desaturate_tests_bounds
|
@@ -409,6 +453,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
409
453
|
assert_equal("#88aa88", evaluate("adjust-hue(#8a8, 360deg)"))
|
410
454
|
assert_equal("#88aa88", evaluate("adjust-hue(#8a8, 0deg)"))
|
411
455
|
assert_equal("rgba(136, 106, 17, 0.5)", evaluate("adjust-hue(rgba(136, 17, 17, 0.5), 45deg)"))
|
456
|
+
assert_equal("rgba(136, 106, 17, 0.5)", evaluate("adjust-hue($color: rgba(136, 17, 17, 0.5), $degrees: 45deg)"))
|
412
457
|
end
|
413
458
|
|
414
459
|
def test_adjust_hue_tests_types
|
@@ -430,6 +475,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
430
475
|
assert_equal("blue", evaluate("mix(transparentize(#f00, 1), #00f, 0%)"))
|
431
476
|
assert_equal("rgba(0, 0, 255, 0)", evaluate("mix(#f00, transparentize(#00f, 1), 0%)"))
|
432
477
|
assert_equal("rgba(255, 0, 0, 0)", evaluate("mix(transparentize(#f00, 1), #00f, 100%)"))
|
478
|
+
assert_equal("rgba(255, 0, 0, 0)", evaluate("mix($color-1: transparentize(#f00, 1), $color-2: #00f, $weight: 100%)"))
|
433
479
|
end
|
434
480
|
|
435
481
|
def test_mix_tests_types
|
@@ -451,6 +497,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
451
497
|
assert_equal("gray", evaluate("grayscale(#00f)"))
|
452
498
|
assert_equal("white", evaluate("grayscale(white)"))
|
453
499
|
assert_equal("black", evaluate("grayscale(black)"))
|
500
|
+
assert_equal("black", evaluate("grayscale($color: black)"))
|
454
501
|
end
|
455
502
|
|
456
503
|
def tets_grayscale_tests_types
|
@@ -463,6 +510,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
463
510
|
assert_equal("red", evaluate("complement(aqua)"))
|
464
511
|
assert_equal("white", evaluate("complement(white)"))
|
465
512
|
assert_equal("black", evaluate("complement(black)"))
|
513
|
+
assert_equal("black", evaluate("complement($color: black)"))
|
466
514
|
end
|
467
515
|
|
468
516
|
def tets_complement_tests_types
|
@@ -481,6 +529,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
481
529
|
def test_unquote
|
482
530
|
assert_equal('foo', evaluate('unquote("foo")'))
|
483
531
|
assert_equal('foo', evaluate('unquote(foo)'))
|
532
|
+
assert_equal('foo', evaluate('unquote($string: foo)'))
|
484
533
|
end
|
485
534
|
|
486
535
|
def test_unquote_tests_type
|
@@ -490,6 +539,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
490
539
|
def test_quote
|
491
540
|
assert_equal('"foo"', evaluate('quote(foo)'))
|
492
541
|
assert_equal('"foo"', evaluate('quote("foo")'))
|
542
|
+
assert_equal('"foo"', evaluate('quote($string: "foo")'))
|
493
543
|
end
|
494
544
|
|
495
545
|
def test_quote_tests_type
|
@@ -520,6 +570,7 @@ MSG
|
|
520
570
|
assert_equal("number", evaluate("type-of(1px)"))
|
521
571
|
assert_equal("bool", evaluate("type-of(true)"))
|
522
572
|
assert_equal("color", evaluate("type-of(#fff)"))
|
573
|
+
assert_equal("color", evaluate("type-of($value: #fff)"))
|
523
574
|
end
|
524
575
|
|
525
576
|
def test_unit
|
@@ -528,12 +579,14 @@ MSG
|
|
528
579
|
assert_equal(%Q{"em*px"}, evaluate("unit(10px * 5em)"))
|
529
580
|
assert_equal(%Q{"em*px"}, evaluate("unit(5em * 10px)"))
|
530
581
|
assert_equal(%Q{"em*px/cm*rem"}, evaluate("unit(10px * 5em / 30cm / 1rem)"))
|
582
|
+
assert_equal(%Q{"px"}, evaluate("unit($number: 100px)"))
|
531
583
|
assert_error_message("#ff0000 is not a number for `unit'", "unit(#f00)")
|
532
584
|
end
|
533
585
|
|
534
586
|
def test_unitless
|
535
587
|
assert_equal(%Q{true}, evaluate("unitless(100)"))
|
536
588
|
assert_equal(%Q{false}, evaluate("unitless(100px)"))
|
589
|
+
assert_equal(%Q{false}, evaluate("unitless($number: 100px)"))
|
537
590
|
assert_error_message("#ff0000 is not a number for `unitless'", "unitless(#f00)")
|
538
591
|
end
|
539
592
|
|
@@ -541,10 +594,44 @@ MSG
|
|
541
594
|
assert_equal(%Q{true}, evaluate("comparable(2px, 1px)"))
|
542
595
|
assert_equal(%Q{true}, evaluate("comparable(10cm, 3mm)"))
|
543
596
|
assert_equal(%Q{false}, evaluate("comparable(100px, 3em)"))
|
597
|
+
assert_equal(%Q{false}, evaluate("comparable($number-1: 100px, $number-2: 3em)"))
|
544
598
|
assert_error_message("#ff0000 is not a number for `comparable'", "comparable(#f00, 1px)")
|
545
599
|
assert_error_message("#ff0000 is not a number for `comparable'", "comparable(1px, #f00)")
|
546
600
|
end
|
547
601
|
|
602
|
+
def test_keyword_args_rgb
|
603
|
+
assert_equal(%Q{white}, evaluate("rgb($red: 255, $green: 255, $blue: 255)"))
|
604
|
+
end
|
605
|
+
|
606
|
+
def test_keyword_args_rgba
|
607
|
+
assert_equal(%Q{rgba(255, 255, 255, 0.5)}, evaluate("rgba($red: 255, $green: 255, $blue: 255, $alpha: 0.5)"))
|
608
|
+
assert_equal(%Q{rgba(255, 255, 255, 0.5)}, evaluate("rgba($color: #fff, $alpha: 0.5)"))
|
609
|
+
end
|
610
|
+
|
611
|
+
def test_keyword_args_rgba_with_extra_args
|
612
|
+
assert_equal(%Q{rgba(255, 255, 255, 0.5)}, evaluate("rgba($red: 255, $green: 255, $blue: 255, $alpha: 0.5, $extra: error)"))
|
613
|
+
rescue Sass::SyntaxError => e
|
614
|
+
assert_equal("Function rgba doesn't take an argument named $extra", e.message)
|
615
|
+
end
|
616
|
+
|
617
|
+
def test_keyword_args_must_have_signature
|
618
|
+
evaluate("no-kw-args($fake: value)")
|
619
|
+
rescue Sass::SyntaxError => e
|
620
|
+
assert_equal("Function no_kw_args doesn't support keyword arguments", e.message)
|
621
|
+
end
|
622
|
+
|
623
|
+
def test_keyword_args_with_missing_argument
|
624
|
+
evaluate("rgb($red: 255, $green: 255)")
|
625
|
+
rescue Sass::SyntaxError => e
|
626
|
+
assert_equal("Function rgb requires an argument named $blue", e.message)
|
627
|
+
end
|
628
|
+
|
629
|
+
def test_only_var_args
|
630
|
+
assert_equal "only-var-args(2px, 3px, 4px)", evaluate("only-var-args(1px, 2px, 3px)")
|
631
|
+
end
|
632
|
+
def test_only_kw_args
|
633
|
+
assert_equal "only-kw-args(a, b, c)", evaluate("only-kw-args($a: 1, $b: 2, $c: 3)")
|
634
|
+
end
|
548
635
|
private
|
549
636
|
|
550
637
|
def evaluate(value)
|