sassc 1.8.3 → 1.8.4

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 (96) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -1
  3. data/ext/libsass/.editorconfig +1 -1
  4. data/ext/libsass/.gitignore +1 -0
  5. data/ext/libsass/LICENSE +1 -1
  6. data/ext/libsass/Makefile +20 -14
  7. data/ext/libsass/Makefile.conf +0 -1
  8. data/ext/libsass/Readme.md +3 -1
  9. data/ext/libsass/appveyor.yml +19 -11
  10. data/ext/libsass/docs/api-importer-example.md +2 -1235
  11. data/ext/libsass/docs/build-with-autotools.md +10 -0
  12. data/ext/libsass/docs/build-with-makefiles.md +18 -0
  13. data/ext/libsass/include/sass/base.h +4 -1
  14. data/ext/libsass/include/sass/values.h +2 -1
  15. data/ext/libsass/src/ast.cpp +279 -346
  16. data/ext/libsass/src/ast.hpp +234 -60
  17. data/ext/libsass/src/base64vlq.cpp +1 -0
  18. data/ext/libsass/src/bind.cpp +35 -45
  19. data/ext/libsass/src/bind.hpp +1 -0
  20. data/ext/libsass/src/color_maps.cpp +1 -0
  21. data/ext/libsass/src/constants.cpp +4 -1
  22. data/ext/libsass/src/constants.hpp +2 -1
  23. data/ext/libsass/src/context.cpp +41 -31
  24. data/ext/libsass/src/context.hpp +10 -10
  25. data/ext/libsass/src/cssize.cpp +7 -4
  26. data/ext/libsass/src/cssize.hpp +1 -3
  27. data/ext/libsass/src/debugger.hpp +73 -14
  28. data/ext/libsass/src/emitter.cpp +37 -25
  29. data/ext/libsass/src/emitter.hpp +10 -9
  30. data/ext/libsass/src/environment.cpp +16 -5
  31. data/ext/libsass/src/environment.hpp +5 -3
  32. data/ext/libsass/src/error_handling.cpp +91 -14
  33. data/ext/libsass/src/error_handling.hpp +105 -4
  34. data/ext/libsass/src/eval.cpp +519 -330
  35. data/ext/libsass/src/eval.hpp +12 -13
  36. data/ext/libsass/src/expand.cpp +92 -56
  37. data/ext/libsass/src/expand.hpp +5 -3
  38. data/ext/libsass/src/extend.cpp +60 -51
  39. data/ext/libsass/src/extend.hpp +1 -3
  40. data/ext/libsass/src/file.cpp +37 -27
  41. data/ext/libsass/src/functions.cpp +78 -62
  42. data/ext/libsass/src/functions.hpp +1 -0
  43. data/ext/libsass/src/inspect.cpp +293 -64
  44. data/ext/libsass/src/inspect.hpp +2 -0
  45. data/ext/libsass/src/lexer.cpp +1 -0
  46. data/ext/libsass/src/listize.cpp +14 -15
  47. data/ext/libsass/src/listize.hpp +3 -5
  48. data/ext/libsass/src/memory_manager.cpp +1 -0
  49. data/ext/libsass/src/node.cpp +2 -3
  50. data/ext/libsass/src/operation.hpp +70 -71
  51. data/ext/libsass/src/output.cpp +28 -32
  52. data/ext/libsass/src/output.hpp +1 -2
  53. data/ext/libsass/src/parser.cpp +402 -183
  54. data/ext/libsass/src/parser.hpp +19 -9
  55. data/ext/libsass/src/plugins.cpp +1 -0
  56. data/ext/libsass/src/position.cpp +1 -0
  57. data/ext/libsass/src/prelexer.cpp +134 -56
  58. data/ext/libsass/src/prelexer.hpp +51 -3
  59. data/ext/libsass/src/remove_placeholders.cpp +35 -9
  60. data/ext/libsass/src/remove_placeholders.hpp +4 -3
  61. data/ext/libsass/src/sass.cpp +1 -0
  62. data/ext/libsass/src/sass.hpp +129 -0
  63. data/ext/libsass/src/sass_context.cpp +31 -14
  64. data/ext/libsass/src/sass_context.hpp +2 -31
  65. data/ext/libsass/src/sass_functions.cpp +1 -0
  66. data/ext/libsass/src/sass_interface.cpp +5 -6
  67. data/ext/libsass/src/sass_util.cpp +1 -2
  68. data/ext/libsass/src/sass_util.hpp +5 -5
  69. data/ext/libsass/src/sass_values.cpp +13 -10
  70. data/ext/libsass/src/source_map.cpp +4 -3
  71. data/ext/libsass/src/source_map.hpp +2 -2
  72. data/ext/libsass/src/subset_map.hpp +0 -1
  73. data/ext/libsass/src/to_c.cpp +1 -0
  74. data/ext/libsass/src/to_c.hpp +1 -3
  75. data/ext/libsass/src/to_value.cpp +3 -5
  76. data/ext/libsass/src/to_value.hpp +1 -1
  77. data/ext/libsass/src/units.cpp +96 -59
  78. data/ext/libsass/src/units.hpp +10 -8
  79. data/ext/libsass/src/utf8_string.cpp +5 -0
  80. data/ext/libsass/src/util.cpp +23 -156
  81. data/ext/libsass/src/util.hpp +10 -14
  82. data/ext/libsass/src/values.cpp +1 -0
  83. data/ext/libsass/test/test_node.cpp +2 -6
  84. data/ext/libsass/test/test_selector_difference.cpp +1 -3
  85. data/ext/libsass/test/test_specificity.cpp +0 -2
  86. data/ext/libsass/test/test_superselector.cpp +0 -2
  87. data/ext/libsass/test/test_unification.cpp +1 -3
  88. data/ext/libsass/win/libsass.targets +18 -5
  89. data/ext/libsass/win/libsass.vcxproj +9 -7
  90. data/ext/libsass/win/libsass.vcxproj.filters +148 -106
  91. data/lib/sassc/version.rb +1 -1
  92. data/test/engine_test.rb +12 -0
  93. data/test/native_test.rb +1 -1
  94. metadata +3 -4
  95. data/ext/libsass/src/to_string.cpp +0 -48
  96. data/ext/libsass/src/to_string.hpp +0 -38
