sassc 1.9.0 → 1.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +30 -3
  3. data/ext/libsass/.gitignore +3 -0
  4. data/ext/libsass/.travis.yml +1 -1
  5. data/ext/libsass/GNUmakefile.am +7 -7
  6. data/ext/libsass/Makefile +7 -4
  7. data/ext/libsass/Makefile.conf +0 -1
  8. data/ext/libsass/appveyor.yml +6 -2
  9. data/ext/libsass/docs/api-context.md +4 -4
  10. data/ext/libsass/docs/api-doc.md +29 -11
  11. data/ext/libsass/docs/api-importer-example.md +5 -5
  12. data/ext/libsass/docs/build-on-windows.md +1 -1
  13. data/ext/libsass/include/sass/base.h +10 -0
  14. data/ext/libsass/include/sass/version.h +4 -0
  15. data/ext/libsass/include/sass/version.h.in +4 -0
  16. data/ext/libsass/include/sass2scss.h +1 -1
  17. data/ext/libsass/script/ci-build-libsass +15 -3
  18. data/ext/libsass/src/ast.cpp +161 -6
  19. data/ext/libsass/src/ast.hpp +71 -44
  20. data/ext/libsass/src/ast_factory.hpp +1 -1
  21. data/ext/libsass/src/ast_fwd_decl.hpp +2 -2
  22. data/ext/libsass/src/constants.cpp +2 -4
  23. data/ext/libsass/src/constants.hpp +3 -4
  24. data/ext/libsass/src/context.cpp +16 -17
  25. data/ext/libsass/src/context.hpp +2 -2
  26. data/ext/libsass/src/cssize.cpp +19 -8
  27. data/ext/libsass/src/cssize.hpp +5 -2
  28. data/ext/libsass/src/debugger.hpp +6 -3
  29. data/ext/libsass/src/emitter.cpp +1 -1
  30. data/ext/libsass/src/environment.cpp +1 -1
  31. data/ext/libsass/src/eval.cpp +42 -14
  32. data/ext/libsass/src/eval.hpp +1 -1
  33. data/ext/libsass/src/expand.cpp +24 -8
  34. data/ext/libsass/src/expand.hpp +2 -1
  35. data/ext/libsass/src/extend.cpp +55 -15
  36. data/ext/libsass/src/extend.hpp +5 -1
  37. data/ext/libsass/src/functions.cpp +10 -5
  38. data/ext/libsass/src/inspect.cpp +25 -19
  39. data/ext/libsass/src/inspect.hpp +2 -2
  40. data/ext/libsass/src/json.cpp +20 -9
  41. data/ext/libsass/src/json.hpp +5 -5
  42. data/ext/libsass/src/lexer.cpp +4 -1
  43. data/ext/libsass/src/lexer.hpp +21 -0
  44. data/ext/libsass/src/listize.cpp +2 -1
  45. data/ext/libsass/src/operation.hpp +4 -4
  46. data/ext/libsass/src/output.cpp +1 -1
  47. data/ext/libsass/src/output.hpp +1 -1
  48. data/ext/libsass/src/parser.cpp +189 -90
  49. data/ext/libsass/src/parser.hpp +42 -2
  50. data/ext/libsass/src/prelexer.cpp +474 -7
  51. data/ext/libsass/src/prelexer.hpp +15 -2
  52. data/ext/libsass/src/remove_placeholders.cpp +5 -5
  53. data/ext/libsass/src/remove_placeholders.hpp +3 -2
  54. data/ext/libsass/src/sass.cpp +33 -3
  55. data/ext/libsass/src/sass2scss.cpp +7 -0
  56. data/ext/libsass/src/sass_context.cpp +32 -62
  57. data/ext/libsass/src/sass_functions.cpp +3 -3
  58. data/ext/libsass/src/sass_values.cpp +5 -5
  59. data/ext/libsass/src/utf8/unchecked.h +16 -16
  60. data/ext/libsass/src/util.cpp +51 -30
  61. data/ext/libsass/src/util.hpp +6 -1
  62. data/ext/libsass/win/libsass.targets +0 -2
  63. data/ext/libsass/win/libsass.vcxproj.filters +0 -6
  64. data/lib/sassc/engine.rb +4 -1
  65. data/lib/sassc/error.rb +23 -1
  66. data/lib/sassc/version.rb +1 -1
  67. data/test/error_test.rb +27 -0
  68. data/test/native_test.rb +1 -1
  69. metadata +5 -5
  70. data/ext/libsass/include/sass/interface.h +0 -105
  71. data/ext/libsass/src/sass_interface.cpp +0 -215
