sassc 1.9.0 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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);