@@ -23,11 +23,11 @@ namespace Sass {
23
23
  class Parser : public ParserState {
24
24
  public:
25
25
 
26
- enum Syntactic_Context { nothing, mixin_def, function_def };
26
+ enum Scope { Root, Mixin, Function, Media, Control, Properties, Rules };
27
27
 
28
28
  Context& ctx;
29
29
  std::vector<Block*> block_stack;
30
- std::vector<Syntactic_Context> stack;
30
+ std::vector<Scope> stack;
31
31
  Media_Block* last_media_block;
32
32
  const char* source;
33
33
  const char* position;
@@ -44,14 +44,14 @@ namespace Sass {
44
44
  Parser(Context& ctx, const ParserState& pstate)
45
45
  : ParserState(pstate), ctx(ctx), block_stack(0), stack(0), last_media_block(0),
46
46
  source(0), position(0), end(0), before_token(pstate), after_token(pstate), pstate(pstate), indentation(0)
47
- { in_at_root = false; stack.push_back(nothing); }
47
+ { in_at_root = false; stack.push_back(Scope::Root); }
48
48
 
49
49
  // static Parser from_string(const std::string& src, Context& ctx, ParserState pstate = ParserState("[STRING]"));
50
- static Parser from_c_str(const char* src, Context& ctx, ParserState pstate = ParserState("[CSTRING]"));
51
- static Parser from_c_str(const char* beg, const char* end, Context& ctx, ParserState pstate = ParserState("[CSTRING]"));
52
- static Parser from_token(Token t, Context& ctx, ParserState pstate = ParserState("[TOKEN]"));
50
+ static Parser from_c_str(const char* src, Context& ctx, ParserState pstate = ParserState("[CSTRING]"), const char* source = 0);
51
+ static Parser from_c_str(const char* beg, const char* end, Context& ctx, ParserState pstate = ParserState("[CSTRING]"), const char* source = 0);
52
+ static Parser from_token(Token t, Context& ctx, ParserState pstate = ParserState("[TOKEN]"), const char* source = 0);
53
53
  // special static parsers to convert strings into certain selectors
54
- static Selector_List* parse_selector(const char* src, Context& ctx, ParserState pstate = ParserState("[SELECTOR]"));
54
+ static Selector_List* parse_selector(const char* src, Context& ctx, ParserState pstate = ParserState("[SELECTOR]"), const char* source = 0);
55
55
 
56
56
  #ifdef __clang__
57
57
 
@@ -96,6 +96,15 @@ namespace Sass {
96
96
 
97
97
  }
98
98
 
99
+ // peek will only skip over space, tabs and line comment
100
+ // return the position where the lexer match will occur
101
+ template <Prelexer::prelexer mx>
102
+ const char* match(const char* start = 0)
103
+ {
104
+ // match the given prelexer
105
+ return mx(position);
106
+ }
107
+
99
108
  // peek will only skip over space, tabs and line comment
100
109
  // return the position where the lexer match will occur
101
110
  template <Prelexer::prelexer mx>
@@ -253,6 +262,7 @@ namespace Sass {
253
262
  Function_Call* parse_function_call();
254
263
  Function_Call_Schema* parse_function_call_schema();
255
264
  String* parse_url_function_string();
265
+ String* parse_url_function_argument();
256
266
  String* parse_interpolated_chunk(Token, bool constant = false);
257
267
  String* parse_string();
258
268
  String_Constant* parse_static_expression();
@@ -298,8 +308,8 @@ namespace Sass {
298
308
  Lookahead lookahead_for_selector(const char* start = 0);
299
309
  Lookahead lookahead_for_include(const char* start = 0);
300
310
 
301
- Expression* fold_operands(Expression* base, std::vector<Expression*>& operands, Sass_OP op);
302
- Expression* fold_operands(Expression* base, std::vector<Expression*>& operands, std::vector<Sass_OP>& ops);
311
+ Expression* fold_operands(Expression* base, std::vector<Expression*>& operands, Operand op);
312
+ Expression* fold_operands(Expression* base, std::vector<Expression*>& operands, std::vector<Operand>& ops, size_t i = 0);
303
313
 
304
314
  void throw_syntax_error(std::string message, size_t ln = 0);
305
315
  void throw_read_error(std::string message, size_t ln = 0);
@@ -7,6 +7,7 @@
7
7
  #include <dlfcn.h>
8
8
  #endif
9
9
 
10
+ #include "sass.hpp"
10
11
  #include <iostream>
11
12
  #include "output.hpp"
12
13
  #include "plugins.hpp"
@@ -1,3 +1,4 @@
1
+ #include "sass.hpp"
1
2
  #include "position.hpp"
2
3
 
3
4
  namespace Sass {
@@ -1,3 +1,4 @@
1
+ #include "sass.hpp"
1
2
  #include <cctype>
2
3
  #include <cstddef>
3
4
  #include <iostream>
@@ -153,8 +154,8 @@ namespace Sass {
153
154
  >(src);
154
155
  }
155
156
 
156
- // Match CSS unit identifier.
157
- const char* unit_identifier(const char* src)
157
+ // Match a single CSS unit
158
+ const char* one_unit(const char* src)
158
159
  {
159
160
  return sequence <
160
161
  optional < exactly <'-'> >,
@@ -169,6 +170,34 @@ namespace Sass {
169
170
  >(src);
170
171
  }
171
172
 
173
+ // Match numerator/denominator CSS units
174
+ const char* multiple_units(const char* src)
175
+ {
176
+ return
177
+ sequence <
178
+ one_unit,
179
+ zero_plus <
180
+ sequence <
181
+ exactly <'*'>,
182
+ one_unit
183
+ >
184
+ >
185
+ >(src);
186
+ }
187
+
188
+ // Match complex CSS unit identifiers
189
+ const char* unit_identifier(const char* src)
190
+ {
191
+ return sequence <
192
+ multiple_units,
193
+ optional <
194
+ sequence <
195
+ exactly <'/'>,
196
+ multiple_units
197
+ > >
198
+ >(src);
199
+ }
200
+
172
201
  const char* identifier_alnums(const char* src)
173
202
  {
174
203
  return one_plus< identifier_alnum >(src);
@@ -194,7 +223,12 @@ namespace Sass {
194
223
  sequence <
195
224
  zero_plus <
196
225
  alternatives <
197
- identifier,
226
+ sequence <
227
+ optional <
228
+ exactly <'$'>
229
+ >,
230
+ identifier
231
+ >,
198
232
  exactly <'-'>
199
233
  >
200
234
  >,
@@ -202,9 +236,13 @@ namespace Sass {
202
236
  zero_plus <
203
237
  alternatives <
204
238
  digits,
205
- identifier,
239
+ sequence <
240
+ optional <
241
+ exactly <'$'>
242
+ >,
243
+ identifier
244
+ >,
206
245
  quoted_string,
207
- exactly<'+'>,
208
246
  exactly<'-'>
209
247
  >
210
248
  >
@@ -278,18 +316,54 @@ namespace Sass {
278
316
  >(src);
279
317
  }
280
318
 
281
- const char* value_schema(const char* src) {
282
- // follows this pattern: ([xyz]*i[xyz]*)+
283
- return one_plus< sequence< zero_plus< alternatives< identifier, percentage, dimension, hex, number, quoted_string > >,
284
- interpolant,
285
- zero_plus< alternatives< identifier, percentage, dimension, hex, number, quoted_string, exactly<'%'> > > > >(src);
319
+ const char* sass_value(const char* src) {
320
+ return alternatives <
321
+ quoted_string,
322
+ identifier,
323
+ percentage,
324
+ hex,
325
+ dimension,
326
+ number
327
+ >(src);
286
328
  }
287
329
 
288
- /* not used anymore - remove?
289
- const char* filename(const char* src) {
290
- return one_plus< alternatives< identifier, number, exactly<'.'> > >(src);
330
+ // this is basically `one_plus < sass_value >`
331
+ // takes care to not parse invalid combinations
332
+ const char* value_combinations(const char* src) {
333
+ // `2px-2px` is invalid combo
334
+ bool was_number = false;
335
+ const char* pos = src;
336
+ while (src) {
337
+ if ((pos = alternatives < quoted_string, identifier, percentage, hex >(src))) {
338
+ was_number = false;
339
+ src = pos;
340
+ } else if (!was_number && !exactly<'+'>(src) && (pos = alternatives < dimension, number >(src))) {
341
+ was_number = true;
342
+ src = pos;
343
+ } else {
344
+ break;
345
+ }
346
+ }
347
+ return src;
348
+ }
349
+
350
+ // must be at least one interpolant
351
+ // can be surrounded by sass values
352
+ // make sure to never parse (dim)(dim)
353
+ // since this wrongly consumes `2px-1px`
354
+ // `2px1px` is valid number (unit `px1px`)
355
+ const char* value_schema(const char* src)
356
+ {
357
+ return sequence <
358
+ one_plus <
359
+ sequence <
360
+ optional < value_combinations >,
361
+ interpolant,
362
+ optional < value_combinations >
363
+ >
364
+ >
365
+ >(src);
291
366
  }
292
- */
293
367
 
294
368
  // Match CSS '@' keywords.
295
369
  const char* at_keyword(const char* src) {
@@ -539,6 +613,9 @@ namespace Sass {
539
613
  }
540
614
  // Match CSS numeric constants.
541
615
 
616
+ const char* op(const char* src) {
617
+ return class_char<op_chars>(src);
618
+ }
542
619
  const char* sign(const char* src) {
543
620
  return class_char<sign_chars>(src);
544
621
  }
@@ -603,23 +680,19 @@ namespace Sass {
603
680
  // Match CSS uri specifiers.
604
681
 
605
682
  const char* uri_prefix(const char* src) {
606
- return exactly<url_kwd>(src);
607
- }
608
- const char* uri_value(const char* src)
609
- {
610
- return
611
- sequence <
612
- negate <
613
- exactly < '$' >
683
+ return sequence <
684
+ exactly <
685
+ url_kwd
614
686
  >,
615
687
  zero_plus <
616
- alternatives <
617
- alnum,
618
- interpolant,
619
- exactly <'/'>,
620
- class_char < uri_chars >
688
+ sequence <
689
+ exactly <'-'>,
690
+ one_plus <
691
+ alpha
692
+ >
621
693
  >
622
- >
694
+ >,
695
+ exactly <'('>
623
696
  >(src);
624
697
  }
625
698
 
@@ -1107,34 +1180,39 @@ namespace Sass {
1107
1180
  return sequence< number, optional_spaces, exactly<'/'>, optional_spaces, number >(src);
1108
1181
  }
1109
1182
 
1110
- template <size_t size, prelexer mx, prelexer pad>
1111
- const char* padded_token(const char* src)
1112
- {
1113
- size_t got = 0;
1114
- const char* pos = src;
1115
- while (got < size) {
1116
- if (!mx(pos)) break;
1117
- ++ pos; ++ got;
1118
- }
1119
- while (got < size) {
1120
- if (!pad(pos)) break;
1121
- ++ pos; ++ got;
1122
- }
1123
- return got ? pos : 0;
1124
- }
1125
-
1126
- template <size_t min, size_t max, prelexer mx>
1127
- const char* minmax_range(const char* src)
1128
- {
1129
- size_t got = 0;
1130
- const char* pos = src;
1131
- while (got < max) {
1132
- if (!mx(pos)) break;
1133
- ++ pos; ++ got;
1134
- }
1135
- if (got < min) return 0;
1136
- if (got > max) return 0;
1137
- return pos;
1183
+ // lexer special_fn: these functions cannot be overloaded
1184
+ // (/((-[\w-]+-)?(calc|element)|expression|progid:[a-z\.]*)\(/i)
1185
+ const char* re_special_fun(const char* src) {
1186
+ return sequence <
1187
+ optional <
1188
+ sequence <
1189
+ exactly <'-'>,
1190
+ one_plus <
1191
+ alternatives <
1192
+ alpha,
1193
+ exactly <'+'>,
1194
+ exactly <'-'>
1195
+ >
1196
+ >
1197
+ >
1198
+ >,
1199
+ alternatives <
1200
+ exactly < calc_fn_kwd >,
1201
+ exactly < expression_kwd >,
1202
+ sequence <
1203
+ sequence <
1204
+ exactly < progid_kwd >,
1205
+ exactly <':'>
1206
+ >,
1207
+ zero_plus <
1208
+ alternatives <
1209
+ char_range <'a', 'z'>,
1210
+ exactly <'.'>
1211
+ >
1212
+ >
1213
+ >
1214
+ >
1215
+ >(src);
1138
1216
  }
1139
1217
 
1140
1218
  }
@@ -200,6 +200,8 @@ namespace Sass {
200
200
  const char* strict_identifier_alpha(const char* src);
201
201
  const char* strict_identifier_alnum(const char* src);
202
202
  // Match a CSS unit identifier.
203
+ const char* one_unit(const char* src);
204
+ const char* multiple_units(const char* src);
203
205
  const char* unit_identifier(const char* src);
204
206
  // const char* strict_identifier_alnums(const char* src);
205
207
  // Match reference selector.
@@ -210,6 +212,7 @@ namespace Sass {
210
212
  // Match interpolant schemas
211
213
  const char* identifier_schema(const char* src);
212
214
  const char* value_schema(const char* src);
215
+ const char* sass_value(const char* src);
213
216
  // const char* filename(const char* src);
214
217
  // const char* filename_schema(const char* src);
215
218
  // const char* url_schema(const char* src);
@@ -252,6 +255,7 @@ namespace Sass {
252
255
  const char* re_nothing(const char* src);
253
256
  const char* re_type_selector2(const char* src);
254
257
 
258
+ const char* re_special_fun(const char* src);
255
259
 
256
260
  const char* kwd_warn(const char* src);
257
261
  const char* kwd_err(const char* src);
@@ -282,6 +286,7 @@ namespace Sass {
282
286
  // Match placeholder selectors.
283
287
  const char* placeholder(const char* src);
284
288
  // Match CSS numeric constants.
289
+ const char* op(const char* src);
285
290
  const char* sign(const char* src);
286
291
  const char* unsigned_number(const char* src);
287
292
  const char* number(const char* src);
@@ -296,7 +301,6 @@ namespace Sass {
296
301
  // const char* rgb_prefix(const char* src);
297
302
  // Match CSS uri specifiers.
298
303
  const char* uri_prefix(const char* src);
299
- const char* uri_value(const char* src);
300
304
  // Match CSS "!important" keyword.
301
305
  const char* kwd_important(const char* src);
302
306
  // Match CSS "!optional" keyword.
@@ -381,6 +385,18 @@ namespace Sass {
381
385
  }
382
386
  return 0;
383
387
  }
388
+ template<prelexer mx, prelexer skip>
389
+ const char* find_first_in_interval(const char* beg, const char* end) {
390
+ bool esc = false;
391
+ while ((beg < end) && *beg) {
392
+ if (esc) esc = false;
393
+ else if (*beg == '\\') esc = true;
394
+ else if (const char* pos = skip(beg)) beg = pos;
395
+ else if (mx(beg)) return beg;
396
+ ++beg;
397
+ }
398
+ return 0;
399
+ }
384
400
  template <prelexer mx>
385
401
  unsigned int count_interval(const char* beg, const char* end) {
386
402
  unsigned int counter = 0;
@@ -405,10 +421,42 @@ namespace Sass {
405
421
  }
406
422
 
407
423
  template <size_t size, prelexer mx, prelexer pad>
408
- const char* padded_token(const char* src);
424
+ const char* padded_token(const char* src)
425
+ {
426
+ size_t got = 0;
427
+ const char* pos = src;
428
+ while (got < size) {
429
+ if (!mx(pos)) break;
430
+ ++ pos; ++ got;
431
+ }
432
+ while (got < size) {
433
+ if (!pad(pos)) break;
434
+ ++ pos; ++ got;
435
+ }
436
+ return got ? pos : 0;
437
+ }
409
438
 
410
439
  template <size_t min, size_t max, prelexer mx>
411
- const char* minmax_range(const char* src);
440
+ const char* minmax_range(const char* src)
441
+ {
442
+ size_t got = 0;
443
+ const char* pos = src;
444
+ while (got < max) {
445
+ if (!mx(pos)) break;
446
+ ++ pos; ++ got;
447
+ }
448
+ if (got < min) return 0;
449
+ if (got > max) return 0;
450
+ return pos;
451
+ }
452
+
453
+ template <char min, char max>
454
+ const char* char_range(const char* src)
455
+ {
456
+ if (*src < min) return 0;
457
+ if (*src > max) return 0;
458
+ return src + 1;
459
+ }
412
460
 
413
461
  }
414
462
  }
@@ -1,7 +1,7 @@
1
+ #include "sass.hpp"
1
2
  #include "remove_placeholders.hpp"
2
3
  #include "context.hpp"
3
4
  #include "inspect.hpp"
4
- #include "to_string.hpp"
5
5
  #include <iostream>
6
6
 
7
7
  namespace Sass {
@@ -16,21 +16,47 @@ namespace Sass {
16
16
  }
17
17
  }
18
18
 
19
+ Selector_List* Remove_Placeholders::remove_placeholders(Selector_List* sl)
20
+ {
21
+ Selector_List* new_sl = SASS_MEMORY_NEW(ctx.mem, Selector_List, sl->pstate());
22
+
23
+ for (size_t i = 0, L = sl->length(); i < L; ++i) {
24
+ if (!(*sl)[i]->contains_placeholder()) {
25
+ *new_sl << (*sl)[i];
26
+ }
27
+ }
28
+
29
+ return new_sl;
30
+
31
+ }
32
+
33
+
19
34
  void Remove_Placeholders::operator()(Ruleset* r) {
20
35
  // Create a new selector group without placeholders
21
36
  Selector_List* sl = static_cast<Selector_List*>(r->selector());
22
37
 
23
38
  if (sl) {
24
- Selector_List* new_sl = SASS_MEMORY_NEW(ctx.mem, Selector_List, sl->pstate());
25
-
26
- for (size_t i = 0, L = sl->length(); i < L; ++i) {
27
- if (!(*sl)[i]->contains_placeholder()) {
28
- *new_sl << (*sl)[i];
39
+ // Set the new placeholder selector list
40
+ r->selector(remove_placeholders(sl));
41
+ // Remove placeholders in wrapped selectors
42
+ for (Complex_Selector* cs : *sl) {
43
+ while (cs) {
44
+ if (cs->head()) {
45
+ for (Simple_Selector* ss : *cs->head()) {
46
+ if (Wrapped_Selector* ws = dynamic_cast<Wrapped_Selector*>(ss)) {
47
+ if (Selector_List* sl = dynamic_cast<Selector_List*>(ws->selector())) {
48
+ Selector_List* clean = remove_placeholders(sl);
49
+ // also clean superflous parent selectors
50
+ // probably not really the correct place
51
+ clean->remove_parent_selectors();
52
+ ws->selector(clean);
53
+ }
54
+ }
29
55
  }
56
+ }
57
+ cs = cs->tail();
30
58
  }
31
-
32
- // Set the new placeholder selector list
33
- r->selector(new_sl);
59
+ }
34
60
  }
35
61
 
36
62
  // Iterate into child blocks