void Inspect::operator()(Complex_Selector* c) { Compound_Selector* head = c->head(); Complex_Selector* tail = c->tail(); Complex_Selector::Combinator comb = c->combinator(); if (c->has_line_feed()) { if (!(c->has_parent_ref())) { append_optional_linefeed(); append_indentation(); } } if (head && head->length() != 0) head->perform(this); bool is_empty = !head || head->length() == 0 || head->is_empty_reference(); bool is_tail = head && !head->is_empty_reference() && tail; if (output_style() == COMPRESSED && comb != Complex_Selector::ANCESTOR_OF) scheduled_space = 0; switch (comb) { case Complex_Selector::ANCESTOR_OF: if (is_tail) append_mandatory_space(); break; case Complex_Selector::PARENT_OF: append_optional_space(); append_string(">"); append_optional_space(); break; case Complex_Selector::ADJACENT_TO: append_optional_space(); append_string("+"); append_optional_space(); break; case Complex_Selector::REFERENCE: append_mandatory_space(); append_string("/"); c->reference()->perform(this); append_string("/"); append_mandatory_space(); break; case Complex_Selector::PRECEDES: if (is_empty) append_optional_space(); else append_mandatory_space(); append_string("~"); if (tail) append_mandatory_space(); else append_optional_space(); break; } if (tail && comb != Complex_Selector::ANCESTOR_OF) { if (c->has_line_break()) append_optional_linefeed(); } if (tail) tail->perform(this); if (!tail && c->has_line_break()) { if (output_style() == COMPACT) { append_mandatory_space(); } } }
bool Compound_Selector::operator==(const Compound_Selector& rhs) const { To_String to_string; // Check if pseudo-elements are the same between the selectors set<string> lpsuedoset, rpsuedoset; for (size_t i = 0, L = length(); i < L; ++i) { if ((*this)[i]->is_pseudo_element()) { string pseudo((*this)[i]->perform(&to_string)); pseudo = pseudo.substr(pseudo.find_first_not_of(":")); // strip off colons to ensure :after matches ::after since ruby sass is forgiving lpsuedoset.insert(pseudo); } } for (size_t i = 0, L = rhs.length(); i < L; ++i) { if (rhs[i]->is_pseudo_element()) { string pseudo(rhs[i]->perform(&to_string)); pseudo = pseudo.substr(pseudo.find_first_not_of(":")); // strip off colons to ensure :after matches ::after since ruby sass is forgiving rpsuedoset.insert(pseudo); } } if (lpsuedoset != rpsuedoset) { return false; } // Check the base const Simple_Selector* const lbase = base(); const Simple_Selector* const rbase = rhs.base(); if ((lbase && !rbase) || (!lbase && rbase) || ((lbase && rbase) && (*lbase != *rbase))) { return false; } // Check the rest of the SimpleSelectors // Use string representations. We can't create a set of Simple_Selector pointers because std::set == std::set is going to call == // on the pointers to determine equality. I don't know of a way to pass in a comparison object. The one you can specify as part of // the template type is used for ordering, but not equality. We also can't just put in non-pointer Simple_Selectors because the // class is intended to be subclassed, and we'd get splicing. set<string> lset, rset; for (size_t i = 0, L = length(); i < L; ++i) { lset.insert((*this)[i]->perform(&to_string)); } for (size_t i = 0, L = rhs.length(); i < L; ++i) { rset.insert(rhs[i]->perform(&to_string)); } return lset == rset; }
Selector* Contextualize::operator()(Compound_Selector* s) { To_String to_string; if (placeholder && extender && s->perform(&to_string) == placeholder->perform(&to_string)) { return extender; } Compound_Selector* ss = new (ctx.mem) Compound_Selector(s->path(), s->position(), s->length()); for (size_t i = 0, L = s->length(); i < L; ++i) { Simple_Selector* simp = static_cast<Simple_Selector*>((*s)[i]->perform(this)); if (simp) *ss << simp; } return ss->length() ? ss : 0; }
Selector* Contextualize::operator()(Compound_Selector* s) { To_String to_string(&ctx); if (placeholder && extender && s->perform(&to_string) == placeholder->perform(&to_string)) { return extender; } Compound_Selector* ss = new (ctx.mem) Compound_Selector(s->pstate(), s->length()); ss->last_block(s->last_block()); ss->media_block(s->media_block()); ss->has_line_break(s->has_line_break()); for (size_t i = 0, L = s->length(); i < L; ++i) { Simple_Selector* simp = static_cast<Simple_Selector*>((*s)[i]->perform(this)); if (simp) *ss << simp; } return ss->length() ? ss : 0; }