Skip to content

Commit 3bde903

Browse files
committed
Merge pull request #29 from rubenswieringa/number-support
Maps & numbers support
2 parents 91a1bad + c6d180b commit 3bde903

File tree

7 files changed

+159
-4
lines changed

7 files changed

+159
-4
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/.bundle/
22
/.yardoc
3+
/.rvmrc
34
/Gemfile.lock
45
/_yardoc/
56
/coverage/

lib/sassc/native/native_functions_api.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,24 @@ module Native
2424
# ADDAPI union Sass_Value* ADDCALL sass_make_color (double r, double g, double b, double a);
2525
attach_function :sass_make_color, [:double, :double, :double, :double], :sass_value_ptr
2626

27+
# ADDAPI union Sass_Value* ADDCALL sass_make_map (size_t len);
28+
attach_function :sass_make_map, [:size_t], :sass_value_ptr
29+
30+
# ADDAPI void ADDCALL sass_map_set_key (union Sass_Value* v, size_t i, union Sass_Value*);
31+
attach_function :sass_map_set_key, [:sass_value_ptr, :size_t, :sass_value_ptr], :void
32+
33+
# ADDAPI union Sass_Value* ADDCALL sass_map_get_key (const union Sass_Value* v, size_t i);
34+
attach_function :sass_map_get_key, [:sass_value_ptr, :size_t], :sass_value_ptr
35+
36+
# ADDAPI void ADDCALL sass_map_set_value (union Sass_Value* v, size_t i, union Sass_Value*);
37+
attach_function :sass_map_set_value, [:sass_value_ptr, :size_t, :sass_value_ptr], :void
38+
39+
# ADDAPI union Sass_Value* ADDCALL sass_map_get_value (const union Sass_Value* v, size_t i);
40+
attach_function :sass_map_get_value, [:sass_value_ptr, :size_t], :sass_value_ptr
41+
42+
# ADDAPI size_t ADDCALL sass_map_get_length (const union Sass_Value* v);
43+
attach_function :sass_map_get_length, [:sass_value_ptr], :size_t
44+
2745
# ADDAPI union Sass_Value* ADDCALL sass_make_error (const char* msg);
2846
attach_function :sass_make_error, [:string], :sass_value_ptr
2947

@@ -37,6 +55,12 @@ module Native
3755
# ADDAPI bool ADDCALL sass_string_is_quoted(const union Sass_Value* v);
3856
attach_function :sass_string_is_quoted, [:sass_value_ptr], :bool
3957

58+
# ADDAPI const char* ADDCALL sass_number_get_value (const union Sass_Value* v);
59+
attach_function :sass_number_get_value, [:sass_value_ptr], :double
60+
61+
# ADDAPI const char* ADDCALL sass_number_get_unit (const union Sass_Value* v);
62+
attach_function :sass_number_get_unit, [:sass_value_ptr], :string
63+
4064
def self.string_get_type(native_value)
4165
string_is_quoted(native_value) ? :string : :identifier
4266
end

lib/sassc/script/value_conversion.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,31 @@ def self.from_native(native_value, options)
1010
type = Native.string_get_type(native_value)
1111
argument = Script::String.new(value, type)
1212

13+
argument
14+
when :sass_number
15+
value = Native.number_get_value(native_value)
16+
unit = Native.number_get_unit(native_value)
17+
argument = Sass::Script::Value::Number.new(value, unit)
18+
1319
argument
1420
when :sass_color
1521
red, green, blue, alpha = Native.color_get_r(native_value), Native.color_get_g(native_value), Native.color_get_b(native_value), Native.color_get_a(native_value)
1622

1723
argument = Script::Color.new([red, green, blue, alpha])
1824
argument.options = options
1925

26+
argument
27+
when :sass_map
28+
values = {}
29+
length = Native::map_get_length native_value
30+
31+
(0..length-1).each do |index|
32+
key = Native::map_get_key(native_value, index)
33+
value = Native::map_get_value(native_value, index)
34+
values[from_native(key, options)] = from_native(value, options)
35+
end
36+
37+
argument = Sass::Script::Value::Map.new values
2038
argument
2139
else
2240
raise UnsupportedValue.new("Sass argument of type #{value_tag} unsupported")
@@ -29,6 +47,10 @@ def self.to_native(value)
2947
String.new(value).to_native
3048
when "Color"
3149
Color.new(value).to_native
50+
when "Number"
51+
Number.new(value).to_native
52+
when "Map"
53+
Map.new(value).to_native
3254
else
3355
raise UnsupportedValue.new("Sass return type #{value_name} unsupported")
3456
end
@@ -39,4 +61,6 @@ def self.to_native(value)
3961

4062
require_relative "value_conversion/base"
4163
require_relative "value_conversion/string"
64+
require_relative "value_conversion/number"
4265
require_relative "value_conversion/color"
66+
require_relative "value_conversion/map"
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module SassC
2+
module Script
3+
module ValueConversion
4+
class Map < Base
5+
def to_native
6+
hash = @value.to_h
7+
native_map = Native::make_map( hash.size )
8+
hash.each_with_index do |(key, value), index|
9+
key = ValueConversion.to_native key
10+
value = ValueConversion.to_native value
11+
Native::map_set_key( native_map, index, key )
12+
Native::map_set_value( native_map, index, value )
13+
end
14+
return native_map
15+
end
16+
end
17+
end
18+
end
19+
end
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module SassC
2+
module Script
3+
module ValueConversion
4+
class Number < Base
5+
def to_native
6+
Native::make_number(@value.value, @value.numerator_units.first)
7+
end
8+
end
9+
end
10+
end
11+
end