@@ -16,6 +16,7 @@ namespace Sass {
16
16
  Context& ctx;
17
17
  std::vector<Block*> block_stack;
18
18
  std::vector<Statement*> p_stack;
19
+ std::vector<Selector_List*> s_stack;
19
20
  Backtrace* backtrace;
20
21
 
21
22
  Statement* fallback_impl(AST_Node* n);
@@ -24,6 +25,8 @@ namespace Sass {
24
25
  Cssize(Context&, Backtrace*);
25
26
  ~Cssize() { }
26
27
 
28
+ Selector_List* selector();
29
+
27
30
  Statement* operator()(Block*);
28
31
  Statement* operator()(Ruleset*);
29
32
  // Statement* operator()(Propset*);
@@ -31,7 +34,7 @@ namespace Sass {
31
34
  Statement* operator()(Media_Block*);
32
35
  Statement* operator()(Supports_Block*);
33
36
  Statement* operator()(At_Root_Block*);
34
- Statement* operator()(At_Rule*);
37
+ Statement* operator()(Directive*);
35
38
  Statement* operator()(Keyframe_Rule*);
36
39
  // Statement* operator()(Declaration*);
37
40
  // Statement* operator()(Assignment*);
@@ -53,7 +56,7 @@ namespace Sass {
53
56
 
54
57
  Statement* parent();
55
58
  std::vector<std::pair<bool, Block*>> slice_by_bubble(Statement*);
56
- Statement* bubble(At_Rule*);
59
+ Statement* bubble(Directive*);
57
60
  Statement* bubble(At_Root_Block*);
58
61
  Statement* bubble(Media_Block*);
59
62
  Statement* bubble(Supports_Block*);
@@ -352,6 +352,7 @@ inline void debug_ast(AST_Node* node, std::string ind, Env* env)
352
352
  Content* block = dynamic_cast<Content*>(node);
353
353
  std::cerr << ind << "Content " << block;
354
354
  std::cerr << " (" << pstate_source_position(node) << ")";
355
+ std::cerr << " [@media:" << block->media_block() << "]";
355
356
  std::cerr << " " << block->tabs() << std::endl;
356
357
  } else if (dynamic_cast<Import_Stub*>(node)) {
357
358
  Import_Stub* block = dynamic_cast<Import_Stub*>(node);
@@ -387,9 +388,9 @@ inline void debug_ast(AST_Node* node, std::string ind, Env* env)
387
388
  std::cerr << " " << has_block->tabs() << std::endl;
388
389
  if (has_block->selector()) debug_ast(has_block->selector(), ind + "@");
389
390
  if (has_block->block()) for(auto i : has_block->block()->elements()) { debug_ast(i, ind + " ", env); }
390
- } else if (dynamic_cast<At_Rule*>(node)) {
391
- At_Rule* block = dynamic_cast<At_Rule*>(node);
392
- std::cerr << ind << "At_Rule " << block;
391
+ } else if (dynamic_cast<Directive*>(node)) {
392
+ Directive* block = dynamic_cast<Directive*>(node);
393
+ std::cerr << ind << "Directive " << block;
393
394
  std::cerr << " (" << pstate_source_position(node) << ")";
394
395
  std::cerr << " [" << block->keyword() << "] " << block->tabs() << std::endl;
395
396
  debug_ast(block->selector(), ind + "~", env);
@@ -556,6 +557,7 @@ inline void debug_ast(AST_Node* node, std::string ind, Env* env)
556
557
  (expression->separator() == SASS_COMMA ? "Comma " : expression->separator() == SASS_HASH ? "Map" : "Space ") <<
557
558
  " [delayed: " << expression->is_delayed() << "] " <<
558
559
  " [interpolant: " << expression->is_interpolant() << "] " <<
560
+ " [listized: " << expression->from_selector() << "] " <<
559
561
  " [arglist: " << expression->is_arglist() << "] " <<
560
562
  " [hash: " << expression->hash() << "] " <<
561
563
  std::endl;
@@ -564,6 +566,7 @@ inline void debug_ast(AST_Node* node, std::string ind, Env* env)
564
566
  Content* expression = dynamic_cast<Content*>(node);
565
567
  std::cerr << ind << "Content " << expression;
566
568
  std::cerr << " (" << pstate_source_position(node) << ")";
569
+ std::cerr << " [@media:" << expression->media_block() << "]";
567
570
  std::cerr << " [Statement]" << std::endl;
568
571
  } else if (dynamic_cast<Boolean*>(node)) {
569
572
  Boolean* expression = dynamic_cast<Boolean*>(node);
@@ -204,7 +204,7 @@ namespace Sass {
204
204
  void Emitter::append_optional_space()
205
205
  {
206
206
  if ((output_style() != COMPRESSED) && buffer().size()) {
207
- char lst = buffer().at(buffer().length() - 1);
207
+ unsigned char lst = buffer().at(buffer().length() - 1);
208
208
  if (!isspace(lst) || scheduled_delimiter) {
209
209
  append_mandatory_space();
210
210
  }
@@ -180,7 +180,7 @@ namespace Sass {
180
180
  if (!ends_with(i->first, "[f]") && !ends_with(i->first, "[f]4") && !ends_with(i->first, "[f]2")) {
181
181
  std::cerr << prefix << std::string(indent, ' ') << i->first << " " << i->second;
182
182
  if (Value* val = dynamic_cast<Value*>(i->second))
183
- { std::cerr << " : " << val->to_string(true, 5); }
183
+ { std::cerr << " : " << val->to_string(); }
184
184
  std::cerr << std::endl;
185
185
  }
186
186
  }
@@ -458,6 +458,7 @@ namespace Sass {
458
458
  *ll << (*l)[i]->perform(this);
459
459
  }
460
460
  ll->is_interpolant(l->is_interpolant());
461
+ ll->from_selector(l->from_selector());
461
462
  ll->is_expanded(true);
462
463
  return ll;
463
464
  }
@@ -834,15 +835,31 @@ namespace Sass {
834
835
  }
835
836
  std::string name(Util::normalize_underscores(c->name()));
836
837
  std::string full_name(name + "[f]");
837
- Arguments* args = c->arguments();
838
- if (full_name != "if[f]") {
839
- args = static_cast<Arguments*>(args->perform(this));
838
+ Arguments* args = SASS_MEMORY_NEW(ctx.mem, Arguments, *c->arguments());
839
+
840
+ // handle call here if valid arg
841
+ // otherwise we eval arguments to early
842
+ if (name == "call" && args->length() > 0) {
843
+ Expression* redirect = args->at(0)->perform(this);
844
+ args->erase(args->begin());
845
+ Function_Call* lit = SASS_MEMORY_NEW(ctx.mem, Function_Call,
846
+ c->pstate(),
847
+ unquote(redirect->to_string()),
848
+ args);
849
+ return operator()(lit);
840
850
  }
841
851
 
842
852
  Env* env = environment();
843
853
  if (!env->has(full_name)) {
844
854
  if (!env->has("*[f]")) {
845
855
  // just pass it through as a literal
856
+ for (Argument* arg : *args) {
857
+ if (Binary_Expression* b = dynamic_cast<Binary_Expression*>(arg->value())) {
858
+ b->reset_whitespace();
859
+ arg->is_delayed(b->can_delay()); // delay
860
+ }
861
+ }
862
+ args = static_cast<Arguments*>(args->perform(this));
846
863
  Function_Call* lit = SASS_MEMORY_NEW(ctx.mem, Function_Call,
847
864
  c->pstate(),
848
865
  c->name(),
@@ -861,6 +878,10 @@ namespace Sass {
861
878
  }
862
879
  }
863
880
 
881
+ if (full_name != "if[f]") {
882
+ args = static_cast<Arguments*>(args->perform(this));
883
+ }
884
+
864
885
  Definition* def = static_cast<Definition*>((*env)[full_name]);
865
886
 
866
887
  if (def->is_overload_stub()) {
@@ -1087,7 +1108,7 @@ namespace Sass {
1087
1108
  void Eval::interpolation(Context& ctx, std::string& res, Expression* ex, bool into_quotes, bool was_itpl) {
1088
1109
 
1089
1110
  bool needs_closing_brace = false;
1090
- //debug_ast(ex);
1111
+
1091
1112
  if (Arguments* args = dynamic_cast<Arguments*>(ex)) {
1092
1113
  List* ll = SASS_MEMORY_NEW(ctx.mem, List, args->pstate(), 0, SASS_COMMA);
1093
1114
  for(auto arg : *args) {
@@ -1165,8 +1186,10 @@ namespace Sass {
1165
1186
  if (!dynamic_cast<String_Quoted*>((*s)[0]) && !dynamic_cast<String_Quoted*>((*s)[L - 1])) {
1166
1187
  if (String_Constant* l = dynamic_cast<String_Constant*>((*s)[0])) {
1167
1188
  if (String_Constant* r = dynamic_cast<String_Constant*>((*s)[L - 1])) {
1168
- if (l->value()[0] == '"' && r->value()[r->value().size() - 1] == '"') into_quotes = true;
1169
- if (l->value()[0] == '\'' && r->value()[r->value().size() - 1] == '\'') into_quotes = true;
1189
+ if (r->value().size() > 0) {
1190
+ if (l->value()[0] == '"' && r->value()[r->value().size() - 1] == '"') into_quotes = true;
1191
+ if (l->value()[0] == '\'' && r->value()[r->value().size() - 1] == '\'') into_quotes = true;
1192
+ }
1170
1193
  }
1171
1194
  }
1172
1195
  }
@@ -1176,7 +1199,6 @@ namespace Sass {
1176
1199
  std::string res("");
1177
1200
  for (size_t i = 0; i < L; ++i) {
1178
1201
  bool is_quoted = dynamic_cast<String_Quoted*>((*s)[i]) != NULL;
1179
- (*s)[i]->perform(this);
1180
1202
  if (was_quoted && !(*s)[i]->is_interpolant() && !was_interpolant) { res += " "; }
1181
1203
  else if (i > 0 && is_quoted && !(*s)[i]->is_interpolant() && !was_interpolant) { res += " "; }
1182
1204
  Expression* ex = (*s)[i]->is_delayed() ? (*s)[i] : (*s)[i]->perform(this);
@@ -1260,17 +1282,16 @@ namespace Sass {
1260
1282
  return cc;
1261
1283
  }
1262
1284
 
1263
- Expression* Eval::operator()(At_Root_Expression* e)
1285
+ Expression* Eval::operator()(At_Root_Query* e)
1264
1286
  {
1265
1287
  Expression* feature = e->feature();
1266
1288
  feature = (feature ? feature->perform(this) : 0);
1267
1289
  Expression* value = e->value();
1268
1290
  value = (value ? value->perform(this) : 0);
1269
- Expression* ee = SASS_MEMORY_NEW(ctx.mem, At_Root_Expression,
1291
+ Expression* ee = SASS_MEMORY_NEW(ctx.mem, At_Root_Query,
1270
1292
  e->pstate(),
1271
1293
  static_cast<String*>(feature),
1272
- value,
1273
- e->is_interpolated());
1294
+ value);
1274
1295
  return ee;
1275
1296
  }
1276
1297
 
@@ -1322,7 +1343,8 @@ namespace Sass {
1322
1343
  Expression* Eval::operator()(Argument* a)
1323
1344
  {
1324
1345
  Expression* val = a->value();
1325
- val->is_delayed(false);
1346
+ // delay missin function arguments?
1347
+ val->is_delayed(a->is_delayed());
1326
1348
  val = val->perform(this);
1327
1349
  val->is_delayed(false);
1328
1350
 
@@ -1355,6 +1377,7 @@ namespace Sass {
1355
1377
  Expression* Eval::operator()(Arguments* a)
1356
1378
  {
1357
1379
  Arguments* aa = SASS_MEMORY_NEW(ctx.mem, Arguments, a->pstate());
1380
+ if (a->length() == 0) return aa;
1358
1381
  for (size_t i = 0, L = a->length(); i < L; ++i) {
1359
1382
  Argument* arg = static_cast<Argument*>((*a)[i]->perform(this));
1360
1383
  if (!(arg->is_rest_argument() || arg->is_keyword_argument())) {
@@ -1660,7 +1683,9 @@ namespace Sass {
1660
1683
  {
1661
1684
  std::vector<Selector_List*> rv;
1662
1685
  Selector_List* sl = SASS_MEMORY_NEW(ctx.mem, Selector_List, s->pstate());
1686
+ sl->is_optional(s->is_optional());
1663
1687
  sl->media_block(s->media_block());
1688
+ sl->is_optional(s->is_optional());
1664
1689
  for (size_t i = 0, iL = s->length(); i < iL; ++i) {
1665
1690
  rv.push_back(operator()((*s)[i]));
1666
1691
  }
@@ -1707,9 +1732,12 @@ namespace Sass {
1707
1732
  {
1708
1733
  // the parser will look for a brace to end the selector
1709
1734
  std::string result_str(s->contents()->perform(this)->to_string(ctx.c_options));
1710
- result_str = unquote(Util::rtrim(result_str)) + "{";
1735
+ result_str = unquote(Util::rtrim(result_str)) + "\n{";
1711
1736
  Parser p = Parser::from_c_str(result_str.c_str(), ctx, s->pstate());
1712
- return operator()(p.parse_selector_list(exp.block_stack.back()->is_root()));
1737
+ p.last_media_block = s->media_block();
1738
+ Selector_List* sl = p.parse_selector_list(exp.block_stack.back()->is_root());
1739
+ if (s->has_parent_ref()) sl->remove_parent_selectors();
1740
+ return operator()(sl);
1713
1741
  }
1714
1742
 
1715
1743
  Expression* Eval::operator()(Parent_Selector* p)
@@ -57,7 +57,7 @@ namespace Sass {
57
57
  // Expression* operator()(Selector_List*);
58
58
  Expression* operator()(Media_Query*);
59
59
  Expression* operator()(Media_Query_Expression*);
60
- Expression* operator()(At_Root_Expression*);
60
+ Expression* operator()(At_Root_Query*);
61
61
  Expression* operator()(Supports_Operator*);
62
62
  Expression* operator()(Supports_Negation*);
63
63
  Expression* operator()(Supports_Declaration*);
@@ -19,6 +19,7 @@ namespace Sass {
19
19
  call_stack(std::vector<AST_Node*>()),
20
20
  property_stack(std::vector<String*>()),
21
21
  selector_stack(std::vector<Selector_List*>()),
22
+ media_block_stack(std::vector<Media_Block*>()),
22
23
  backtrace_stack(std::vector<Backtrace*>()),
23
24
  in_keyframes(false)
24
25
  {
@@ -29,6 +30,7 @@ namespace Sass {
29
30
  // import_stack.push_back(0);
30
31
  property_stack.push_back(0);
31
32
  selector_stack.push_back(0);
33
+ media_block_stack.push_back(0);
32
34
  backtrace_stack.push_back(0);
33
35
  backtrace_stack.push_back(bt);
34
36
  }
@@ -134,6 +136,7 @@ namespace Sass {
134
136
  env = new Env(environment());
135
137
  env_stack.push_back(env);
136
138
  }
139
+ sel->set_media_block(media_block_stack.back());
137
140
  Block* blk = r->block()->perform(this)->block();
138
141
  Ruleset* rr = SASS_MEMORY_NEW(ctx.mem, Ruleset,
139
142
  r->pstate(),
@@ -144,6 +147,7 @@ namespace Sass {
144
147
  env_stack.pop_back();
145
148
  delete env;
146
149
  }
150
+ rr->is_root(r->is_root());
147
151
  rr->tabs(r->tabs());
148
152
 
149
153
  return rr;
@@ -195,9 +199,10 @@ namespace Sass {
195
199
 
196
200
  Statement* Expand::operator()(Media_Block* m)
197
201
  {
202
+ media_block_stack.push_back(m);
198
203
  Expression* mq = m->media_queries()->perform(&eval);
199
204
  std::string str_mq(mq->to_string(ctx.c_options));
200
- char* str = sass_strdup(str_mq.c_str());
205
+ char* str = sass_copy_c_string(str_mq.c_str());
201
206
  ctx.strings.push_back(str);
202
207
  Parser p(Parser::from_c_str(str, ctx, mq->pstate()));
203
208
  mq = p.parse_media_queries();
@@ -206,6 +211,7 @@ namespace Sass {
206
211
  static_cast<List*>(mq->perform(&eval)),
207
212
  m->block()->perform(this)->block(),
208
213
  0);
214
+ media_block_stack.pop_back();
209
215
  mm->tabs(m->tabs());
210
216
  return mm;
211
217
  }
@@ -216,17 +222,17 @@ namespace Sass {
216
222
  // if (ab) ab->is_root(true);
217
223
  Expression* ae = a->expression();
218
224
  if (ae) ae = ae->perform(&eval);
219
- else ae = SASS_MEMORY_NEW(ctx.mem, At_Root_Expression, a->pstate());
225
+ else ae = SASS_MEMORY_NEW(ctx.mem, At_Root_Query, a->pstate());
220
226
  Block* bb = ab ? ab->perform(this)->block() : 0;
221
227
  At_Root_Block* aa = SASS_MEMORY_NEW(ctx.mem, At_Root_Block,
222
228
  a->pstate(),
223
229
  bb,
224
- static_cast<At_Root_Expression*>(ae));
230
+ static_cast<At_Root_Query*>(ae));
225
231
  // aa->block()->is_root(true);
226
232
  return aa;
227
233
  }
228
234
 
229
- Statement* Expand::operator()(At_Rule* a)
235
+ Statement* Expand::operator()(Directive* a)
230
236
  {
231
237
  LOCAL_FLAG(in_keyframes, a->is_keyframes());
232
238
  Block* ab = a->block();
@@ -237,7 +243,7 @@ namespace Sass {
237
243
  if (as) as = dynamic_cast<Selector*>(as->perform(&eval));
238
244
  selector_stack.pop_back();
239
245
  Block* bb = ab ? ab->perform(this)->block() : 0;
240
- At_Rule* aa = SASS_MEMORY_NEW(ctx.mem, At_Rule,
246
+ Directive* aa = SASS_MEMORY_NEW(ctx.mem, Directive,
241
247
  a->pstate(),
242
248
  a->keyword(),
243
249
  as,
@@ -593,7 +599,7 @@ namespace Sass {
593
599
  error("Can't extend " + sel_str + ": can't extend nested selectors", c->pstate(), backtrace());
594
600
  }
595
601
  Compound_Selector* placeholder = c->head();
596
- placeholder->is_optional(s->is_optional());
602
+ if (contextualized->is_optional()) placeholder->is_optional(true);
597
603
  for (size_t i = 0, L = extender->length(); i < L; ++i) {
598
604
  Complex_Selector* sel = (*extender)[i];
599
605
  if (!(sel->head() && sel->head()->length() > 0 &&
@@ -621,8 +627,18 @@ namespace Sass {
621
627
  Statement* Expand::operator()(Extension* e)
622
628
  {
623
629
  if (Selector_List* extender = dynamic_cast<Selector_List*>(selector())) {
624
- selector_stack.push_back(0);
625
630
  Selector* s = e->selector();
631
+ if (Selector_Schema* schema = dynamic_cast<Selector_Schema*>(s)) {
632
+ if (schema->has_parent_ref()) s = eval(schema);
633
+ }
634
+ if (Selector_List* sl = dynamic_cast<Selector_List*>(s)) {
635
+ for (Complex_Selector* cs : *sl) {
636
+ if (cs != NULL && cs->head() != NULL) {
637
+ cs->head()->media_block(media_block_stack.back());
638
+ }
639
+ }
640
+ }
641
+ selector_stack.push_back(0);
626
642
  expand_selector_list(s, extender);
627
643
  selector_stack.pop_back();
628
644
  }
@@ -637,7 +653,7 @@ namespace Sass {
637
653
  (d->type() == Definition::MIXIN ? "[m]" : "[f]")] = dd;
638
654
 
639
655
  if (d->type() == Definition::FUNCTION && (
640
- d->name() == "calc" ||
656
+ Prelexer::calc_fn_call(d->name().c_str()) ||
641
657
  d->name() == "element" ||
642
658
  d->name() == "expression" ||
643
659
  d->name() == "url"
@@ -33,6 +33,7 @@ namespace Sass {
33
33
  std::vector<AST_Node*> call_stack;
34
34
  std::vector<String*> property_stack;
35
35
  std::vector<Selector_List*> selector_stack;
36
+ std::vector<Media_Block*> media_block_stack;
36
37
  std::vector<Backtrace*>backtrace_stack;
37
38
  bool in_keyframes;
38
39
 
@@ -51,7 +52,7 @@ namespace Sass {
51
52
  Statement* operator()(Media_Block*);
52
53
  Statement* operator()(Supports_Block*);
53
54
  Statement* operator()(At_Root_Block*);
54
- Statement* operator()(At_Rule*);
55
+ Statement* operator()(Directive*);
55
56
  Statement* operator()(Declaration*);
56
57
  Statement* operator()(Assignment*);
57
58
  Statement* operator()(Import*);
@@ -6,6 +6,7 @@
6
6
  #include "parser.hpp"
7
7
  #include "node.hpp"
8
8
  #include "sass_util.hpp"
9
+ #include "remove_placeholders.hpp"
9
10
  #include "debug.hpp"
10
11
  #include <iostream>
11
12
  #include <deque>
@@ -1463,6 +1464,7 @@ namespace Sass {
1463
1464
  Node current = afters.collection()->front().clone(ctx);
1464
1465
  afters.collection()->pop_front();
1465
1466
  DEBUG_PRINTLN(WEAVE, "CURRENT: " << current)
1467
+ if (current.collection()->size() == 0) continue;
1466
1468
 
1467
1469
  Node last_current = Node::createCollection();
1468
1470
  last_current.collection()->push_back(current.collection()->back());
@@ -1737,14 +1739,14 @@ namespace Sass {
1737
1739
  SubsetMapEntries entries = subset_map.get_v(pHead->to_str_vec());
1738
1740
  for (ExtensionPair ext : entries) {
1739
1741
  // check if both selectors have the same media block parent
1740
- if (ext.first->media_block() == pComplexSelector->media_block()) continue;
1742
+ // if (ext.first->media_block() == pComplexSelector->media_block()) continue;
1741
1743
  if (ext.second->media_block() == 0) continue;
1742
- if (pComplexSelector->media_block() &&
1744
+ if (pHead->media_block() &&
1743
1745
  ext.second->media_block()->media_queries() &&
1744
- pComplexSelector->media_block()->media_queries()
1746
+ pHead->media_block()->media_queries()
1745
1747
  ) {
1746
1748
  std::string query_left(ext.second->media_block()->media_queries()->to_string(ctx.c_options));
1747
- std::string query_right(pComplexSelector->media_block()->media_queries()->to_string(ctx.c_options));
1749
+ std::string query_right(pHead->media_block()->media_queries()->to_string(ctx.c_options));
1748
1750
  if (query_left == query_right) continue;
1749
1751
  }
1750
1752
 
@@ -1943,19 +1945,57 @@ namespace Sass {
1943
1945
  }
1944
1946
  }
1945
1947
 
1946
- for (Complex_Selector* cs : *pNewSelectors) {
1947
- while (cs) {
1948
- if (cs->head()) {
1949
- for (Simple_Selector* ss : *cs->head()) {
1950
- if (Wrapped_Selector* ws = dynamic_cast<Wrapped_Selector*>(ss)) {
1951
- if (Selector_List* sl = dynamic_cast<Selector_List*>(ws->selector())) {
1952
- bool extended = false;
1953
- ws->selector(extendSelectorList(sl, ctx, subset_map, false, extended));
1948
+ Remove_Placeholders remove_placeholders(ctx);
1949
+ // it seems that we have to remove the place holders early here
1950
+ // normally we do this as the very last step (compare to ruby sass)
1951
+ pNewSelectors = remove_placeholders.remove_placeholders(pNewSelectors);
1952
+
1953
+ // unwrap all wrapped selectors with inner lists
1954
+ for (Complex_Selector* cur : *pNewSelectors) {
1955
+ // process tails
1956
+ while (cur) {
1957
+ // process header
1958
+ if (cur->head()) {
1959
+ // create a copy since we add multiple items if stuff get unwrapped
1960
+ Compound_Selector* cpy_head = SASS_MEMORY_NEW(ctx.mem, Compound_Selector, cur->pstate());
1961
+ for (Simple_Selector* hs : *cur->head()) {
1962
+ if (Wrapped_Selector* ws = dynamic_cast<Wrapped_Selector*>(hs)) {
1963
+ if (Selector_List* sl = dynamic_cast<Selector_List*>(ws->selector())) {
1964
+ // special case for ruby ass
1965
+ if (sl->empty()) {
1966
+ // this seems inconsistent but it is how ruby sass seems to remove parentheses
1967
+ *cpy_head << SASS_MEMORY_NEW(ctx.mem, Type_Selector, hs->pstate(), ws->name());
1968
+ }
1969
+ // has wrapped selectors
1970
+ else {
1971
+ // extend the inner list of wrapped selector
1972
+ Selector_List* ext_sl = extendSelectorList(sl, ctx, subset_map);
1973
+ for (size_t i = 0; i < ext_sl->length(); i += 1) {
1974
+ if (Complex_Selector* ext_cs = ext_sl->at(i)) {
1975
+ // create clones for wrapped selector and the inner list
1976
+ Wrapped_Selector* cpy_ws = SASS_MEMORY_NEW(ctx.mem, Wrapped_Selector, *ws);
1977
+ Selector_List* cpy_ws_sl = SASS_MEMORY_NEW(ctx.mem, Selector_List, sl->pstate());
1978
+ // remove parent selectors from inner selector
1979
+ if (ext_cs->first()) *cpy_ws_sl << ext_cs->first();
1980
+ // assign list to clone
1981
+ cpy_ws->selector(cpy_ws_sl);
1982
+ // append the clone
1983
+ *cpy_head << cpy_ws;
1984
+ }
1985
+ }
1986
+ }
1987
+ } else {
1988
+ *cpy_head << hs;
1989
+ }
1990
+ } else {
1991
+ *cpy_head << hs;
1954
1992
  }
1955
1993
  }
1994
+ // replace header
1995
+ cur->head(cpy_head);
1956
1996
  }
1957
- }
1958
- cs = cs->tail();
1997
+ // process tail
1998
+ cur = cur->tail();
1959
1999
  }
1960
2000
  }
1961
2001
  return pNewSelectors;
@@ -2068,7 +2108,7 @@ namespace Sass {
2068
2108
  pMediaBlock->block()->perform(this);
2069
2109
  }
2070
2110
 
2071
- void Extend::operator()(At_Rule* a)
2111
+ void Extend::operator()(Directive* a)
2072
2112
  {
2073
2113
  // Selector_List* ls = dynamic_cast<Selector_List*>(a->selector());
2074
2114
  // selector_stack.push_back(ls);