void Cssize::append_block(Block* b) { Block* current_block = block_stack.back(); for (size_t i = 0, L = b->length(); i < L; ++i) { Statement* ith = (*b)[i]->perform(this); if (ith && ith->block()) { for (size_t j = 0, K = ith->block()->length(); j < K; ++j) { *current_block << (*ith->block())[j]; } } else if (ith) { *current_block << ith; } } }
Statement* Cssize::operator()(At_Rule* r) { if (!r->block() || !r->block()->length()) return r; if (parent()->statement_type() == Statement::RULESET) { return (r->is_keyframes()) ? SASS_MEMORY_NEW(ctx.mem, Bubble, r->pstate(), r) : bubble(r); } p_stack.push_back(r); At_Rule* rr = SASS_MEMORY_NEW(ctx.mem, At_Rule, r->pstate(), r->keyword(), r->selector(), r->block() ? r->block()->perform(this)->block() : 0); if (r->value()) rr->value(r->value()); p_stack.pop_back(); bool directive_exists = false; size_t L = rr->block() ? rr->block()->length() : 0; for (size_t i = 0; i < L && !directive_exists; ++i) { Statement* s = (*r->block())[i]; if (s->statement_type() != Statement::BUBBLE) directive_exists = true; else { s = static_cast<Bubble*>(s)->node(); if (s->statement_type() != Statement::DIRECTIVE) directive_exists = false; else directive_exists = (static_cast<At_Rule*>(s)->keyword() == rr->keyword()); } } Block* result = SASS_MEMORY_NEW(ctx.mem, Block, rr->pstate()); if (!(directive_exists || rr->is_keyframes())) { At_Rule* empty_node = static_cast<At_Rule*>(rr); empty_node->block(SASS_MEMORY_NEW(ctx.mem, Block, rr->block() ? rr->block()->pstate() : rr->pstate())); *result << empty_node; } Statement* ss = debubble(rr->block() ? rr->block() : SASS_MEMORY_NEW(ctx.mem, Block, rr->pstate()), rr); for (size_t i = 0, L = ss->block()->length(); i < L; ++i) { *result << (*ss->block())[i]; } return result; }
Statement* Cssize::flatten(Statement* s) { Block* bb = s->block(); Block* result = SASS_MEMORY_NEW(ctx.mem, Block, bb->pstate(), 0, bb->is_root()); for (size_t i = 0, L = bb->length(); i < L; ++i) { Statement* ss = (*bb)[i]; if (ss->block()) { ss = flatten(ss); for (size_t j = 0, K = ss->block()->length(); j < K; ++j) { *result << (*ss->block())[j]; } } else { *result << ss; } } return result; }
void Output_Nested::operator()(Media_Block* m) { List* q = m->media_queries(); Block* b = m->block(); bool decls = false; indent(); ctx->source_map.add_mapping(m); append_singleline_part_to_buffer("@media "); q->perform(this); append_multiline_part_to_buffer(" {\n"); Selector* e = m->enclosing_selector(); bool hoisted = false; if (e && b->has_non_hoistable()) { hoisted = true; ++indentation; indent(); e->perform(this); append_multiline_part_to_buffer(" {\n"); } ++indentation; decls = true; for (size_t i = 0, L = b->length(); i < L; ++i) { Statement* stm = (*b)[i]; if (!stm->is_hoistable()) { if (!stm->block()) indent(); stm->perform(this); append_multiline_part_to_buffer("\n"); } } --indentation; if (hoisted) { buffer.erase(buffer.length()-1); if (ctx) ctx->source_map.remove_line(); append_multiline_part_to_buffer(" }\n"); --indentation; } if (decls) ++indentation; if (hoisted) ++indentation; for (size_t i = 0, L = b->length(); i < L; ++i) { Statement* stm = (*b)[i]; if (stm->is_hoistable()) { stm->perform(this); } } if (hoisted) --indentation; if (decls) --indentation; buffer.erase(buffer.length()-1); if (ctx) ctx->source_map.remove_line(); append_multiline_part_to_buffer(" }\n"); }
void Output_Nested::operator()(At_Rule* a) { string kwd = a->keyword(); Selector* s = a->selector(); Expression* v = a->value(); Block* b = a->block(); bool decls = false; // indent(); append_to_buffer(kwd); if (s) { append_to_buffer(" "); s->perform(this); } else if (v) { append_to_buffer(" "); v->perform(this); } if (!b) { append_to_buffer(";"); return; } append_to_buffer(" {\n"); ++indentation; decls = true; for (size_t i = 0, L = b->length(); i < L; ++i) { Statement* stm = (*b)[i]; if (!stm->is_hoistable()) { if (!stm->block()) indent(); stm->perform(this); append_to_buffer("\n"); } } --indentation; if (decls) ++indentation; for (size_t i = 0, L = b->length(); i < L; ++i) { Statement* stm = (*b)[i]; if (stm->is_hoistable()) { stm->perform(this); append_to_buffer("\n"); } } if (decls) --indentation; buffer.erase(buffer.length()-1); if (ctx) ctx->source_map.remove_line(); if (b->has_hoistable()) { buffer.erase(buffer.length()-1); if (ctx) ctx->source_map.remove_line(); } append_to_buffer(" }\n"); }
void Output_Nested::operator()(Media_Block* m) { List* q = m->media_queries(); Block* b = m->block(); bool decls = false; indent(); buffer += "@media "; q->perform(this); buffer += " {\n"; Selector* e = m->enclosing_selector(); bool hoisted = false; if (e && b->has_non_hoistable()) { hoisted = true; ++indentation; indent(); e->perform(this); buffer += " {\n"; } ++indentation; decls = true; for (size_t i = 0, L = b->length(); i < L; ++i) { Statement* stm = (*b)[i]; if (!stm->is_hoistable()) { if (!stm->block()) indent(); stm->perform(this); buffer += '\n'; } } --indentation; if (hoisted) { buffer.erase(buffer.length()-1); buffer += " }\n"; --indentation; } if (decls) ++indentation; if (hoisted) ++indentation; for (size_t i = 0, L = b->length(); i < L; ++i) { Statement* stm = (*b)[i]; if (stm->is_hoistable()) { stm->perform(this); } } if (hoisted) --indentation; if (decls) --indentation; buffer.erase(buffer.length()-1); buffer += " }\n"; }
void Output_Nested::operator()(At_Rule* a) { string kwd = a->keyword(); Selector* s = a->selector(); Block* b = a->block(); bool decls = false; // indent(); buffer += kwd; if (s) { buffer += ' '; s->perform(this); } if (!b) { buffer += ';'; return; } buffer += " {\n"; ++indentation; decls = true; for (size_t i = 0, L = b->length(); i < L; ++i) { Statement* stm = (*b)[i]; if (!stm->is_hoistable()) { if (!stm->block()) indent(); stm->perform(this); buffer += '\n'; } } --indentation; if (decls) ++indentation; for (size_t i = 0, L = b->length(); i < L; ++i) { Statement* stm = (*b)[i]; if (stm->is_hoistable()) { stm->perform(this); buffer += '\n'; } } if (decls) --indentation; buffer.erase(buffer.length()-1); if (b->has_hoistable()) { buffer.erase(buffer.length()-1); } buffer += " }\n"; }
void Output_Nested::operator()(Ruleset* r) { Selector* s = r->selector(); Block* b = r->block(); bool decls = false; if (s->has_placeholder()) return; if (b->has_non_hoistable()) { decls = true; indent(); if (source_comments) { stringstream ss; ss << "/* line " << r->line() << ", " << r->path() << " */" << endl; buffer += ss.str(); indent(); } s->perform(this); buffer += " {\n"; ++indentation; for (size_t i = 0, L = b->length(); i < L; ++i) { Statement* stm = (*b)[i]; if (!stm->is_hoistable()) { if (!stm->block()) indent(); stm->perform(this); buffer += '\n'; } } --indentation; buffer.erase(buffer.length()-1); buffer += " }\n"; } if (b->has_hoistable()) { if (decls) ++indentation; // indent(); for (size_t i = 0, L = b->length(); i < L; ++i) { Statement* stm = (*b)[i]; if (stm->is_hoistable()) { stm->perform(this); } } if (decls) --indentation; } }
void Output_Nested::operator()(Ruleset* r) { Selector* s = r->selector(); Block* b = r->block(); bool decls = false; if (s->has_placeholder()) return; if (b->has_non_hoistable()) { decls = true; indent(); if (source_comments) { stringstream ss; ss << "/* line " << r->line() << ", " << r->path() << " */" << endl; buffer += ss.str(); indent(); } s->perform(this); buffer += " {\n"; ++indentation; for (size_t i = 0, L = b->length(); i < L; ++i) { Statement* stm = (*b)[i]; bool bPrintExpression = true; // Check print conditions if (typeid(*stm) == typeid(Declaration)) { Declaration* dec = static_cast<Declaration*>(stm); if (dec->value()->concrete_type() == Expression::STRING) { String_Constant* valConst = static_cast<String_Constant*>(dec->value()); string val(valConst->value()); if (val.empty()) { bPrintExpression = false; } } else if (dec->value()->concrete_type() == Expression::LIST) { List* list = static_cast<List*>(dec->value()); bool all_invisible = true; for (size_t list_i = 0, list_L = list->length(); list_i < list_L; ++list_i) { Expression* item = (*list)[list_i]; if (!item->is_invisible()) all_invisible = false; } if (all_invisible) bPrintExpression = false; } } // Print if OK if (!stm->is_hoistable() && bPrintExpression) { if (!stm->block()) indent(); stm->perform(this); buffer += '\n'; } } --indentation; buffer.erase(buffer.length()-1); buffer += " }\n"; } if (b->has_hoistable()) { if (decls) ++indentation; // indent(); for (size_t i = 0, L = b->length(); i < L; ++i) { Statement* stm = (*b)[i]; if (stm->is_hoistable()) { stm->perform(this); } } if (decls) --indentation; } }
Statement* Cssize::debubble(Block* children, Statement* parent) { Has_Block* previous_parent = 0; std::vector<std::pair<bool, Block*>> baz = slice_by_bubble(children); Block* result = SASS_MEMORY_NEW(ctx.mem, Block, children->pstate()); for (size_t i = 0, L = baz.size(); i < L; ++i) { bool is_bubble = baz[i].first; Block* slice = baz[i].second; if (!is_bubble) { if (!parent) { *result << slice; } else if (previous_parent) { *previous_parent->block() += slice; } else { previous_parent = static_cast<Has_Block*>(shallow_copy(parent)); previous_parent->tabs(parent->tabs()); Has_Block* new_parent = static_cast<Has_Block*>(shallow_copy(parent)); new_parent->block(slice); new_parent->tabs(parent->tabs()); *result << new_parent; } continue; } Block* wrapper_block = SASS_MEMORY_NEW(ctx.mem, Block, children->block()->pstate(), children->block()->length(), children->block()->is_root()); for (size_t j = 0, K = slice->length(); j < K; ++j) { Statement* ss = 0; Bubble* b = static_cast<Bubble*>((*slice)[j]); if (!parent || parent->statement_type() != Statement::MEDIA || b->node()->statement_type() != Statement::MEDIA || static_cast<Media_Block*>(b->node())->media_queries() == static_cast<Media_Block*>(parent)->media_queries()) { ss = b->node(); } else { List* mq = merge_media_queries(static_cast<Media_Block*>(b->node()), static_cast<Media_Block*>(parent)); if (!mq->length()) continue; static_cast<Media_Block*>(b->node())->media_queries(mq); ss = b->node(); } if (!ss) continue; ss->tabs(ss->tabs() + b->tabs()); ss->group_end(b->group_end()); if (!ss) continue; Block* bb = SASS_MEMORY_NEW(ctx.mem, Block, children->block()->pstate(), children->block()->length(), children->block()->is_root()); *bb << ss->perform(this); Statement* wrapper = flatten(bb); *wrapper_block << wrapper; if (wrapper->block()->length()) { previous_parent = 0; } } if (wrapper_block) { *result << flatten(wrapper_block); } } return flatten(result); }
void Output_Nested::operator()(Ruleset* r) { Selector* s = r->selector(); Block* b = r->block(); bool decls = false; // In case the extend visitor isn't called (if there are no @extend // directives in the entire document), check for placeholders here and // make sure they aren't output. // TODO: investigate why I decided to duplicate this logic in the extend visitor Selector_List* sl = static_cast<Selector_List*>(s); if (!ctx->extensions.size()) { Selector_List* new_sl = new (ctx->mem) Selector_List(sl->path(), sl->position()); for (size_t i = 0, L = sl->length(); i < L; ++i) { if (!(*sl)[i]->has_placeholder()) { *new_sl << (*sl)[i]; } } s = new_sl; sl = new_sl; r->selector(new_sl); } if (sl->length() == 0) return; if (b->has_non_hoistable()) { decls = true; indent(); if (source_comments) { stringstream ss; ss << "/* line " << r->position().line << ", " << r->path() << " */" << endl; append_singleline_part_to_buffer(ss.str()); indent(); } s->perform(this); append_multiline_part_to_buffer(" {\n"); ++indentation; for (size_t i = 0, L = b->length(); i < L; ++i) { Statement* stm = (*b)[i]; bool bPrintExpression = true; // Check print conditions if (typeid(*stm) == typeid(Declaration)) { Declaration* dec = static_cast<Declaration*>(stm); if (dec->value()->concrete_type() == Expression::STRING) { String_Constant* valConst = static_cast<String_Constant*>(dec->value()); string val(valConst->value()); if (val.empty()) { bPrintExpression = false; } } else if (dec->value()->concrete_type() == Expression::LIST) { List* list = static_cast<List*>(dec->value()); bool all_invisible = true; for (size_t list_i = 0, list_L = list->length(); list_i < list_L; ++list_i) { Expression* item = (*list)[list_i]; if (!item->is_invisible()) all_invisible = false; } if (all_invisible) bPrintExpression = false; } } // Print if OK if (!stm->is_hoistable() && bPrintExpression) { if (!stm->block()) indent(); stm->perform(this); append_multiline_part_to_buffer("\n"); } } --indentation; buffer.erase(buffer.length()-1); if (ctx) ctx->source_map.remove_line(); append_multiline_part_to_buffer(" }\n"); } if (b->has_hoistable()) { if (decls) ++indentation; // indent(); for (size_t i = 0, L = b->length(); i < L; ++i) { Statement* stm = (*b)[i]; if (stm->is_hoistable()) { stm->perform(this); } } if (decls) --indentation; } }