Skip to content

Commit 4d3fe32

Browse files
committed
Correctly handle interpolants in url() strings
1 parent 2e15e46 commit 4d3fe32

File tree

7 files changed

+59
-16
lines changed

7 files changed

+59
-16
lines changed

src/constants.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ namespace Sass {
7979
extern const char only_kwd[] = "only";
8080
extern const char rgb_kwd[] = "rgb(";
8181
extern const char url_kwd[] = "url(";
82+
// extern const char url_prefix_kwd[] = "url-prefix(";
8283
extern const char important_kwd[] = "important";
8384
extern const char pseudo_not_kwd[] = ":not(";
8485
extern const char even_kwd[] = "even";

src/constants.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ namespace Sass {
8080
extern const char only_kwd[];
8181
extern const char rgb_kwd[];
8282
extern const char url_kwd[];
83+
// extern const char url_prefix_kwd[];
8384
extern const char image_url_kwd[];
8485
extern const char important_kwd[];
8586
extern const char pseudo_not_kwd[];

src/parser.cpp

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1405,7 +1405,7 @@ namespace Sass {
14051405
}
14061406
return string;
14071407
}
1408-
else if (peek< real_uri_value >()) {
1408+
else if (peek< sequence< uri_prefix, W, real_uri_value > >()) {
14091409
return parse_url_function_string();
14101410
}
14111411
else if (peek< re_functional >()) {
@@ -1790,8 +1790,28 @@ namespace Sass {
17901790

17911791
String* Parser::parse_url_function_string()
17921792
{
1793-
lex< real_uri_value >();
1794-
return SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, lexed);
1793+
const char* p = position;
1794+
1795+
lex< uri_prefix >();
1796+
std::string prefix = lexed;
1797+
1798+
lex< real_uri_value >(false);
1799+
std::string uri = lexed;
1800+
1801+
if (peek< exactly< hash_lbrace > >()) {
1802+
const char* pp = position;
1803+
// TODO: error checking for unclosed interpolants
1804+
while (peek< exactly< hash_lbrace > >(pp)) {
1805+
pp = sequence< interpolant, real_uri_value >(pp);
1806+
}
1807+
position = peek< real_uri_suffix >(pp);
1808+
return parse_interpolated_chunk(Token(p, position));
1809+
} else {
1810+
lex< real_uri_suffix >();
1811+
std::string res = prefix + Util::rtrim(uri) + lexed.to_string();
1812+
return SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, res);
1813+
}
1814+
17951815
}
17961816

17971817
Function_Call* Parser::parse_function_call()

src/prelexer.cpp

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -951,23 +951,31 @@ namespace Sass {
951951
}
952952

953953

954+
// const char* real_uri_prefix(const char* src) {
955+
// return alternatives<
956+
// exactly< url_kwd >,
957+
// exactly< url_prefix_kwd >
958+
// >(src);
959+
// }
960+
961+
const char* real_uri_suffix(const char* src) {
962+
return sequence< W, exactly< ')' > >(src);
963+
}
964+
954965
const char* real_uri_value(const char* src) {
955966
return
956967
sequence<
957-
exactly< url_kwd >,
958-
W,
959-
zero_plus< alternatives<
960-
class_char< real_uri_chars >,
961-
uri_character,
962-
NONASCII,
963-
ESCAPE
964-
> >,
965-
alternatives<
966-
sequence<
967-
W,
968-
exactly< ')' >
968+
non_greedy<
969+
alternatives<
970+
class_char< real_uri_chars >,
971+
uri_character,
972+
NONASCII,
973+
ESCAPE
969974
>,
970-
exactly< hash_lbrace >
975+
alternatives<
976+
real_uri_suffix,
977+
exactly< hash_lbrace >
978+
>
971979
>
972980
>
973981
(src);

src/prelexer.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,8 @@ namespace Sass {
347347
const char* UUNICODE(const char* src);
348348
const char* NONASCII(const char* src);
349349
const char* ESCAPE(const char* src);
350+
const char* real_uri_suffix(const char* src);
351+
// const char* real_uri_prefix(const char* src);
350352
const char* real_uri_value(const char* src);
351353

352354
// Path matching functions.

src/util.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,15 @@ namespace Sass {
529529
namespace Util {
530530
using std::string;
531531

532+
std::string rtrim(const std::string &str) {
533+
std::string trimmed = str;
534+
size_t pos_ws = trimmed.find_last_not_of(" \t\n\v\f\r");
535+
if (pos_ws != std::string::npos)
536+
{ trimmed.erase(pos_ws + 1); }
537+
else { trimmed.clear(); }
538+
return trimmed;
539+
}
540+
532541
std::string normalize_underscores(const std::string& str) {
533542
std::string normalized = str;
534543
for(size_t i = 0, L = normalized.length(); i < L; ++i) {

src/util.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ namespace Sass {
3636

3737
namespace Util {
3838

39+
std::string rtrim(const std::string& str);
40+
3941
std::string normalize_underscores(const std::string& str);
4042
std::string normalize_decimals(const std::string& str);
4143
std::string normalize_sixtuplet(const std::string& col);

0 commit comments

Comments
 (0)