Skip to content

Commit aabd135

Browse files
committed
Implements first sass map support
1 parent 535455a commit aabd135

File tree

2 files changed

+67
-1
lines changed

2 files changed

+67
-1
lines changed

lib/CSS/Sass.xs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,41 @@ SV *sv_from_sass_value(union Sass_Value val)
5959
for (i=0; i<val.list.length; i++)
6060
av_push(perl, sv_from_sass_value(val.list.values[i]));
6161
} break;
62+
case SASS_MAP: {
63+
int i;
64+
HV *map = newHV();
65+
for (i=0; i<val.map.length; i++) {
66+
// this returns an AV inside an SV
67+
SV* sv = sv_from_sass_value(val.map.pairs[i].key);
68+
// we expect an array to access the sass value
69+
if (!SvROK(sv) || SvTYPE(SvRV(sv)) != SVt_PVAV) {
70+
av_push(perl, newSVpvf("BUG: Expect array for sass value"));
71+
break;
72+
}
73+
// get basic type from the sass type variable
74+
SV** sv_type_ptr = av_fetch((AV*) SvRV(sv), 0, 0);
75+
// we only support string types as keys
76+
if (!sv_type_ptr || !SvOK(*sv_type_ptr) || !(
77+
SvIV(*sv_type_ptr) == SASS_NUMBER ||
78+
SvIV(*sv_type_ptr) == SASS_STRING
79+
)) {
80+
av_push(perl, newSVpvf("BUG: Key must be int or string"));
81+
break;
82+
}
83+
// now get the key which is a number or a string
84+
SV** sv_key_ptr = av_fetch((AV*) SvRV(sv), 1, 0);
85+
// check for valid pointer
86+
if (!sv_key_ptr) {
87+
av_push(perl, newSVpvf("BUG: Could not access value"));
88+
break;
89+
}
90+
// call us recursive if needed to get sass values
91+
SV* sv_value = sv_from_sass_value(val.map.pairs[i].value);
92+
// finally store the result inside the hash
93+
hv_store_ent(map, *sv_key_ptr, sv_value, 0);
94+
}
95+
av_push(perl, newRV_noinc((SV*) map));
96+
} break;
6297
case SASS_ERROR:
6398
av_push(perl, newSVpv(val.error.message, 0));
6499
break;
@@ -83,6 +118,10 @@ union Sass_Value sass_value_from_sv(SV *sv)
83118
if (!SvROK(sv) || SvTYPE(SvRV(sv)) != SVt_PVAV)
84119
return make_sass_error_f("perl type must be an arrayref (SvTYPE=%u)", (unsigned)SvTYPE(SvRV(sv)));
85120

121+
// we expect an array to access the sass value
122+
if (!SvROK(sv) || SvTYPE(SvRV(sv)) != SVt_PVAV) {
123+
return make_sass_error_f("BUG: Expect array for sass value");
124+
}
86125
AV *av = (AV*)SvRV(sv);
87126
switch (sviv(*av_fetch(av, 0, false))) {
88127
case SASS_BOOLEAN: return make_sass_boolean(sviv(*av_fetch(av, 1, false)));
@@ -103,6 +142,25 @@ union Sass_Value sass_value_from_sv(SV *sv)
103142
list.list.values[i] = sass_value_from_sv(*av_fetch(av, i+2, false));
104143
return list;
105144
}
145+
case SASS_MAP: {
146+
SV* sv_hash = *av_fetch(av, 1, false);
147+
// we expect an array to access the sass value
148+
if (!SvROK(sv_hash) || SvTYPE(SvRV(sv_hash)) != SVt_PVHV) {
149+
return make_sass_error_f("BUG: Expect hash for sass map value");
150+
}
151+
HV* hv = (HV*)SvRV(sv_hash);
152+
union Sass_Value map = make_sass_map(HvUSEDKEYS(hv));
153+
int i = 0;
154+
HE *key;
155+
hv_iterinit(hv);
156+
while (NULL != (key = hv_iternext(hv))) {
157+
map.map.pairs[i].key = sass_value_from_sv(HeSVKEY_force(key));
158+
map.map.pairs[i].value = sass_value_from_sv(HeVAL(key));
159+
i++;
160+
}
161+
return map;
162+
}
163+
default: make_sass_error_f("BUG: This Sass_Value is not handled yet (tag=%d).", sviv(*av_fetch(av, 0, false)));
106164
}
107165

108166
return make_sass_error_f("Unknown sass_type (tag=%u)", (unsigned)sviv(*av_fetch(av, 0, false)));
@@ -157,6 +215,8 @@ BOOT:
157215
Constant(SASS_COLOR);
158216
Constant(SASS_STRING);
159217
Constant(SASS_LIST);
218+
Constant(SASS_MAP);
219+
Constant(SASS_NULL);
160220
Constant(SASS_ERROR);
161221

162222
Constant(SASS_COMMA);

t/03_xs_functions.t

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
use strict;
77
use warnings;
88

9-
use Test::More tests => 42;
9+
use Test::More tests => 45;
1010

1111
use CSS::Sass;
1212

@@ -119,3 +119,9 @@ is ($r->{error_status}, 1, "sass_functi
119119
like ($r->{error_message}, qr/perl type.*arrayref/, "sass_function bad perl type error_message explains itself");
120120
is ($r->{output_string}, undef, "sass_function bad perl type fails");
121121

122+
$r = CSS::Sass::compile_sass('$map: (key1: value1, 2: value2, color: rgba(1,1,1,0.4)); A { color: map-get($map, color); }', {
123+
sass_functions => [ [ 'test($map)' => sub { $_[1] } ] ] });
124+
125+
is ($r->{error_status}, 0, "sass_function map handling no error_status");
126+
is ($r->{error_message}, undef, "sass_function map handling error_message is undef");
127+
like ($r->{output_string}, qr@\Qcolor: rgba(1, 1, 1, 0.4)\E@, "sass_function map handling works");

0 commit comments

Comments
 (0)