@@ -68,6 +68,116 @@ namespace Sass {
6868 return value;
6969 }
7070
71+
72+ // / Returns whether [value] is an unquoted string that start with `var(` and
73+ // / contains `/`.
74+ bool _isVarSlash (Expression* value) {
75+ if (String_Constant * string = Cast<String_Constant>(value)) {
76+ return starts_with (string->value (), " var(" ) &&
77+ string_constains (string->value (), ' /' );
78+ }
79+ if (StringLiteral * string = Cast<StringLiteral>(value)) {
80+ return starts_with (string->text (), " var(" ) &&
81+ string_constains (string->text (), ' /' );
82+ }
83+ return false ;
84+ }
85+
86+
87+ Expression* _parseChannels (std::string name, std::vector<std::string> argumentNames, Value* channels, ParserState pstate, Backtraces traces)
88+ {
89+ if (isVar (channels)) {
90+ std::stringstream fncall;
91+ fncall << name << " ("
92+ << channels->to_css () << " )" ;
93+ return SASS_MEMORY_NEW (StringLiteral,
94+ pstate, fncall.str ());
95+ }
96+
97+ // Expression* list = Listize::perform(channels);
98+
99+ if (List * list = Cast<List>(channels)) {
100+ bool isCommaSeparated = list->separator () == SASS_COMMA;
101+ bool isBracketed = list->is_bracketed ();
102+ if (isCommaSeparated || isBracketed) {
103+ std::stringstream msg;
104+ msg << " $channels must be" ;
105+ if (isBracketed) msg << " an unbracketed" ;
106+ if (isCommaSeparated) {
107+ msg << (isBracketed ? " ," : " a" );
108+ msg << " space-separated" ;
109+ }
110+ msg << " list." ;
111+ error (msg.str (), pstate, traces);
112+ }
113+
114+ if (list->length () > 3 ) {
115+ error (
116+ " Only 3 elements allowed, but ${list.length} were passed." ,
117+ pstate, traces);
118+ }
119+ else if (list->length () < 3 ) {
120+ bool hasVar = false ;
121+ for (Expression* item : list->elements ()) {
122+ if (isVar (item)) {
123+ hasVar = true ;
124+ break ;
125+ }
126+ }
127+ if (hasVar || (!list->empty () && _isVarSlash (list->last ()))) {
128+ std::stringstream fncall;
129+ fncall << name << " (" ;
130+ for (size_t i = 0 , iL = list->length (); i < iL; i++) {
131+ if (i > 0 ) { fncall << " , " ; }
132+ fncall << list->get (i)->to_css ();
133+ }
134+ fncall << " )" ;
135+ return SASS_MEMORY_NEW (StringLiteral,
136+ pstate, fncall.str ());
137+ }
138+ else {
139+ std::string argument = argumentNames[list->length ()];
140+ error (
141+ " Missing element " + argument + " ." ,
142+ pstate, traces);
143+ }
144+ }
145+
146+ Number* secondNumber = Cast<Number>(list->get (2 ));
147+ String_Constant* secondString = Cast<String_Constant>(list->get (2 ));
148+ if (secondNumber && secondNumber->hasAsSlash ()) {
149+ List* rv = SASS_MEMORY_NEW (List, pstate);
150+ rv->append (list->get (0 ));
151+ rv->append (list->get (1 ));
152+ rv->append (secondNumber->lhsAsSlash ());
153+ rv->append (secondNumber->rhsAsSlash ());
154+ return rv;
155+ }
156+ else if (secondString &&
157+ // !maybeSlashSeparated.hasQuotes &&
158+ string_constains (secondString->value (), ' /' )) {
159+ std::stringstream fncall;
160+ fncall << name << " (" ;
161+ for (size_t i = 0 , iL = list->length (); i < iL; i++) {
162+ if (i > 0 ) { fncall << " , " ; }
163+ fncall << list->get (i)->to_css ();
164+
165+ }
166+ fncall << " )" ;
167+ return SASS_MEMORY_NEW (StringLiteral,
168+ pstate, fncall.str ());
169+ }
170+ else {
171+ return list;
172+ }
173+ }
174+ else {
175+ error (" $channels must be a space-separated list." ,
176+ pstate, traces);
177+ }
178+ return nullptr ;
179+ }
180+
71181 AST_Node* getArg (std::string name, Env& env)
72182 {
73183 if (env.has_local (name)) {
@@ -227,154 +337,53 @@ namespace Sass {
227337 return _rgbTwoArg (" rgba" , env, rgba_2_sig, pstate, traces);
228338 }
229339
230- // / Returns whether [value] is an unquoted string that start with `var(` and
231- // / contains `/`.
232- bool _isVarSlash (Expression* value) {
233- if (String_Constant * string = Cast<String_Constant>(value)) {
234- return starts_with (string->value (), " var(" ) &&
235- string_constains (string->value (), ' /' );
340+ Signature rgba_1_sig = " rgba($channels)" ;
341+ BUILT_IN (rgba_1)
342+ {
343+ Value* channels = ARG (" $channels" , Value, " a value" );
344+ ExpressionObj parsed = _parseChannels (" rgba" ,
345+ { " $red" , " $green" , " $blue" }, channels, pstate, traces);
346+ if (StringLiteral * str = Cast<StringLiteral>(parsed)) {
347+ return str;
236348 }
237- if (StringLiteral * string = Cast<StringLiteral>(value)) {
238- return starts_with (string->text (), " var(" ) &&
239- string_constains (string->text (), ' /' );
349+ if (List * list = Cast<List>(parsed)) {
350+ return _rgb (" rgba" , list->elements (), rgba_1_sig, pstate, traces);
240351 }
241- return false ;
352+ return nullptr ;
242353 }
243354
244-
245- Expression* _parseChannels (std::string name, std::vector<std::string> argumentNames, Value* channels, ParserState pstate, Backtraces traces )
355+ Signature rgb_4_sig = " rgb($red, $green, $blue, $alpha) " ;
356+ BUILT_IN (rgb_4 )
246357 {
247- if (isVar (channels)) {
248- std::stringstream fncall;
249- fncall << name << " ("
250- << channels->to_css () << " )" ;
251- return SASS_MEMORY_NEW (StringLiteral,
252- pstate, fncall.str ());
253- }
254-
255- // Expression* list = Listize::perform(channels);
256-
257- if (List * list = Cast<List>(channels)) {
258- bool isCommaSeparated = list->separator () == SASS_COMMA;
259- bool isBracketed = list->is_bracketed ();
260- if (isCommaSeparated || isBracketed) {
261- std::stringstream msg;
262- msg << " $channels must be" ;
263- if (isBracketed) msg << " an unbracketed" ;
264- if (isCommaSeparated) {
265- msg << (isBracketed ? " ," : " a" );
266- msg << " space-separated" ;
267- }
268- msg << " list." ;
269- error (msg.str (), pstate, traces);
270- }
271-
272- if (list->length () > 3 ) {
273- error (
274- " Only 3 elements allowed, but ${list.length} were passed." ,
275- pstate, traces);
276- }
277- else if (list->length () < 3 ) {
278- bool hasVar = false ;
279- for (Expression* item : list->elements ()) {
280- if (isVar (item)) {
281- hasVar = true ;
282- break ;
283- }
284- }
285- if (hasVar || (!list->empty () && _isVarSlash (list->last ()))) {
286- std::stringstream fncall;
287- fncall << name << " (" ;
288- for (size_t i = 0 , iL = list->length (); i < iL; i++) {
289- if (i > 0 ) { fncall << " , " ; }
290- fncall << list->get (i)->to_css ();
291- }
292- fncall << " )" ;
293- return SASS_MEMORY_NEW (StringLiteral,
294- pstate, fncall.str ());
295- }
296- else {
297- std::string argument = argumentNames[list->length ()];
298- error (
299- " Missing element " + argument + " ." ,
300- pstate, traces);
301- }
302- }
358+ return _rgb (" rgb" , env, rgb_4_sig, pstate, traces);
359+ }
303360
304- Number* secondNumber = Cast<Number>(list->get (2 ));
305- String_Constant* secondString = Cast<String_Constant>(list->get (2 ));
306- if (secondNumber && secondNumber->hasAsSlash ()) {
307- List* rv = SASS_MEMORY_NEW (List, pstate);
308- rv->append (list->get (0 ));
309- rv->append (list->get (1 ));
310- rv->append (secondNumber->lhsAsSlash ());
311- rv->append (secondNumber->rhsAsSlash ());
312- return rv;
313- }
314- else if (secondString &&
315- // !maybeSlashSeparated.hasQuotes &&
316- string_constains (secondString->value (), ' /' )) {
317- std::stringstream fncall;
318- fncall << name << " (" ;
319- for (size_t i = 0 , iL = list->length (); i < iL; i++) {
320- if (i > 0 ) { fncall << " , " ; }
321- fncall << list->get (i)->to_css ();
361+ Signature rgb_3_sig = " rgb($red, $green, $blue)" ;
362+ BUILT_IN (rgb_3)
363+ {
364+ return _rgb (" rgb" , env, rgb_3_sig, pstate, traces);
365+ }
322366
323- }
324- fncall << " )" ;
325- return SASS_MEMORY_NEW (StringLiteral,
326- pstate, fncall.str ());
327- }
328- else {
329- return list;
330- }
331- }
332- else {
333- error (" $channels must be a space-separated list." ,
334- pstate, traces);
335- }
336- return nullptr ;
367+ Signature rgb_2_sig = " rgb($color, $alpha)" ;
368+ BUILT_IN (rgb_2)
369+ {
370+ return _rgbTwoArg (" rgb" , env, rgb_2_sig, pstate, traces);
337371 }
338372
339- Signature rgba_1_sig = " rgba ($channels)" ;
340- BUILT_IN (rgba_1 )
373+ Signature rgb_1_sig = " rgb ($channels)" ;
374+ BUILT_IN (rgb_1 )
341375 {
342376 Value* channels = ARG (" $channels" , Value, " a value" );
343- ExpressionObj parsed = _parseChannels (" rgba " ,
377+ ExpressionObj parsed = _parseChannels (" rgb " ,
344378 { " $red" , " $green" , " $blue" }, channels, pstate, traces);
345379 if (StringLiteral * str = Cast<StringLiteral>(parsed)) {
346380 return str;
347381 }
348382 if (List * list = Cast<List>(parsed)) {
349- return _rgb (" rgb" , list->elements (), rgba_1_sig, pstate, traces);
350- }
351- }
352-
353- Signature rgb_sig = " rgb($red, $green, $blue)" ;
354- BUILT_IN (rgb)
355- {
356- if (
357- isSpecialNumber (env[" $red" ]) ||
358- isSpecialNumber (env[" $green" ]) ||
359- isSpecialNumber (env[" $blue" ])
360- ) {
361- return SASS_MEMORY_NEW (String_Constant, pstate, " rgb("
362- + env[" $red" ]->to_string ()
363- + " , "
364- + env[" $green" ]->to_string ()
365- + " , "
366- + env[" $blue" ]->to_string ()
367- + " )"
368- );
383+ return _rgb (" rgb" , list->elements (), rgb_1_sig, pstate, traces);
369384 }
370-
371- return SASS_MEMORY_NEW (Color_RGBA,
372- pstate,
373- COLOR_NUM (" $red" ),
374- COLOR_NUM (" $green" ),
375- COLOR_NUM (" $blue" ));
385+ return nullptr ;
376386 }
377-
378387 // //////////////
379388 // RGB FUNCTIONS
380389 // //////////////
0 commit comments