Esempio n. 1
0
  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;
      }
    }
  }
Esempio n. 2
0
  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;
  }
Esempio n. 3
0
 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;
 }
Esempio n. 4
0
  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");
  }
Esempio n. 5
0
  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");
  }
Esempio n. 6
0
  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";
  }
Esempio n. 7
0
  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";
  }
Esempio n. 8
0
  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;
    }
  }
Esempio n. 9
0
  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;
    }
  }
Esempio n. 10
0
  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);
  }
Esempio n. 11
0
  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;
    }
  }