test/functions_test.rb

Lines changed: 76 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,22 @@ def test_function_that_returns_a_color
6464
CSS
6565
end
6666

67+
def test_function_that_returns_a_number
68+
assert_sass <<-SCSS, <<-CSS
69+
div { width: returns-a-number(); }
70+
SCSS
71+
div { width: -312rem; }
72+
CSS
73+
end
74+
75+
def test_function_that_takes_a_number
76+
assert_sass <<-SCSS, <<-CSS
77+
div { display: inspect-number(42.1px); }
78+
SCSS
79+
div { display: 42.1px; }
80+
CSS
81+
end
82+
6783
def test_function_with_optional_arguments
6884
assert_sass <<-SCSS, <<-EXPECTED_CSS
6985
div {
@@ -87,14 +103,14 @@ def test_functions_may_accept_sass_color_type
87103
end
88104

89105
def test_function_with_unsupported_tag
90-
engine = Engine.new("div {url: function_with_unsupported_tag(1);}")
106+
engine = Engine.new("div {url: function_with_unsupported_tag(());}")
91107

92108
exception = assert_raises(SassC::SyntaxError) do
93109
engine.render
94110
end
95111

96-
assert_match /Sass argument of type sass_number unsupported/, exception.message
97-
assert_equal "[SassC::FunctionsHandler] Sass argument of type sass_number unsupported", stderr_output
112+
assert_match /Sass argument of type sass_list unsupported/, exception.message
113+
assert_equal "[SassC::FunctionsHandler] Sass argument of type sass_list unsupported", stderr_output
98114
end
99115

100116
def test_function_with_error
@@ -117,6 +133,23 @@ def test_function_that_returns_a_sass_value
117133
CSS
118134
end
119135

136+
def test_function_that_returns_a_sass_map
137+
assert_sass <<-SCSS, <<-CSS
138+
$my-map: returns-sass-map();
139+
div { background: map-get( $my-map, color ); }
140+
SCSS
141+
div { background: black; }
142+
CSS
143+
end
144+
145+
def test_function_that_takes_a_sass_map
146+
assert_sass <<-SCSS, <<-CSS
147+
div { background-color: map-get( inspect-map(( color: black, number: 1.23px, string: "abc", map: ( x: 'y' ))), color ); }
148+
SCSS
149+
div { background-color: black; }
150+
CSS
151+
end
152+
120153
private
121154

122155
def assert_sass(sass, expected_css)
@@ -151,7 +184,7 @@ def function_that_raises_errors
151184
raise StandardError, "Intentional wrong thing happened somewhere inside the custom function"
152185
end
153186

154-
def function_with_unsupported_tag(number)
187+
def function_with_unsupported_tag(value)
155188
end
156189

157190
def nice_color_argument(color)
@@ -162,10 +195,49 @@ def returns_a_color
162195
return Script::Color.new(red: 0, green: 0, blue: 0)
163196
end
164197

198+
def returns_a_number
199+
return Sass::Script::Value::Number.new(-312,'rem')
200+
end
201+
202+
def inspect_number ( argument )
203+
raise StandardError.new "passed value is not a Sass::Script::Value::Number" unless argument.is_a? Sass::Script::Value::Number
204+
return argument
205+
end
206+
207+
def inspect_map ( argument )
208+
argument.to_h.each_pair do |key, value|
209+
raise StandardError.new "key #{key.inspect} is not a string" unless key.is_a? Sass::Script::Value::String
210+
211+
valueClass = case key.value
212+
when 'string'
213+
Sass::Script::Value::String
214+
when 'number'
215+
Sass::Script::Value::Number
216+
when 'color'
217+
Sass::Script::Value::Color
218+
when 'map'
219+
Sass::Script::Value::Map
220+
end
221+
222+
raise StandardError.new "unknown key #{key.inspect}" unless valueClass
223+
raise StandardError.new "value for #{key.inspect} is not a #{valueClass}" unless value.is_a? valueClass
224+
end
225+
return argument
226+
end
227+
165228
def returns_sass_value
166229
return Sass::Script::Value::Color.new(red: 0, green: 0, blue: 0)
167230
end
168231

232+
def returns_sass_map
233+
key = Script::String.new("color", "string")
234+
value = Sass::Script::Value::Color.new(red: 0, green: 0, blue: 0)
235+
values = {}
236+
values[key] = value
237+
map = Sass::Script::Value::Map.new values
238+
return map
239+
end
240+
169241
module Compass
170242
def stylesheet_path(path)
171243
Script::String.new("/css/#{path.value}", :identifier)

test/native_test.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ def test_custom_function
9696
assert_equal :sass_string, Native.value_get_tag(string)
9797
assert_equal "hello", Native.string_get_value(string)
9898

99+
number = Native.make_number(123.4, "rem")
100+
assert_equal 123.4, Native.number_get_value(number)
101+
assert_equal "rem", Native.number_get_unit(number)
102+
99103
Native.compile_data_context(data_context)
100104

101105
css = Native.context_get_output_string(context)

0 commit comments

Comments
 (0)