Skip to content

Commit

Permalink
Implement extend for wrapped selectors
Browse files Browse the repository at this point in the history
  • Loading branch information
mgreter committed Jan 9, 2016
1 parent 92ddab3 commit 964613e
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 25 deletions.
18 changes: 13 additions & 5 deletions src/ast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -971,11 +971,12 @@ namespace Sass {

if (head && head->length() > 0) {

Selector_List* retval = 0;
// we have a parent selector in a simple compound list
// mix parent complex selector into the compound list
if (dynamic_cast<Parent_Selector*>((*head)[0])) {
retval = SASS_MEMORY_NEW(ctx.mem, Selector_List, pstate());
if (parents && parents->length()) {
Selector_List* retval = SASS_MEMORY_NEW(ctx.mem, Selector_List, pstate());
if (tails && tails->length() > 0) {
for (size_t n = 0, nL = tails->length(); n < nL; ++n) {
for (size_t i = 0, iL = parents->length(); i < iL; ++i) {
Expand Down Expand Up @@ -1014,11 +1015,9 @@ namespace Sass {
*retval << s;
}
}
return retval;
}
// have no parent but some tails
else {
Selector_List* retval = SASS_MEMORY_NEW(ctx.mem, Selector_List, pstate());
if (tails && tails->length() > 0) {
for (size_t n = 0, nL = tails->length(); n < nL; ++n) {
Complex_Selector* cpy = this->clone(ctx);
Expand All @@ -1039,14 +1038,23 @@ namespace Sass {
if (!cpy->head()->length()) cpy->head(0);
*retval << cpy->skip_empty_reference();
}
return retval;
}
}
// no parent selector in head
else {
return this->tails(ctx, tails);
retval = this->tails(ctx, tails);
}

for (Simple_Selector* ss : *head) {
if (Wrapped_Selector* ws = dynamic_cast<Wrapped_Selector*>(ss)) {
if (Selector_List* sl = dynamic_cast<Selector_List*>(ws->selector())) {
if (parents) ws->selector(sl->parentize(parents, ctx));
}
}
}

return retval;

}
// has no head
else {
Expand Down
29 changes: 17 additions & 12 deletions src/expand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -534,15 +534,11 @@ namespace Sass {
return 0;
}

Statement* Expand::operator()(Extension* e)
{
To_String to_string(&ctx);
Selector_List* extender = dynamic_cast<Selector_List*>(selector());
if (!extender) return 0;
selector_stack.push_back(0);

if (Selector_List* selector_list = dynamic_cast<Selector_List*>(e->selector())) {
for (Complex_Selector* complex_selector : selector_list->elements()) {
void Expand::expand_selector_list(Selector* s, Selector_List* extender) {

if (Selector_List* sl = dynamic_cast<Selector_List*>(s)) {
for (Complex_Selector* complex_selector : sl->elements()) {
Complex_Selector* tail = complex_selector;
while (tail) {
if (tail->head()) for (Simple_Selector* header : tail->head()->elements()) {
Expand All @@ -555,16 +551,17 @@ namespace Sass {
}
}

Selector_List* contextualized = dynamic_cast<Selector_List*>(e->selector()->perform(&eval));
if (contextualized == NULL) return 0;

Selector_List* contextualized = dynamic_cast<Selector_List*>(s->perform(&eval));
if (contextualized == NULL) return;
for (auto complex_sel : contextualized->elements()) {
Complex_Selector* c = complex_sel;
if (!c->head() || c->tail()) {
To_String to_string(&ctx); std::string sel_str(contextualized->perform(&to_string));
error("Can't extend " + sel_str + ": can't extend nested selectors", c->pstate(), backtrace());
}
Compound_Selector* placeholder = c->head();
placeholder->is_optional(e->selector()->is_optional());
placeholder->is_optional(s->is_optional());
for (size_t i = 0, L = extender->length(); i < L; ++i) {
Complex_Selector* sel = (*extender)[i];
if (!(sel->head() && sel->head()->length() > 0 &&
Expand All @@ -587,8 +584,16 @@ namespace Sass {
}
}

selector_stack.pop_back();
}

Statement* Expand::operator()(Extension* e)
{
if (Selector_List* extender = dynamic_cast<Selector_List*>(selector())) {
selector_stack.push_back(0);
Selector* s = e->selector();
expand_selector_list(s, extender);
selector_stack.pop_back();
}
return 0;
}

Expand Down
3 changes: 3 additions & 0 deletions src/expand.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ namespace Sass {

Statement* fallback_impl(AST_Node* n);

private:
void expand_selector_list(Selector*, Selector_List* extender);

public:
Expand(Context&, Env*, Backtrace*);
virtual ~Expand() { }
Expand Down
27 changes: 27 additions & 0 deletions src/extend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1732,6 +1732,18 @@ namespace Sass {
Compound_Selector* pHead = pIter->head();

if (pHead) {
for (Simple_Selector* pSimple : *pHead) {
if (Wrapped_Selector* ws = dynamic_cast<Wrapped_Selector*>(pSimple)) {
if (Selector_List* sl = dynamic_cast<Selector_List*>(ws->selector())) {
for (Complex_Selector* cs : sl->elements()) {
if (complexSelectorHasExtension(cs, ctx, subset_map)) {
hasExtension = true;
break;
}
}
}
}
}
SubsetMapEntries entries = subset_map.get_v(pHead->to_str_vec());
for (ExtensionPair ext : entries) {
// check if both selectors have the same media block parent
Expand Down Expand Up @@ -1967,6 +1979,21 @@ namespace Sass {
}
}

for (Complex_Selector* cs : *pNewSelectors) {
while (cs) {
if (cs->head()) {
for (Simple_Selector* ss : *cs->head()) {
if (Wrapped_Selector* ws = dynamic_cast<Wrapped_Selector*>(ss)) {
if (Selector_List* sl = dynamic_cast<Selector_List*>(ws->selector())) {
bool extended = false;
ws->selector(extendSelectorList(sl, ctx, subset_map, false, extended));
}
}
}
}
cs = cs->tail();
}
}
return pNewSelectors;

}
Expand Down
42 changes: 34 additions & 8 deletions src/remove_placeholders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,47 @@ namespace Sass {
}
}

Selector_List* Remove_Placeholders::remove_placeholders(Selector_List* sl)
{
Selector_List* new_sl = SASS_MEMORY_NEW(ctx.mem, Selector_List, sl->pstate());

for (size_t i = 0, L = sl->length(); i < L; ++i) {
if (!(*sl)[i]->contains_placeholder()) {
*new_sl << (*sl)[i];
}
}

return new_sl;

}


void Remove_Placeholders::operator()(Ruleset* r) {
// Create a new selector group without placeholders
Selector_List* sl = static_cast<Selector_List*>(r->selector());

if (sl) {
Selector_List* new_sl = SASS_MEMORY_NEW(ctx.mem, Selector_List, sl->pstate());

for (size_t i = 0, L = sl->length(); i < L; ++i) {
if (!(*sl)[i]->contains_placeholder()) {
*new_sl << (*sl)[i];
// Set the new placeholder selector list
r->selector(remove_placeholders(sl));
// Remove placeholders in wrapped selectors
for (Complex_Selector* cs : *sl) {
while (cs) {
if (cs->head()) {
for (Simple_Selector* ss : *cs->head()) {
if (Wrapped_Selector* ws = dynamic_cast<Wrapped_Selector*>(ss)) {
if (Selector_List* sl = dynamic_cast<Selector_List*>(ws->selector())) {
Selector_List* clean = remove_placeholders(sl);
// also clean superflous parent selectors
// probably not really the correct place
clean->remove_parent_selectors();
ws->selector(clean);
}
}
}
}
cs = cs->tail();
}

// Set the new placeholder selector list
r->selector(new_sl);
}
}

// Iterate into child blocks
Expand Down
3 changes: 3 additions & 0 deletions src/remove_placeholders.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ namespace Sass {

void fallback_impl(AST_Node* n) {}

private:
Selector_List* remove_placeholders(Selector_List*);

public:
Remove_Placeholders(Context&);
virtual ~Remove_Placeholders() { }
Expand Down

0 comments on commit 964613e

Please sign in to comment.