Skip to content

Commit 9037eda

Browse files
authored
Merge pull request #2528 from mgreter/feature/attribute-selector-modifier
Implement case modifier for attribute selector
2 parents 9d8b9e5 + 6001090 commit 9037eda

File tree

9 files changed

+65
-6
lines changed

9 files changed

+65
-6
lines changed

src/ast.hpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2579,14 +2579,16 @@ namespace Sass {
25792579
ADD_CONSTREF(std::string, matcher)
25802580
// this cannot be changed to obj atm!!!!!!????!!!!!!!
25812581
ADD_PROPERTY(String_Obj, value) // might be interpolated
2582+
ADD_PROPERTY(char, modifier);
25822583
public:
2583-
Attribute_Selector(ParserState pstate, std::string n, std::string m, String_Obj v)
2584-
: Simple_Selector(pstate, n), matcher_(m), value_(v)
2584+
Attribute_Selector(ParserState pstate, std::string n, std::string m, String_Obj v, char o = 0)
2585+
: Simple_Selector(pstate, n), matcher_(m), value_(v), modifier_(o)
25852586
{ simple_type(ATTR_SEL); }
25862587
Attribute_Selector(const Attribute_Selector* ptr)
25872588
: Simple_Selector(ptr),
25882589
matcher_(ptr->matcher_),
2589-
value_(ptr->value_)
2590+
value_(ptr->value_),
2591+
modifier_(ptr->modifier_)
25902592
{ simple_type(ATTR_SEL); }
25912593
virtual size_t hash()
25922594
{

src/emitter.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,17 @@ namespace Sass {
105105
wbuf.buffer = text + wbuf.buffer;
106106
}
107107

108+
// append a single char to the buffer
109+
void Emitter::append_char(const char chr)
110+
{
111+
// write space/lf
112+
flush_schedules();
113+
// add to buffer
114+
wbuf.buffer += chr;
115+
// account for data in source-maps
116+
wbuf.smap.append(Offset(chr));
117+
}
118+
108119
// append some text or token to the buffer
109120
void Emitter::append_string(const std::string& text)
110121
{

src/emitter.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ namespace Sass {
6666
void prepend_output(const OutputBuffer& out);
6767
// append some text or token to the buffer
6868
void append_string(const std::string& text);
69+
// append a single character to buffer
70+
void append_char(const char chr);
6971
// append some white-space only text
7072
void append_wspace(const std::string& text);
7173
// append some text or token to the buffer

src/inspect.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -965,6 +965,10 @@ namespace Sass {
965965
}
966966
}
967967
add_close_mapping(s);
968+
if (s->modifier() != 0) {
969+
append_mandatory_space();
970+
append_char(s->modifier());
971+
}
968972
append_string("]");
969973
}
970974

src/lexer.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,14 @@ namespace Sass {
110110
}
111111

112112

113+
// Match a single character literal.
114+
// Regex equivalent: /(?:x)/i
115+
// only define lower case alpha chars
116+
template <char chr>
117+
const char* insensitive(const char* src) {
118+
return *src == chr || *src+32 == chr ? src + 1 : 0;
119+
}
120+
113121
// Match the full string literal.
114122
// Regex equivalent: /(?:literal)/i
115123
// only define lower case alpha chars

src/parser.cpp

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -954,12 +954,28 @@ namespace Sass {
954954
return 0;
955955
}
956956

957+
const char* Parser::re_attr_sensitive_close(const char* src)
958+
{
959+
return alternatives < exactly<']'>, exactly<'/'> >(src);
960+
}
961+
962+
const char* Parser::re_attr_insensitive_close(const char* src)
963+
{
964+
return sequence < insensitive<'i'>, re_attr_sensitive_close >(src);
965+
}
966+
957967
Attribute_Selector_Obj Parser::parse_attribute_selector()
958968
{
959969
ParserState p = pstate;
960970
if (!lex_css< attribute_name >()) error("invalid attribute name in attribute selector", pstate);
961971
std::string name(lexed);
962-
if (lex_css< alternatives < exactly<']'>, exactly<'/'> > >()) return SASS_MEMORY_NEW(Attribute_Selector, p, name, "", 0);
972+
if (lex_css< re_attr_sensitive_close >()) {
973+
return SASS_MEMORY_NEW(Attribute_Selector, p, name, "", 0, 0);
974+
}
975+
else if (lex_css< re_attr_insensitive_close >()) {
976+
char modifier = lexed.begin[0];
977+
return SASS_MEMORY_NEW(Attribute_Selector, p, name, "", 0, modifier);
978+
}
963979
if (!lex_css< alternatives< exact_match, class_match, dash_match,
964980
prefix_match, suffix_match, substring_match > >()) {
965981
error("invalid operator in attribute selector for " + name, pstate);
@@ -977,8 +993,15 @@ namespace Sass {
977993
error("expected a string constant or identifier in attribute selector for " + name, pstate);
978994
}
979995

980-
if (!lex_css< alternatives < exactly<']'>, exactly<'/'> > >()) error("unterminated attribute selector for " + name, pstate);
981-
return SASS_MEMORY_NEW(Attribute_Selector, p, name, matcher, value);
996+
if (lex_css< re_attr_sensitive_close >()) {
997+
return SASS_MEMORY_NEW(Attribute_Selector, p, name, matcher, value, 0);
998+
}
999+
else if (lex_css< re_attr_insensitive_close >()) {
1000+
char modifier = lexed.begin[0];
1001+
return SASS_MEMORY_NEW(Attribute_Selector, p, name, matcher, value, modifier);
1002+
}
1003+
error("unterminated attribute selector for " + name, pstate);
1004+
return NULL; // to satisfy compilers (error must not return)
9821005
}
9831006

9841007
/* parse block comment and add to block */

src/parser.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,9 @@ namespace Sass {
379379
Number_Ptr lexed_percentage(const std::string& parsed) { return lexed_percentage(pstate, parsed); };
380380
Expression_Ptr lexed_hex_color(const std::string& parsed) { return lexed_hex_color(pstate, parsed); };
381381

382+
static const char* re_attr_sensitive_close(const char* src);
383+
static const char* re_attr_insensitive_close(const char* src);
384+
382385
};
383386

384387
size_t check_bom_chars(const char* src, const char *end, const unsigned char* bom, size_t len);

src/position.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
namespace Sass {
55

66

7+
Offset::Offset(const char chr)
8+
: line(chr == '\n' ? 1 : 0),
9+
column(chr == '\n' ? 0 : 1)
10+
{}
11+
712
Offset::Offset(const char* string)
813
: line(0), column(0)
914
{

src/position.hpp

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

1313
public: // c-tor
14+
Offset(const char chr);
1415
Offset(const char* string);
1516
Offset(const std::string& text);
1617
Offset(const size_t line, const size_t column);

0 commit comments

Comments
 (0)