Skip to content

Commit 92e19f1

Browse files
committed
Merge pull request sass#718 from mgreter/fix/color-token-ops
Improve color token operations
2 parents 7aaa45a + ce36478 commit 92e19f1

File tree

5 files changed

+58
-23
lines changed

5 files changed

+58
-23
lines changed

ast.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,11 +1171,12 @@ namespace Sass {
11711171
ADD_PROPERTY(double, g);
11721172
ADD_PROPERTY(double, b);
11731173
ADD_PROPERTY(double, a);
1174+
ADD_PROPERTY(bool, sixtuplet);
11741175
ADD_PROPERTY(string, disp);
11751176
size_t hash_;
11761177
public:
1177-
Color(string path, Position position, double r, double g, double b, double a = 1, const string disp = "")
1178-
: Expression(path, position), r_(r), g_(g), b_(b), a_(a), disp_(disp),
1178+
Color(string path, Position position, double r, double g, double b, double a = 1, bool sixtuplet = true, const string disp = "")
1179+
: Expression(path, position), r_(r), g_(g), b_(b), a_(a), sixtuplet_(sixtuplet), disp_(disp),
11791180
hash_(0)
11801181
{ concrete_type(COLOR); }
11811182
string type() { return "color"; }

eval.cpp

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "eval.hpp"
22
#include "ast.hpp"
33
#include "bind.hpp"
4+
#include "util.hpp"
45
#include "to_string.hpp"
56
#include "inspect.hpp"
67
#include "to_c.hpp"
@@ -561,27 +562,35 @@ namespace Sass {
561562
Expression* result = 0;
562563
bool zero = !( t->value().substr(0, 1) == "." ||
563564
t->value().substr(0, 2) == "-." );
565+
566+
const string& text = t->value();
567+
size_t num_pos = text.find_first_not_of(" \n\r\t");
568+
if (num_pos == string::npos) num_pos = text.length();
569+
size_t unit_pos = text.find_first_not_of("-+0123456789.", num_pos);
570+
if (unit_pos == string::npos) unit_pos = text.length();
571+
const string& num = text.substr(num_pos, unit_pos - num_pos);
572+
564573
switch (t->type())
565574
{
566575
case Textual::NUMBER:
567576
result = new (ctx.mem) Number(t->path(),
568577
t->position(),
569-
atof(t->value().c_str()),
578+
atof(num.c_str()),
570579
"",
571580
zero);
572581
break;
573582
case Textual::PERCENTAGE:
574583
result = new (ctx.mem) Number(t->path(),
575584
t->position(),
576-
atof(t->value().c_str()),
585+
atof(num.c_str()),
577586
"%",
578587
zero);
579588
break;
580589
case Textual::DIMENSION:
581590
result = new (ctx.mem) Number(t->path(),
582591
t->position(),
583-
atof(t->value().c_str()),
584-
Token(number(t->value().c_str())),
592+
atof(num.c_str()),
593+
Token(number(text.c_str())),
585594
zero);
586595
break;
587596
case Textual::HEX: {
@@ -595,7 +604,7 @@ namespace Sass {
595604
static_cast<double>(strtol(r.c_str(), NULL, 16)),
596605
static_cast<double>(strtol(g.c_str(), NULL, 16)),
597606
static_cast<double>(strtol(b.c_str(), NULL, 16)),
598-
1,
607+
1, true,
599608
t->value());
600609
}
601610
else {
@@ -604,7 +613,7 @@ namespace Sass {
604613
static_cast<double>(strtol(string(2,hext[0]).c_str(), NULL, 16)),
605614
static_cast<double>(strtol(string(2,hext[1]).c_str(), NULL, 16)),
606615
static_cast<double>(strtol(string(2,hext[2]).c_str(), NULL, 16)),
607-
1,
616+
1, false,
608617
t->value());
609618
}
610619
} break;
@@ -938,11 +947,13 @@ namespace Sass {
938947
case Binary_Expression::DIV: {
939948
string sep(op == Binary_Expression::SUB ? "-" : "/");
940949
To_String to_string;
950+
string color(r->sixtuplet() ? r->perform(&to_string) :
951+
Util::normalize_sixtuplet(r->perform(&to_string)));
941952
return new (ctx.mem) String_Constant(l->path(),
942953
l->position(),
943954
l->perform(&to_string)
944955
+ sep
945-
+ r->perform(&to_string));
956+
+ color);
946957
} break;
947958
case Binary_Expression::MOD: {
948959
error("cannot divide a number by a color", r->path(), r->position());
@@ -992,27 +1003,30 @@ namespace Sass {
9921003
Expression::Concrete_Type ltype = lhs->concrete_type();
9931004
Expression::Concrete_Type rtype = rhs->concrete_type();
9941005

995-
// TODO: currently SASS converts colors to standard form when adding to strings;
996-
// when https://github.com/nex3/sass/issues/363 is added this can be removed to
997-
// preserve the original value
998-
if (ltype == Expression::COLOR) ((Sass::Color*)lhs)->disp("");
999-
if (rtype == Expression::COLOR) ((Sass::Color*)rhs)->disp("");
1000-
10011006
string lstr(lhs->perform(&to_string));
10021007
string rstr(rhs->perform(&to_string));
1008+
1009+
bool l_str_quoted = ((Sass::String*)lhs) && ((Sass::String*)lhs)->needs_unquoting();
1010+
bool r_str_quoted = ((Sass::String*)rhs) && ((Sass::String*)rhs)->needs_unquoting();
1011+
bool l_str_color = ltype == Expression::STRING && ctx.names_to_colors.count(lstr) && !l_str_quoted;
1012+
bool r_str_color = rtype == Expression::STRING && ctx.names_to_colors.count(rstr) && !r_str_quoted;
1013+
10031014
bool unquoted = false;
10041015
if (ltype == Expression::STRING && lstr[0] != '"' && lstr[0] != '\'') unquoted = true;
1005-
if (ltype == Expression::STRING && !lhs->is_delayed() && ctx.names_to_colors.count(lstr) &&
1006-
rtype == Expression::STRING && !rhs->is_delayed() && ctx.names_to_colors.count(rstr)) {
1016+
if (l_str_color && r_str_color) {
10071017
return op_colors(ctx, op, ctx.names_to_colors[lstr], ctx.names_to_colors[rstr]);
10081018
}
1009-
else if (ltype == Expression::STRING && !lhs->is_delayed() && ctx.names_to_colors.count(lstr) &&
1010-
rtype == Expression::NUMBER) {
1019+
else if (l_str_color && rtype == Expression::COLOR) {
1020+
return op_colors(ctx, op, ctx.names_to_colors[lstr], rhs);
1021+
}
1022+
else if (l_str_color && rtype == Expression::NUMBER) {
10111023
return op_color_number(ctx, op, ctx.names_to_colors[lstr], rhs);
10121024
}
1013-
else if (ltype == Expression::NUMBER &&
1014-
rtype == Expression::STRING && !rhs->is_delayed() && ctx.names_to_colors.count(rstr)) {
1015-
return op_number_color(ctx, op, rhs, ctx.names_to_colors[rstr]);
1025+
else if (ltype == Expression::COLOR && r_str_color) {
1026+
return op_number_color(ctx, op, lhs, ctx.names_to_colors[rstr]);
1027+
}
1028+
else if (ltype == Expression::NUMBER && r_str_color) {
1029+
return op_number_color(ctx, op, lhs, ctx.names_to_colors[rstr]);
10161030
}
10171031
if (op == Binary_Expression::MUL) error("invalid operands for multiplication", lhs->path(), lhs->position());
10181032
if (op == Binary_Expression::MOD) error("invalid operands for modulo", lhs->path(), lhs->position());

functions.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -734,8 +734,11 @@ namespace Sass {
734734
{
735735
To_String to_string;
736736
AST_Node* arg = env["$string"];
737-
string str(unquote(arg->perform(&to_string)));
737+
string org(arg->perform(&to_string));
738+
string str(unquote(org));
738739
String_Constant* result = new (ctx.mem) String_Constant(path, position, str);
740+
// remember if the string was quoted (color tokens)
741+
if (org[0] != str[0]) result->needs_unquoting(true);
739742
result->is_delayed(true);
740743
return result;
741744
}

util.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,22 @@ namespace Sass {
2121
return normalized[0] == '.' ? normalized.insert(0, prefix) : normalized;
2222
}
2323

24+
// compress a color sixtuplet if possible
25+
// input: "#CC9900" -> output: "#C90"
26+
string normalize_sixtuplet(const string& col) {
27+
if(
28+
col.substr(1, 1) == col.substr(2, 1) &&
29+
col.substr(3, 1) == col.substr(4, 1) &&
30+
col.substr(5, 1) == col.substr(6, 1)
31+
) {
32+
return string("#" + col.substr(1, 1)
33+
+ col.substr(3, 1)
34+
+ col.substr(5, 1));
35+
} else {
36+
return string(col);
37+
}
38+
}
39+
2440
bool isPrintable(Ruleset* r) {
2541
if (r == NULL) {
2642
return false;

util.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ namespace Sass {
1111

1212
std::string normalize_underscores(const std::string& str);
1313
std::string normalize_decimals(const std::string& str);
14+
std::string normalize_sixtuplet(const std::string& col);
1415

1516
bool containsAnyPrintableStatements(Block* b);
1617

0 commit comments

Comments
 (0)