sassc 1.10.1 → 1.11.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.
- checksums.yaml +4 -4
- data/README.md +5 -2
- data/ext/libsass/.github/CONTRIBUTING.md +65 -0
- data/ext/libsass/.github/ISSUE_TEMPLATE.md +29 -0
- data/ext/libsass/Makefile +8 -3
- data/ext/libsass/Makefile.conf +28 -22
- data/ext/libsass/Readme.md +14 -7
- data/ext/libsass/configure.ac +5 -8
- data/ext/libsass/docs/api-context-internal.md +3 -0
- data/ext/libsass/docs/api-context.md +7 -0
- data/ext/libsass/docs/api-doc.md +4 -0
- data/ext/libsass/docs/api-importer.md +2 -0
- data/ext/libsass/docs/api-value-example.md +55 -0
- data/ext/libsass/docs/api-value.md +49 -22
- data/ext/libsass/docs/implementations.md +4 -0
- data/ext/libsass/include/sass/base.h +5 -4
- data/ext/libsass/include/sass/context.h +3 -0
- data/ext/libsass/include/sass/values.h +28 -27
- data/ext/libsass/include/sass/version.h +1 -1
- data/ext/libsass/include/sass2scss.h +1 -1
- data/ext/libsass/script/ci-build-libsass +3 -3
- data/ext/libsass/script/ci-install-deps +12 -3
- data/ext/libsass/src/ast.cpp +321 -212
- data/ext/libsass/src/ast.hpp +273 -165
- data/ext/libsass/src/ast_factory.hpp +4 -5
- data/ext/libsass/src/ast_fwd_decl.hpp +8 -7
- data/ext/libsass/src/bind.cpp +2 -7
- data/ext/libsass/src/bind.hpp +0 -1
- data/ext/libsass/src/check_nesting.cpp +379 -0
- data/ext/libsass/src/check_nesting.hpp +60 -0
- data/ext/libsass/src/constants.cpp +7 -6
- data/ext/libsass/src/constants.hpp +2 -1
- data/ext/libsass/src/context.cpp +7 -1
- data/ext/libsass/src/context.hpp +1 -1
- data/ext/libsass/src/cssize.cpp +76 -32
- data/ext/libsass/src/cssize.hpp +7 -8
- data/ext/libsass/src/debugger.hpp +70 -40
- data/ext/libsass/src/error_handling.cpp +15 -2
- data/ext/libsass/src/error_handling.hpp +19 -0
- data/ext/libsass/src/eval.cpp +107 -161
- data/ext/libsass/src/eval.hpp +12 -8
- data/ext/libsass/src/expand.cpp +81 -74
- data/ext/libsass/src/expand.hpp +13 -12
- data/ext/libsass/src/extend.cpp +149 -142
- data/ext/libsass/src/extend.hpp +10 -3
- data/ext/libsass/src/file.cpp +2 -1
- data/ext/libsass/src/functions.cpp +96 -59
- data/ext/libsass/src/functions.hpp +2 -2
- data/ext/libsass/src/inspect.cpp +33 -45
- data/ext/libsass/src/inspect.hpp +7 -7
- data/ext/libsass/src/json.cpp +17 -5
- data/ext/libsass/src/lexer.cpp +3 -3
- data/ext/libsass/src/listize.cpp +10 -10
- data/ext/libsass/src/listize.hpp +3 -3
- data/ext/libsass/src/node.cpp +30 -30
- data/ext/libsass/src/node.hpp +13 -13
- data/ext/libsass/src/operation.hpp +21 -19
- data/ext/libsass/src/output.cpp +48 -103
- data/ext/libsass/src/output.hpp +0 -1
- data/ext/libsass/src/parser.cpp +161 -133
- data/ext/libsass/src/parser.hpp +10 -7
- data/ext/libsass/src/remove_placeholders.cpp +6 -6
- data/ext/libsass/src/remove_placeholders.hpp +1 -1
- data/ext/libsass/src/sass.cpp +21 -0
- data/ext/libsass/src/sass.hpp +8 -1
- data/ext/libsass/src/sass2scss.cpp +14 -3
- data/ext/libsass/src/sass_context.cpp +69 -24
- data/ext/libsass/src/sass_context.hpp +3 -0
- data/ext/libsass/src/source_map.cpp +22 -10
- data/ext/libsass/src/to_value.cpp +2 -2
- data/ext/libsass/src/to_value.hpp +1 -1
- data/ext/libsass/src/units.hpp +3 -1
- data/ext/libsass/src/util.cpp +20 -16
- data/ext/libsass/src/util.hpp +2 -1
- data/ext/libsass/win/libsass.targets +2 -0
- data/ext/libsass/win/libsass.vcxproj.filters +6 -0
- data/lib/sassc/engine.rb +5 -0
- data/lib/sassc/native/native_functions_api.rb +13 -1
- data/lib/sassc/script/value_conversion.rb +11 -1
- data/lib/sassc/script/value_conversion/list.rb +23 -0
- data/lib/sassc/version.rb +1 -1
- data/test/engine_test.rb +18 -2
- data/test/functions_test.rb +30 -0
- data/test/native_test.rb +1 -1
- metadata +8 -3
data/ext/libsass/src/eval.hpp
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
|
4
4
|
#include "ast.hpp"
|
5
5
|
#include "context.hpp"
|
6
|
+
#include "listize.hpp"
|
6
7
|
#include "operation.hpp"
|
7
8
|
#include "environment.hpp"
|
8
9
|
|
@@ -22,11 +23,12 @@ namespace Sass {
|
|
22
23
|
Eval(Expand& exp);
|
23
24
|
~Eval();
|
24
25
|
|
26
|
+
bool force;
|
25
27
|
bool is_in_comment;
|
26
28
|
|
27
29
|
Env* environment();
|
28
30
|
Context& context();
|
29
|
-
|
31
|
+
CommaSequence_Selector* selector();
|
30
32
|
Backtrace* backtrace();
|
31
33
|
|
32
34
|
// for evaluating function bodies
|
@@ -50,11 +52,12 @@ namespace Sass {
|
|
50
52
|
Expression* operator()(Variable*);
|
51
53
|
Expression* operator()(Textual*);
|
52
54
|
Expression* operator()(Number*);
|
55
|
+
Expression* operator()(Color*);
|
53
56
|
Expression* operator()(Boolean*);
|
54
57
|
Expression* operator()(String_Schema*);
|
55
58
|
Expression* operator()(String_Quoted*);
|
56
59
|
Expression* operator()(String_Constant*);
|
57
|
-
// Expression* operator()(
|
60
|
+
// Expression* operator()(CommaSequence_Selector*);
|
58
61
|
Expression* operator()(Media_Query*);
|
59
62
|
Expression* operator()(Media_Query_Expression*);
|
60
63
|
Expression* operator()(At_Root_Query*);
|
@@ -68,17 +71,18 @@ namespace Sass {
|
|
68
71
|
Expression* operator()(Comment*);
|
69
72
|
|
70
73
|
// these will return selectors
|
71
|
-
|
72
|
-
|
74
|
+
CommaSequence_Selector* operator()(CommaSequence_Selector*);
|
75
|
+
CommaSequence_Selector* operator()(Sequence_Selector*);
|
73
76
|
Attribute_Selector* operator()(Attribute_Selector*);
|
74
77
|
// they don't have any specific implementatio (yet)
|
75
|
-
|
78
|
+
Element_Selector* operator()(Element_Selector* s) { return s; };
|
76
79
|
Pseudo_Selector* operator()(Pseudo_Selector* s) { return s; };
|
77
80
|
Wrapped_Selector* operator()(Wrapped_Selector* s) { return s; };
|
78
|
-
|
79
|
-
|
81
|
+
Class_Selector* operator()(Class_Selector* s) { return s; };
|
82
|
+
Id_Selector* operator()(Id_Selector* s) { return s; };
|
83
|
+
Placeholder_Selector* operator()(Placeholder_Selector* s) { return s; };
|
80
84
|
// actual evaluated selectors
|
81
|
-
|
85
|
+
CommaSequence_Selector* operator()(Selector_Schema*);
|
82
86
|
Expression* operator()(Parent_Selector*);
|
83
87
|
|
84
88
|
template <typename U>
|
data/ext/libsass/src/expand.cpp
CHANGED
@@ -11,17 +11,23 @@
|
|
11
11
|
|
12
12
|
namespace Sass {
|
13
13
|
|
14
|
-
|
14
|
+
// simple endless recursion protection
|
15
|
+
const unsigned int maxRecursion = 500;
|
16
|
+
static unsigned int recursions = 0;
|
17
|
+
|
18
|
+
Expand::Expand(Context& ctx, Env* env, Backtrace* bt, std::vector<CommaSequence_Selector*>* stack)
|
15
19
|
: ctx(ctx),
|
16
20
|
eval(Eval(*this)),
|
17
21
|
env_stack(std::vector<Env*>()),
|
18
22
|
block_stack(std::vector<Block*>()),
|
19
23
|
call_stack(std::vector<AST_Node*>()),
|
20
24
|
property_stack(std::vector<String*>()),
|
21
|
-
selector_stack(std::vector<
|
25
|
+
selector_stack(std::vector<CommaSequence_Selector*>()),
|
22
26
|
media_block_stack(std::vector<Media_Block*>()),
|
23
27
|
backtrace_stack(std::vector<Backtrace*>()),
|
24
|
-
in_keyframes(false)
|
28
|
+
in_keyframes(false),
|
29
|
+
at_root_without_rule(false),
|
30
|
+
old_at_root_without_rule(false)
|
25
31
|
{
|
26
32
|
env_stack.push_back(0);
|
27
33
|
env_stack.push_back(env);
|
@@ -29,7 +35,8 @@ namespace Sass {
|
|
29
35
|
call_stack.push_back(0);
|
30
36
|
// import_stack.push_back(0);
|
31
37
|
property_stack.push_back(0);
|
32
|
-
selector_stack.push_back(0);
|
38
|
+
if (stack == NULL) { selector_stack.push_back(0); }
|
39
|
+
else { selector_stack.insert(selector_stack.end(), stack->begin(), stack->end()); }
|
33
40
|
media_block_stack.push_back(0);
|
34
41
|
backtrace_stack.push_back(0);
|
35
42
|
backtrace_stack.push_back(bt);
|
@@ -47,7 +54,7 @@ namespace Sass {
|
|
47
54
|
return 0;
|
48
55
|
}
|
49
56
|
|
50
|
-
|
57
|
+
CommaSequence_Selector* Expand::selector()
|
51
58
|
{
|
52
59
|
if (selector_stack.size() > 0)
|
53
60
|
return selector_stack.back();
|
@@ -86,23 +93,26 @@ namespace Sass {
|
|
86
93
|
|
87
94
|
Statement* Expand::operator()(Ruleset* r)
|
88
95
|
{
|
89
|
-
|
96
|
+
LOCAL_FLAG(old_at_root_without_rule, at_root_without_rule);
|
90
97
|
|
91
98
|
if (in_keyframes) {
|
92
99
|
Keyframe_Rule* k = SASS_MEMORY_NEW(ctx.mem, Keyframe_Rule, r->pstate(), r->block()->perform(this)->block());
|
93
100
|
if (r->selector()) {
|
94
101
|
selector_stack.push_back(0);
|
95
|
-
k->selector(static_cast<
|
102
|
+
k->selector(static_cast<CommaSequence_Selector*>(r->selector()->perform(&eval)));
|
96
103
|
selector_stack.pop_back();
|
97
104
|
}
|
98
105
|
return k;
|
99
106
|
}
|
100
107
|
|
108
|
+
// reset when leaving scope
|
109
|
+
LOCAL_FLAG(at_root_without_rule, false);
|
110
|
+
|
101
111
|
// do some special checks for the base level rules
|
102
112
|
if (r->is_root()) {
|
103
|
-
if (
|
104
|
-
for (
|
105
|
-
|
113
|
+
if (CommaSequence_Selector* selector_list = dynamic_cast<CommaSequence_Selector*>(r->selector())) {
|
114
|
+
for (Sequence_Selector* complex_selector : selector_list->elements()) {
|
115
|
+
Sequence_Selector* tail = complex_selector;
|
106
116
|
while (tail) {
|
107
117
|
if (tail->head()) for (Simple_Selector* header : tail->head()->elements()) {
|
108
118
|
if (dynamic_cast<Parent_Selector*>(header) == NULL) continue; // skip all others
|
@@ -116,13 +126,13 @@ namespace Sass {
|
|
116
126
|
}
|
117
127
|
|
118
128
|
Expression* ex = r->selector()->perform(&eval);
|
119
|
-
|
129
|
+
CommaSequence_Selector* sel = dynamic_cast<CommaSequence_Selector*>(ex);
|
120
130
|
if (sel == 0) throw std::runtime_error("Expanded null selector");
|
121
131
|
|
122
132
|
if (sel->length() == 0 || sel->has_parent_ref()) {
|
123
133
|
bool has_parent_selector = false;
|
124
134
|
for (size_t i = 0, L = selector_stack.size(); i < L && !has_parent_selector; i++) {
|
125
|
-
|
135
|
+
CommaSequence_Selector* ll = selector_stack.at(i);
|
126
136
|
has_parent_selector = ll != 0 && ll->length() > 0;
|
127
137
|
}
|
128
138
|
if (!has_parent_selector) {
|
@@ -131,10 +141,9 @@ namespace Sass {
|
|
131
141
|
}
|
132
142
|
|
133
143
|
selector_stack.push_back(sel);
|
134
|
-
Env
|
144
|
+
Env env(environment());
|
135
145
|
if (block_stack.back()->is_root()) {
|
136
|
-
env
|
137
|
-
env_stack.push_back(env);
|
146
|
+
env_stack.push_back(&env);
|
138
147
|
}
|
139
148
|
sel->set_media_block(media_block_stack.back());
|
140
149
|
Block* blk = r->block()->perform(this)->block();
|
@@ -145,48 +154,14 @@ namespace Sass {
|
|
145
154
|
selector_stack.pop_back();
|
146
155
|
if (block_stack.back()->is_root()) {
|
147
156
|
env_stack.pop_back();
|
148
|
-
delete env;
|
149
157
|
}
|
158
|
+
|
150
159
|
rr->is_root(r->is_root());
|
151
160
|
rr->tabs(r->tabs());
|
152
161
|
|
153
162
|
return rr;
|
154
163
|
}
|
155
164
|
|
156
|
-
Statement* Expand::operator()(Propset* p)
|
157
|
-
{
|
158
|
-
property_stack.push_back(p->property_fragment());
|
159
|
-
Block* expanded_block = p->block()->perform(this)->block();
|
160
|
-
|
161
|
-
for (size_t i = 0, L = expanded_block->length(); i < L; ++i) {
|
162
|
-
Statement* stm = (*expanded_block)[i];
|
163
|
-
if (Declaration* dec = static_cast<Declaration*>(stm)) {
|
164
|
-
String_Schema* combined_prop = SASS_MEMORY_NEW(ctx.mem, String_Schema, p->pstate());
|
165
|
-
if (!property_stack.empty()) {
|
166
|
-
*combined_prop << property_stack.back()->perform(&eval)
|
167
|
-
<< SASS_MEMORY_NEW(ctx.mem, String_Quoted,
|
168
|
-
p->pstate(), "-")
|
169
|
-
<< dec->property(); // TODO: eval the prop into a string constant
|
170
|
-
}
|
171
|
-
else {
|
172
|
-
*combined_prop << dec->property();
|
173
|
-
}
|
174
|
-
dec->property(combined_prop);
|
175
|
-
*block_stack.back() << dec;
|
176
|
-
}
|
177
|
-
else if (typeid(*stm) == typeid(Comment)) {
|
178
|
-
// drop comments in propsets
|
179
|
-
}
|
180
|
-
else {
|
181
|
-
error("contents of namespaced properties must result in style declarations only", stm->pstate(), backtrace());
|
182
|
-
}
|
183
|
-
}
|
184
|
-
|
185
|
-
property_stack.pop_back();
|
186
|
-
|
187
|
-
return 0;
|
188
|
-
}
|
189
|
-
|
190
165
|
Statement* Expand::operator()(Supports_Block* f)
|
191
166
|
{
|
192
167
|
Expression* condition = f->condition()->perform(&eval);
|
@@ -219,16 +194,19 @@ namespace Sass {
|
|
219
194
|
Statement* Expand::operator()(At_Root_Block* a)
|
220
195
|
{
|
221
196
|
Block* ab = a->block();
|
222
|
-
// if (ab) ab->is_root(true);
|
223
197
|
Expression* ae = a->expression();
|
198
|
+
|
224
199
|
if (ae) ae = ae->perform(&eval);
|
225
200
|
else ae = SASS_MEMORY_NEW(ctx.mem, At_Root_Query, a->pstate());
|
201
|
+
|
202
|
+
LOCAL_FLAG(at_root_without_rule, true);
|
203
|
+
LOCAL_FLAG(in_keyframes, false);
|
204
|
+
|
226
205
|
Block* bb = ab ? ab->perform(this)->block() : 0;
|
227
206
|
At_Root_Block* aa = SASS_MEMORY_NEW(ctx.mem, At_Root_Block,
|
228
207
|
a->pstate(),
|
229
208
|
bb,
|
230
209
|
static_cast<At_Root_Query*>(ae));
|
231
|
-
// aa->block()->is_root(true);
|
232
210
|
return aa;
|
233
211
|
}
|
234
212
|
|
@@ -254,15 +232,20 @@ namespace Sass {
|
|
254
232
|
|
255
233
|
Statement* Expand::operator()(Declaration* d)
|
256
234
|
{
|
235
|
+
Block* ab = d->block();
|
257
236
|
String* old_p = d->property();
|
258
237
|
String* new_p = static_cast<String*>(old_p->perform(&eval));
|
259
238
|
Expression* value = d->value()->perform(&eval);
|
260
|
-
|
239
|
+
Block* bb = ab ? ab->perform(this)->block() : 0;
|
240
|
+
if (!bb) {
|
241
|
+
if (!value || (value->is_invisible() && !d->is_important())) return 0;
|
242
|
+
}
|
261
243
|
Declaration* decl = SASS_MEMORY_NEW(ctx.mem, Declaration,
|
262
244
|
d->pstate(),
|
263
245
|
new_p,
|
264
246
|
value,
|
265
|
-
d->is_important()
|
247
|
+
d->is_important(),
|
248
|
+
bb);
|
266
249
|
decl->tabs(d->tabs());
|
267
250
|
return decl;
|
268
251
|
}
|
@@ -477,7 +460,7 @@ namespace Sass {
|
|
477
460
|
if (expr->concrete_type() == Expression::MAP) {
|
478
461
|
map = static_cast<Map*>(expr);
|
479
462
|
}
|
480
|
-
else if (
|
463
|
+
else if (CommaSequence_Selector* ls = dynamic_cast<CommaSequence_Selector*>(expr)) {
|
481
464
|
Listize listize(ctx.mem);
|
482
465
|
list = dynamic_cast<List*>(ls->perform(&listize));
|
483
466
|
}
|
@@ -513,7 +496,7 @@ namespace Sass {
|
|
513
496
|
}
|
514
497
|
else {
|
515
498
|
// bool arglist = list->is_arglist();
|
516
|
-
if (list->length() == 1 && dynamic_cast<
|
499
|
+
if (list->length() == 1 && dynamic_cast<CommaSequence_Selector*>(list)) {
|
517
500
|
list = dynamic_cast<Vectorized<Expression*>*>(list);
|
518
501
|
}
|
519
502
|
for (size_t i = 0, L = list->length(); i < L; ++i) {
|
@@ -573,11 +556,11 @@ namespace Sass {
|
|
573
556
|
}
|
574
557
|
|
575
558
|
|
576
|
-
void Expand::expand_selector_list(Selector* s,
|
559
|
+
void Expand::expand_selector_list(Selector* s, CommaSequence_Selector* extender) {
|
577
560
|
|
578
|
-
if (
|
579
|
-
for (
|
580
|
-
|
561
|
+
if (CommaSequence_Selector* sl = dynamic_cast<CommaSequence_Selector*>(s)) {
|
562
|
+
for (Sequence_Selector* complex_selector : sl->elements()) {
|
563
|
+
Sequence_Selector* tail = complex_selector;
|
581
564
|
while (tail) {
|
582
565
|
if (tail->head()) for (Simple_Selector* header : tail->head()->elements()) {
|
583
566
|
if (dynamic_cast<Parent_Selector*>(header) == NULL) continue; // skip all others
|
@@ -590,24 +573,24 @@ namespace Sass {
|
|
590
573
|
}
|
591
574
|
|
592
575
|
|
593
|
-
|
576
|
+
CommaSequence_Selector* contextualized = dynamic_cast<CommaSequence_Selector*>(s->perform(&eval));
|
594
577
|
if (contextualized == NULL) return;
|
595
578
|
for (auto complex_sel : contextualized->elements()) {
|
596
|
-
|
579
|
+
Sequence_Selector* c = complex_sel;
|
597
580
|
if (!c->head() || c->tail()) {
|
598
581
|
std::string sel_str(contextualized->to_string(ctx.c_options));
|
599
582
|
error("Can't extend " + sel_str + ": can't extend nested selectors", c->pstate(), backtrace());
|
600
583
|
}
|
601
|
-
|
584
|
+
SimpleSequence_Selector* placeholder = c->head();
|
602
585
|
if (contextualized->is_optional()) placeholder->is_optional(true);
|
603
586
|
for (size_t i = 0, L = extender->length(); i < L; ++i) {
|
604
|
-
|
587
|
+
Sequence_Selector* sel = (*extender)[i];
|
605
588
|
if (!(sel->head() && sel->head()->length() > 0 &&
|
606
589
|
dynamic_cast<Parent_Selector*>((*sel->head())[0])))
|
607
590
|
{
|
608
|
-
|
591
|
+
SimpleSequence_Selector* hh = SASS_MEMORY_NEW(ctx.mem, SimpleSequence_Selector, (*extender)[i]->pstate());
|
609
592
|
hh->media_block((*extender)[i]->media_block());
|
610
|
-
|
593
|
+
Sequence_Selector* ssel = SASS_MEMORY_NEW(ctx.mem, Sequence_Selector, (*extender)[i]->pstate());
|
611
594
|
ssel->media_block((*extender)[i]->media_block());
|
612
595
|
if (sel->has_line_feed()) ssel->has_line_feed(true);
|
613
596
|
Parent_Selector* ps = SASS_MEMORY_NEW(ctx.mem, Parent_Selector, (*extender)[i]->pstate());
|
@@ -626,13 +609,13 @@ namespace Sass {
|
|
626
609
|
|
627
610
|
Statement* Expand::operator()(Extension* e)
|
628
611
|
{
|
629
|
-
if (
|
612
|
+
if (CommaSequence_Selector* extender = dynamic_cast<CommaSequence_Selector*>(selector())) {
|
630
613
|
Selector* s = e->selector();
|
631
614
|
if (Selector_Schema* schema = dynamic_cast<Selector_Schema*>(s)) {
|
632
615
|
if (schema->has_parent_ref()) s = eval(schema);
|
633
616
|
}
|
634
|
-
if (
|
635
|
-
for (
|
617
|
+
if (CommaSequence_Selector* sl = dynamic_cast<CommaSequence_Selector*>(s)) {
|
618
|
+
for (Sequence_Selector* cs : *sl) {
|
636
619
|
if (cs != NULL && cs->head() != NULL) {
|
637
620
|
cs->head()->media_block(media_block_stack.back());
|
638
621
|
}
|
@@ -673,6 +656,12 @@ namespace Sass {
|
|
673
656
|
|
674
657
|
Statement* Expand::operator()(Mixin_Call* c)
|
675
658
|
{
|
659
|
+
recursions ++;
|
660
|
+
|
661
|
+
if (recursions > maxRecursion) {
|
662
|
+
throw Exception::StackError(*c);
|
663
|
+
}
|
664
|
+
|
676
665
|
Env* env = environment();
|
677
666
|
std::string full_name(c->name() + "[m]");
|
678
667
|
if (!env->has(full_name)) {
|
@@ -704,10 +693,23 @@ namespace Sass {
|
|
704
693
|
}
|
705
694
|
|
706
695
|
bind(std::string("Mixin"), c->name(), params, args, &ctx, &new_env, &eval);
|
707
|
-
|
708
|
-
|
696
|
+
|
697
|
+
Block* trace_block = SASS_MEMORY_NEW(ctx.mem, Block, c->pstate());
|
698
|
+
Trace* trace = SASS_MEMORY_NEW(ctx.mem, Trace, c->pstate(), c->name(), trace_block);
|
699
|
+
|
700
|
+
|
701
|
+
block_stack.push_back(trace_block);
|
702
|
+
for (auto bb : *body) {
|
703
|
+
Statement* ith = bb->perform(this);
|
704
|
+
if (ith) *trace->block() << ith;
|
705
|
+
}
|
706
|
+
block_stack.pop_back();
|
707
|
+
|
709
708
|
env_stack.pop_back();
|
710
|
-
|
709
|
+
backtrace_stack.pop_back();
|
710
|
+
|
711
|
+
recursions --;
|
712
|
+
return trace;
|
711
713
|
}
|
712
714
|
|
713
715
|
Statement* Expand::operator()(Content* c)
|
@@ -715,18 +717,23 @@ namespace Sass {
|
|
715
717
|
Env* env = environment();
|
716
718
|
// convert @content directives into mixin calls to the underlying thunk
|
717
719
|
if (!env->has("@content[m]")) return 0;
|
720
|
+
|
718
721
|
if (block_stack.back()->is_root()) {
|
719
722
|
selector_stack.push_back(0);
|
720
723
|
}
|
724
|
+
|
721
725
|
Mixin_Call* call = SASS_MEMORY_NEW(ctx.mem, Mixin_Call,
|
722
726
|
c->pstate(),
|
723
727
|
"@content",
|
724
728
|
SASS_MEMORY_NEW(ctx.mem, Arguments, c->pstate()));
|
725
|
-
|
729
|
+
|
730
|
+
Trace* trace = dynamic_cast<Trace*>(call->perform(this));
|
731
|
+
|
726
732
|
if (block_stack.back()->is_root()) {
|
727
733
|
selector_stack.pop_back();
|
728
734
|
}
|
729
|
-
|
735
|
+
|
736
|
+
return trace;
|
730
737
|
}
|
731
738
|
|
732
739
|
// produce an error if something is not implemented
|
data/ext/libsass/src/expand.hpp
CHANGED
@@ -21,34 +21,35 @@ namespace Sass {
|
|
21
21
|
|
22
22
|
Env* environment();
|
23
23
|
Context& context();
|
24
|
-
|
24
|
+
CommaSequence_Selector* selector();
|
25
25
|
Backtrace* backtrace();
|
26
26
|
|
27
27
|
Context& ctx;
|
28
28
|
Eval eval;
|
29
29
|
|
30
30
|
// it's easier to work with vectors
|
31
|
-
std::vector<Env*>
|
32
|
-
std::vector<Block*>
|
33
|
-
std::vector<AST_Node*>
|
34
|
-
std::vector<String*>
|
35
|
-
std::vector<
|
36
|
-
std::vector<Media_Block*>
|
37
|
-
std::vector<Backtrace*>backtrace_stack;
|
38
|
-
bool
|
31
|
+
std::vector<Env*> env_stack;
|
32
|
+
std::vector<Block*> block_stack;
|
33
|
+
std::vector<AST_Node*> call_stack;
|
34
|
+
std::vector<String*> property_stack;
|
35
|
+
std::vector<CommaSequence_Selector*> selector_stack;
|
36
|
+
std::vector<Media_Block*> media_block_stack;
|
37
|
+
std::vector<Backtrace*> backtrace_stack;
|
38
|
+
bool in_keyframes;
|
39
|
+
bool at_root_without_rule;
|
40
|
+
bool old_at_root_without_rule;
|
39
41
|
|
40
42
|
Statement* fallback_impl(AST_Node* n);
|
41
43
|
|
42
44
|
private:
|
43
|
-
void expand_selector_list(Selector*,
|
45
|
+
void expand_selector_list(Selector*, CommaSequence_Selector* extender);
|
44
46
|
|
45
47
|
public:
|
46
|
-
Expand(Context&, Env*, Backtrace
|
48
|
+
Expand(Context&, Env*, Backtrace*, std::vector<CommaSequence_Selector*>* stack = NULL);
|
47
49
|
~Expand() { }
|
48
50
|
|
49
51
|
Statement* operator()(Block*);
|
50
52
|
Statement* operator()(Ruleset*);
|
51
|
-
Statement* operator()(Propset*);
|
52
53
|
Statement* operator()(Media_Block*);
|
53
54
|
Statement* operator()(Supports_Block*);
|
54
55
|
Statement* operator()(At_Root_Block*);
|
data/ext/libsass/src/extend.cpp
CHANGED
@@ -62,26 +62,26 @@
|
|
62
62
|
namespace Sass {
|
63
63
|
|
64
64
|
|
65
|
-
typedef std::pair<
|
65
|
+
typedef std::pair<Sequence_Selector*, SimpleSequence_Selector*> ExtensionPair;
|
66
66
|
typedef std::vector<ExtensionPair> SubsetMapEntries;
|
67
67
|
|
68
68
|
#ifdef DEBUG
|
69
69
|
|
70
70
|
// TODO: move the ast specific ostream operators into ast.hpp/ast.cpp
|
71
|
-
std::ostream& operator<<(std::ostream& os, const
|
71
|
+
std::ostream& operator<<(std::ostream& os, const Sequence_Selector::Combinator combinator) {
|
72
72
|
switch (combinator) {
|
73
|
-
case
|
74
|
-
case
|
75
|
-
case
|
76
|
-
case
|
77
|
-
case
|
73
|
+
case Sequence_Selector::ANCESTOR_OF: os << "\" \""; break;
|
74
|
+
case Sequence_Selector::PARENT_OF: os << "\">\""; break;
|
75
|
+
case Sequence_Selector::PRECEDES: os << "\"~\""; break;
|
76
|
+
case Sequence_Selector::ADJACENT_TO: os << "\"+\""; break;
|
77
|
+
case Sequence_Selector::REFERENCE: os << "\"/\""; break;
|
78
78
|
}
|
79
79
|
|
80
80
|
return os;
|
81
81
|
}
|
82
82
|
|
83
83
|
|
84
|
-
std::ostream& operator<<(std::ostream& os,
|
84
|
+
std::ostream& operator<<(std::ostream& os, SimpleSequence_Selector& compoundSelector) {
|
85
85
|
for (size_t i = 0, L = compoundSelector.length(); i < L; ++i) {
|
86
86
|
if (i > 0) os << ", ";
|
87
87
|
os << compoundSelector[i]->to_string();
|
@@ -94,7 +94,7 @@ namespace Sass {
|
|
94
94
|
return os;
|
95
95
|
}
|
96
96
|
|
97
|
-
// Print a string representation of a
|
97
|
+
// Print a string representation of a SimpleSequence_Selector
|
98
98
|
static void printSimpleSelector(Simple_Selector* pSimpleSelector, const char* message=NULL, bool newline=true) {
|
99
99
|
|
100
100
|
if (message) {
|
@@ -112,13 +112,13 @@ namespace Sass {
|
|
112
112
|
}
|
113
113
|
}
|
114
114
|
|
115
|
-
// Print a string representation of a
|
116
|
-
typedef std::pair<
|
115
|
+
// Print a string representation of a SimpleSequence_Selector
|
116
|
+
typedef std::pair<SimpleSequence_Selector*, Sequence_Selector*> SelsNewSeqPair;
|
117
117
|
typedef std::vector<SelsNewSeqPair> SelsNewSeqPairCollection;
|
118
118
|
|
119
119
|
|
120
|
-
// Print a string representation of a
|
121
|
-
static void printCompoundSelector(
|
120
|
+
// Print a string representation of a SimpleSequence_Selector
|
121
|
+
static void printCompoundSelector(SimpleSequence_Selector* pCompoundSelector, const char* message=NULL, bool newline=true) {
|
122
122
|
|
123
123
|
if (message) {
|
124
124
|
std::cerr << message;
|
@@ -136,13 +136,13 @@ namespace Sass {
|
|
136
136
|
}
|
137
137
|
|
138
138
|
|
139
|
-
std::ostream& operator<<(std::ostream& os,
|
139
|
+
std::ostream& operator<<(std::ostream& os, Sequence_Selector& complexSelector) {
|
140
140
|
|
141
141
|
os << "[";
|
142
|
-
|
142
|
+
Sequence_Selector* pIter = &complexSelector;
|
143
143
|
bool first = true;
|
144
144
|
while (pIter) {
|
145
|
-
if (pIter->combinator() !=
|
145
|
+
if (pIter->combinator() != Sequence_Selector::ANCESTOR_OF) {
|
146
146
|
if (!first) {
|
147
147
|
os << ", ";
|
148
148
|
}
|
@@ -169,8 +169,8 @@ namespace Sass {
|
|
169
169
|
}
|
170
170
|
|
171
171
|
|
172
|
-
// Print a string representation of a
|
173
|
-
static void printComplexSelector(
|
172
|
+
// Print a string representation of a Sequence_Selector
|
173
|
+
static void printComplexSelector(Sequence_Selector* pComplexSelector, const char* message=NULL, bool newline=true) {
|
174
174
|
|
175
175
|
if (message) {
|
176
176
|
std::cerr << message;
|
@@ -201,8 +201,8 @@ namespace Sass {
|
|
201
201
|
std::cerr << ", ";
|
202
202
|
}
|
203
203
|
std::cerr << "[";
|
204
|
-
|
205
|
-
|
204
|
+
SimpleSequence_Selector* pSels = pair.first;
|
205
|
+
Sequence_Selector* pNewSelector = pair.second;
|
206
206
|
std::cerr << "[" << *pSels << "], ";
|
207
207
|
printComplexSelector(pNewSelector, NULL, false);
|
208
208
|
}
|
@@ -225,7 +225,7 @@ namespace Sass {
|
|
225
225
|
typedef std::deque<std::string> SourceStrings;
|
226
226
|
SourceStrings sourceStrings;
|
227
227
|
for (SourcesSet::iterator iterator = sources.begin(), iteratorEnd = sources.end(); iterator != iteratorEnd; ++iterator) {
|
228
|
-
|
228
|
+
Sequence_Selector* pSource = *iterator;
|
229
229
|
std::stringstream sstream;
|
230
230
|
sstream << complexSelectorToNode(pSource, ctx);
|
231
231
|
sourceStrings.push_back(sstream.str());
|
@@ -254,8 +254,8 @@ namespace Sass {
|
|
254
254
|
os << "SUBSET_MAP_ENTRIES[";
|
255
255
|
|
256
256
|
for (SubsetMapEntries::iterator iterator = entries.begin(), endIterator = entries.end(); iterator != endIterator; ++iterator) {
|
257
|
-
|
258
|
-
|
257
|
+
Sequence_Selector* pExtComplexSelector = iterator->first; // The selector up to where the @extend is (ie, the thing to merge)
|
258
|
+
SimpleSequence_Selector* pExtCompoundSelector = iterator->second; // The stuff after the @extend
|
259
259
|
|
260
260
|
if (iterator != entries.begin()) {
|
261
261
|
os << ", ";
|
@@ -287,17 +287,17 @@ namespace Sass {
|
|
287
287
|
}
|
288
288
|
#endif
|
289
289
|
|
290
|
-
static bool parentSuperselector(
|
291
|
-
// TODO: figure out a better way to create a
|
290
|
+
static bool parentSuperselector(Sequence_Selector* pOne, Sequence_Selector* pTwo, Context& ctx) {
|
291
|
+
// TODO: figure out a better way to create a Sequence_Selector from scratch
|
292
292
|
// TODO: There's got to be a better way. This got ugly quick...
|
293
293
|
Position noPosition(-1, -1, -1);
|
294
|
-
|
295
|
-
|
294
|
+
Element_Selector fakeParent(ParserState("[FAKE]"), "temp");
|
295
|
+
SimpleSequence_Selector fakeHead(ParserState("[FAKE]"), 1 /*size*/);
|
296
296
|
fakeHead.elements().push_back(&fakeParent);
|
297
|
-
|
297
|
+
Sequence_Selector fakeParentContainer(ParserState("[FAKE]"), Sequence_Selector::ANCESTOR_OF, &fakeHead /*head*/, NULL /*tail*/);
|
298
298
|
|
299
|
-
pOne->set_innermost(&fakeParentContainer,
|
300
|
-
pTwo->set_innermost(&fakeParentContainer,
|
299
|
+
pOne->set_innermost(&fakeParentContainer, Sequence_Selector::ANCESTOR_OF);
|
300
|
+
pTwo->set_innermost(&fakeParentContainer, Sequence_Selector::ANCESTOR_OF);
|
301
301
|
|
302
302
|
bool isSuperselector = pOne->is_superselector_of(pTwo);
|
303
303
|
|
@@ -318,7 +318,7 @@ namespace Sass {
|
|
318
318
|
Node result = Node::createCollection();
|
319
319
|
|
320
320
|
for (ComplexSelectorDeque::const_iterator iter = deque.begin(), iterEnd = deque.end(); iter != iterEnd; iter++) {
|
321
|
-
|
321
|
+
Sequence_Selector* pChild = *iter;
|
322
322
|
result.collection()->push_back(complexSelectorToNode(pChild, ctx));
|
323
323
|
}
|
324
324
|
|
@@ -331,7 +331,7 @@ namespace Sass {
|
|
331
331
|
|
332
332
|
Context& mCtx;
|
333
333
|
|
334
|
-
bool operator()(
|
334
|
+
bool operator()(Sequence_Selector* pOne, Sequence_Selector* pTwo, Sequence_Selector*& pOut) const {
|
335
335
|
/*
|
336
336
|
This code is based on the following block from ruby sass' subweave
|
337
337
|
do |s1, s2|
|
@@ -347,7 +347,7 @@ namespace Sass {
|
|
347
347
|
return true;
|
348
348
|
}
|
349
349
|
|
350
|
-
if (pOne->combinator() !=
|
350
|
+
if (pOne->combinator() != Sequence_Selector::ANCESTOR_OF || pTwo->combinator() != Sequence_Selector::ANCESTOR_OF) {
|
351
351
|
return false;
|
352
352
|
}
|
353
353
|
|
@@ -382,7 +382,7 @@ namespace Sass {
|
|
382
382
|
}
|
383
383
|
|
384
384
|
|
385
|
-
|
385
|
+
Sequence_Selector* pCompareOut = NULL;
|
386
386
|
if (comparator(x[i], y[j], pCompareOut)) {
|
387
387
|
DEBUG_PRINTLN(LCS, "RETURNING AFTER ELEM COMPARE")
|
388
388
|
lcs_backtrace(c, x, y, i - 1, j - 1, comparator, out);
|
@@ -419,7 +419,7 @@ namespace Sass {
|
|
419
419
|
|
420
420
|
for (size_t i = 1; i < x.size(); i++) {
|
421
421
|
for (size_t j = 1; j < y.size(); j++) {
|
422
|
-
|
422
|
+
Sequence_Selector* pCompareOut = NULL;
|
423
423
|
|
424
424
|
if (comparator(x[i], y[j], pCompareOut)) {
|
425
425
|
c[i][j] = c[i - 1][j - 1] + 1;
|
@@ -559,7 +559,7 @@ namespace Sass {
|
|
559
559
|
for (NodeDeque::iterator seqs1Iter = seqs1.collection()->begin(), seqs1EndIter = seqs1.collection()->end(); seqs1Iter != seqs1EndIter; ++seqs1Iter) {
|
560
560
|
Node& seq1 = *seqs1Iter;
|
561
561
|
|
562
|
-
|
562
|
+
Sequence_Selector* pSeq1 = nodeToComplexSelector(seq1, ctx);
|
563
563
|
|
564
564
|
// Compute the maximum specificity. This requires looking at the "sources" of the sequence. See SimpleSequence.sources in the ruby code
|
565
565
|
// for a good description of sources.
|
@@ -576,7 +576,7 @@ namespace Sass {
|
|
576
576
|
DEBUG_EXEC(TRIM, printSourcesSet(sources, ctx, "TRIM SOURCES: "))
|
577
577
|
|
578
578
|
for (SourcesSet::iterator sourcesSetIterator = sources.begin(), sourcesSetIteratorEnd = sources.end(); sourcesSetIterator != sourcesSetIteratorEnd; ++sourcesSetIterator) {
|
579
|
-
const
|
579
|
+
const Sequence_Selector* const pCurrentSelector = *sourcesSetIterator;
|
580
580
|
maxSpecificity = std::max(maxSpecificity, pCurrentSelector->specificity());
|
581
581
|
}
|
582
582
|
|
@@ -606,7 +606,7 @@ namespace Sass {
|
|
606
606
|
for (NodeDeque::iterator seqs2Iter = seqs2.collection()->begin(), seqs2IterEnd = seqs2.collection()->end(); seqs2Iter != seqs2IterEnd; ++seqs2Iter) {
|
607
607
|
Node& seq2 = *seqs2Iter;
|
608
608
|
|
609
|
-
|
609
|
+
Sequence_Selector* pSeq2 = nodeToComplexSelector(seq2, ctx);
|
610
610
|
|
611
611
|
DEBUG_PRINTLN(TRIM, "SEQ2 SPEC: " << pSeq2->specificity())
|
612
612
|
DEBUG_PRINTLN(TRIM, "IS SPEC: " << pSeq2->specificity() << " >= " << maxSpecificity << " " << (pSeq2->specificity() >= maxSpecificity ? "true" : "false"))
|
@@ -651,18 +651,18 @@ namespace Sass {
|
|
651
651
|
|
652
652
|
|
653
653
|
static bool parentSuperselector(const Node& one, const Node& two, Context& ctx) {
|
654
|
-
// TODO: figure out a better way to create a
|
654
|
+
// TODO: figure out a better way to create a Sequence_Selector from scratch
|
655
655
|
// TODO: There's got to be a better way. This got ugly quick...
|
656
656
|
Position noPosition(-1, -1, -1);
|
657
|
-
|
658
|
-
|
657
|
+
Element_Selector fakeParent(ParserState("[FAKE]"), "temp");
|
658
|
+
SimpleSequence_Selector fakeHead(ParserState("[FAKE]"), 1 /*size*/);
|
659
659
|
fakeHead.elements().push_back(&fakeParent);
|
660
|
-
|
660
|
+
Sequence_Selector fakeParentContainer(ParserState("[FAKE]"), Sequence_Selector::ANCESTOR_OF, &fakeHead /*head*/, NULL /*tail*/);
|
661
661
|
|
662
|
-
|
663
|
-
pOneWithFakeParent->set_innermost(&fakeParentContainer,
|
664
|
-
|
665
|
-
pTwoWithFakeParent->set_innermost(&fakeParentContainer,
|
662
|
+
Sequence_Selector* pOneWithFakeParent = nodeToComplexSelector(one, ctx);
|
663
|
+
pOneWithFakeParent->set_innermost(&fakeParentContainer, Sequence_Selector::ANCESTOR_OF);
|
664
|
+
Sequence_Selector* pTwoWithFakeParent = nodeToComplexSelector(two, ctx);
|
665
|
+
pTwoWithFakeParent->set_innermost(&fakeParentContainer, Sequence_Selector::ANCESTOR_OF);
|
666
666
|
|
667
667
|
return pOneWithFakeParent->is_superselector_of(pTwoWithFakeParent);
|
668
668
|
}
|
@@ -970,7 +970,7 @@ namespace Sass {
|
|
970
970
|
Node sel2 = seq2.collection()->back();
|
971
971
|
seq2.collection()->pop_back();
|
972
972
|
|
973
|
-
if (op1.combinator() ==
|
973
|
+
if (op1.combinator() == Sequence_Selector::PRECEDES && op2.combinator() == Sequence_Selector::PRECEDES) {
|
974
974
|
|
975
975
|
if (sel1.selector()->is_superselector_of(sel2.selector())) {
|
976
976
|
|
@@ -987,9 +987,9 @@ namespace Sass {
|
|
987
987
|
DEBUG_PRINTLN(ALL, "sel1: " << sel1)
|
988
988
|
DEBUG_PRINTLN(ALL, "sel2: " << sel2)
|
989
989
|
|
990
|
-
|
990
|
+
Sequence_Selector* pMergedWrapper = sel1.selector()->clone(ctx); // Clone the Sequence_Selector to get back to something we can transform to a node once we replace the head with the unification result
|
991
991
|
// TODO: does subject matter? Ruby: return unless merged = sel1.unify(sel2.members, sel2.subject?)
|
992
|
-
|
992
|
+
SimpleSequence_Selector* pMerged = sel1.selector()->head()->unify_with(sel2.selector()->head(), ctx);
|
993
993
|
pMergedWrapper->head(pMerged);
|
994
994
|
|
995
995
|
DEBUG_EXEC(ALL, printCompoundSelector(pMerged, "MERGED: "))
|
@@ -998,22 +998,22 @@ namespace Sass {
|
|
998
998
|
|
999
999
|
Node firstPerm = Node::createCollection();
|
1000
1000
|
firstPerm.collection()->push_back(sel1);
|
1001
|
-
firstPerm.collection()->push_back(Node::createCombinator(
|
1001
|
+
firstPerm.collection()->push_back(Node::createCombinator(Sequence_Selector::PRECEDES));
|
1002
1002
|
firstPerm.collection()->push_back(sel2);
|
1003
|
-
firstPerm.collection()->push_back(Node::createCombinator(
|
1003
|
+
firstPerm.collection()->push_back(Node::createCombinator(Sequence_Selector::PRECEDES));
|
1004
1004
|
newRes.collection()->push_back(firstPerm);
|
1005
1005
|
|
1006
1006
|
Node secondPerm = Node::createCollection();
|
1007
1007
|
secondPerm.collection()->push_back(sel2);
|
1008
|
-
secondPerm.collection()->push_back(Node::createCombinator(
|
1008
|
+
secondPerm.collection()->push_back(Node::createCombinator(Sequence_Selector::PRECEDES));
|
1009
1009
|
secondPerm.collection()->push_back(sel1);
|
1010
|
-
secondPerm.collection()->push_back(Node::createCombinator(
|
1010
|
+
secondPerm.collection()->push_back(Node::createCombinator(Sequence_Selector::PRECEDES));
|
1011
1011
|
newRes.collection()->push_back(secondPerm);
|
1012
1012
|
|
1013
1013
|
if (pMerged) {
|
1014
1014
|
Node mergedPerm = Node::createCollection();
|
1015
1015
|
mergedPerm.collection()->push_back(Node::createSelector(pMergedWrapper, ctx));
|
1016
|
-
mergedPerm.collection()->push_back(Node::createCombinator(
|
1016
|
+
mergedPerm.collection()->push_back(Node::createCombinator(Sequence_Selector::PRECEDES));
|
1017
1017
|
newRes.collection()->push_back(mergedPerm);
|
1018
1018
|
}
|
1019
1019
|
|
@@ -1023,13 +1023,13 @@ namespace Sass {
|
|
1023
1023
|
|
1024
1024
|
}
|
1025
1025
|
|
1026
|
-
} else if (((op1.combinator() ==
|
1026
|
+
} else if (((op1.combinator() == Sequence_Selector::PRECEDES && op2.combinator() == Sequence_Selector::ADJACENT_TO)) || ((op1.combinator() == Sequence_Selector::ADJACENT_TO && op2.combinator() == Sequence_Selector::PRECEDES))) {
|
1027
1027
|
|
1028
1028
|
Node tildeSel = sel1;
|
1029
1029
|
Node tildeOp = op1;
|
1030
1030
|
Node plusSel = sel2;
|
1031
1031
|
Node plusOp = op2;
|
1032
|
-
if (op1.combinator() !=
|
1032
|
+
if (op1.combinator() != Sequence_Selector::PRECEDES) {
|
1033
1033
|
tildeSel = sel2;
|
1034
1034
|
tildeOp = op2;
|
1035
1035
|
plusSel = sel1;
|
@@ -1046,9 +1046,9 @@ namespace Sass {
|
|
1046
1046
|
DEBUG_PRINTLN(ALL, "PLUS SEL: " << plusSel)
|
1047
1047
|
DEBUG_PRINTLN(ALL, "TILDE SEL: " << tildeSel)
|
1048
1048
|
|
1049
|
-
|
1049
|
+
Sequence_Selector* pMergedWrapper = plusSel.selector()->clone(ctx); // Clone the Sequence_Selector to get back to something we can transform to a node once we replace the head with the unification result
|
1050
1050
|
// TODO: does subject matter? Ruby: merged = plus_sel.unify(tilde_sel.members, tilde_sel.subject?)
|
1051
|
-
|
1051
|
+
SimpleSequence_Selector* pMerged = plusSel.selector()->head()->unify_with(tildeSel.selector()->head(), ctx);
|
1052
1052
|
pMergedWrapper->head(pMerged);
|
1053
1053
|
|
1054
1054
|
DEBUG_EXEC(ALL, printCompoundSelector(pMerged, "MERGED: "))
|
@@ -1057,15 +1057,15 @@ namespace Sass {
|
|
1057
1057
|
|
1058
1058
|
Node firstPerm = Node::createCollection();
|
1059
1059
|
firstPerm.collection()->push_back(tildeSel);
|
1060
|
-
firstPerm.collection()->push_back(Node::createCombinator(
|
1060
|
+
firstPerm.collection()->push_back(Node::createCombinator(Sequence_Selector::PRECEDES));
|
1061
1061
|
firstPerm.collection()->push_back(plusSel);
|
1062
|
-
firstPerm.collection()->push_back(Node::createCombinator(
|
1062
|
+
firstPerm.collection()->push_back(Node::createCombinator(Sequence_Selector::ADJACENT_TO));
|
1063
1063
|
newRes.collection()->push_back(firstPerm);
|
1064
1064
|
|
1065
1065
|
if (pMerged) {
|
1066
1066
|
Node mergedPerm = Node::createCollection();
|
1067
1067
|
mergedPerm.collection()->push_back(Node::createSelector(pMergedWrapper, ctx));
|
1068
|
-
mergedPerm.collection()->push_back(Node::createCombinator(
|
1068
|
+
mergedPerm.collection()->push_back(Node::createCombinator(Sequence_Selector::ADJACENT_TO));
|
1069
1069
|
newRes.collection()->push_back(mergedPerm);
|
1070
1070
|
}
|
1071
1071
|
|
@@ -1074,7 +1074,7 @@ namespace Sass {
|
|
1074
1074
|
DEBUG_PRINTLN(ALL, "RESULT: " << res)
|
1075
1075
|
|
1076
1076
|
}
|
1077
|
-
} else if (op1.combinator() ==
|
1077
|
+
} else if (op1.combinator() == Sequence_Selector::PARENT_OF && (op2.combinator() == Sequence_Selector::PRECEDES || op2.combinator() == Sequence_Selector::ADJACENT_TO)) {
|
1078
1078
|
|
1079
1079
|
res.collection()->push_front(op2);
|
1080
1080
|
res.collection()->push_front(sel2);
|
@@ -1082,7 +1082,7 @@ namespace Sass {
|
|
1082
1082
|
seq1.collection()->push_back(sel1);
|
1083
1083
|
seq1.collection()->push_back(op1);
|
1084
1084
|
|
1085
|
-
} else if (op2.combinator() ==
|
1085
|
+
} else if (op2.combinator() == Sequence_Selector::PARENT_OF && (op1.combinator() == Sequence_Selector::PRECEDES || op1.combinator() == Sequence_Selector::ADJACENT_TO)) {
|
1086
1086
|
|
1087
1087
|
res.collection()->push_front(op1);
|
1088
1088
|
res.collection()->push_front(sel1);
|
@@ -1095,9 +1095,9 @@ namespace Sass {
|
|
1095
1095
|
DEBUG_PRINTLN(ALL, "sel1: " << sel1)
|
1096
1096
|
DEBUG_PRINTLN(ALL, "sel2: " << sel2)
|
1097
1097
|
|
1098
|
-
|
1098
|
+
Sequence_Selector* pMergedWrapper = sel1.selector()->clone(ctx); // Clone the Sequence_Selector to get back to something we can transform to a node once we replace the head with the unification result
|
1099
1099
|
// TODO: does subject matter? Ruby: return unless merged = sel1.unify(sel2.members, sel2.subject?)
|
1100
|
-
|
1100
|
+
SimpleSequence_Selector* pMerged = sel1.selector()->head()->unify_with(sel2.selector()->head(), ctx);
|
1101
1101
|
pMergedWrapper->head(pMerged);
|
1102
1102
|
|
1103
1103
|
DEBUG_EXEC(ALL, printCompoundSelector(pMerged, "MERGED: "))
|
@@ -1121,7 +1121,7 @@ namespace Sass {
|
|
1121
1121
|
|
1122
1122
|
Node op1 = ops1.collection()->front();
|
1123
1123
|
|
1124
|
-
if (op1.combinator() ==
|
1124
|
+
if (op1.combinator() == Sequence_Selector::PARENT_OF && !seq2.collection()->empty() && seq2.collection()->back().selector()->is_superselector_of(seq1.collection()->back().selector())) {
|
1125
1125
|
seq2.collection()->pop_back();
|
1126
1126
|
}
|
1127
1127
|
|
@@ -1136,7 +1136,7 @@ namespace Sass {
|
|
1136
1136
|
|
1137
1137
|
Node op2 = ops2.collection()->front();
|
1138
1138
|
|
1139
|
-
if (op2.combinator() ==
|
1139
|
+
if (op2.combinator() == Sequence_Selector::PARENT_OF && !seq1.collection()->empty() && seq1.collection()->back().selector()->is_superselector_of(seq2.collection()->back().selector())) {
|
1140
1140
|
seq1.collection()->pop_back();
|
1141
1141
|
}
|
1142
1142
|
|
@@ -1509,10 +1509,10 @@ namespace Sass {
|
|
1509
1509
|
// This forward declaration is needed since extendComplexSelector calls extendCompoundSelector, which may recursively
|
1510
1510
|
// call extendComplexSelector again.
|
1511
1511
|
static Node extendComplexSelector(
|
1512
|
-
|
1512
|
+
Sequence_Selector* pComplexSelector,
|
1513
1513
|
Context& ctx,
|
1514
1514
|
ExtensionSubsetMap& subset_map,
|
1515
|
-
std::set<
|
1515
|
+
std::set<SimpleSequence_Selector> seen, bool isReplace, bool isOriginal);
|
1516
1516
|
|
1517
1517
|
|
1518
1518
|
|
@@ -1532,15 +1532,15 @@ namespace Sass {
|
|
1532
1532
|
class GroupByToAFunctor {
|
1533
1533
|
public:
|
1534
1534
|
KeyType operator()(ExtensionPair& extPair) const {
|
1535
|
-
|
1535
|
+
Sequence_Selector* pSelector = extPair.first;
|
1536
1536
|
return *pSelector;
|
1537
1537
|
}
|
1538
1538
|
};
|
1539
1539
|
static Node extendCompoundSelector(
|
1540
|
-
|
1540
|
+
SimpleSequence_Selector* pSelector,
|
1541
1541
|
Context& ctx,
|
1542
1542
|
ExtensionSubsetMap& subset_map,
|
1543
|
-
std::set<
|
1543
|
+
std::set<SimpleSequence_Selector> seen, bool isReplace) {
|
1544
1544
|
|
1545
1545
|
DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelector, "EXTEND COMPOUND: "))
|
1546
1546
|
// TODO: Ruby has another loop here to skip certain members?
|
@@ -1550,13 +1550,13 @@ namespace Sass {
|
|
1550
1550
|
|
1551
1551
|
SubsetMapEntries entries = subset_map.get_v(pSelector->to_str_vec());
|
1552
1552
|
|
1553
|
-
typedef std::vector<std::pair<
|
1553
|
+
typedef std::vector<std::pair<Sequence_Selector, std::vector<ExtensionPair> > > GroupedByToAResult;
|
1554
1554
|
|
1555
|
-
GroupByToAFunctor<
|
1555
|
+
GroupByToAFunctor<Sequence_Selector> extPairKeyFunctor;
|
1556
1556
|
GroupedByToAResult arr;
|
1557
1557
|
group_by_to_a(entries, extPairKeyFunctor, arr);
|
1558
1558
|
|
1559
|
-
typedef std::pair<
|
1559
|
+
typedef std::pair<SimpleSequence_Selector*, Sequence_Selector*> SelsNewSeqPair;
|
1560
1560
|
typedef std::vector<SelsNewSeqPair> SelsNewSeqPairCollection;
|
1561
1561
|
|
1562
1562
|
|
@@ -1564,18 +1564,18 @@ namespace Sass {
|
|
1564
1564
|
|
1565
1565
|
|
1566
1566
|
for (GroupedByToAResult::iterator groupedIter = arr.begin(), groupedIterEnd = arr.end(); groupedIter != groupedIterEnd; groupedIter++) {
|
1567
|
-
std::pair<
|
1567
|
+
std::pair<Sequence_Selector, std::vector<ExtensionPair> >& groupedPair = *groupedIter;
|
1568
1568
|
|
1569
|
-
|
1569
|
+
Sequence_Selector& seq = groupedPair.first;
|
1570
1570
|
std::vector<ExtensionPair>& group = groupedPair.second;
|
1571
1571
|
|
1572
1572
|
DEBUG_EXEC(EXTEND_COMPOUND, printComplexSelector(&seq, "SEQ: "))
|
1573
1573
|
|
1574
1574
|
|
1575
|
-
|
1575
|
+
SimpleSequence_Selector* pSels = SASS_MEMORY_NEW(ctx.mem, SimpleSequence_Selector, pSelector->pstate());
|
1576
1576
|
for (std::vector<ExtensionPair>::iterator groupIter = group.begin(), groupIterEnd = group.end(); groupIter != groupIterEnd; groupIter++) {
|
1577
1577
|
ExtensionPair& pair = *groupIter;
|
1578
|
-
|
1578
|
+
SimpleSequence_Selector* pCompound = pair.second;
|
1579
1579
|
for (size_t index = 0; index < pCompound->length(); index++) {
|
1580
1580
|
Simple_Selector* pSimpleSelector = (*pCompound)[index];
|
1581
1581
|
(*pSels) << pSimpleSelector;
|
@@ -1585,21 +1585,21 @@ namespace Sass {
|
|
1585
1585
|
|
1586
1586
|
DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSels, "SELS: "))
|
1587
1587
|
|
1588
|
-
|
1589
|
-
|
1588
|
+
Sequence_Selector* pExtComplexSelector = &seq; // The selector up to where the @extend is (ie, the thing to merge)
|
1589
|
+
SimpleSequence_Selector* pExtCompoundSelector = pSels; // All the simple selectors to be replaced from the current compound selector from all extensions
|
1590
1590
|
|
1591
|
-
// TODO: This can return a
|
1591
|
+
// TODO: This can return a SimpleSequence_Selector with no elements. Should that just be returning NULL?
|
1592
1592
|
// RUBY: self_without_sel = Sass::Util.array_minus(members, sels)
|
1593
|
-
|
1593
|
+
SimpleSequence_Selector* pSelectorWithoutExtendSelectors = pSelector->minus(pExtCompoundSelector, ctx);
|
1594
1594
|
|
1595
1595
|
DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelector, "MEMBERS: "))
|
1596
1596
|
DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelectorWithoutExtendSelectors, "SELF_WO_SEL: "))
|
1597
1597
|
|
1598
|
-
|
1599
|
-
|
1598
|
+
SimpleSequence_Selector* pInnermostCompoundSelector = pExtComplexSelector->last()->head();
|
1599
|
+
SimpleSequence_Selector* pUnifiedSelector = NULL;
|
1600
1600
|
|
1601
1601
|
if (!pInnermostCompoundSelector) {
|
1602
|
-
pInnermostCompoundSelector = SASS_MEMORY_NEW(ctx.mem,
|
1602
|
+
pInnermostCompoundSelector = SASS_MEMORY_NEW(ctx.mem, SimpleSequence_Selector, pSelector->pstate());
|
1603
1603
|
}
|
1604
1604
|
|
1605
1605
|
pUnifiedSelector = pInnermostCompoundSelector->unify_with(pSelectorWithoutExtendSelectors, ctx);
|
@@ -1618,14 +1618,14 @@ namespace Sass {
|
|
1618
1618
|
// next if group.map {|e, _| check_directives_match!(e, parent_directives)}.none?
|
1619
1619
|
|
1620
1620
|
// TODO: This seems a little fishy to me. See if it causes any problems. From the ruby, we should be able to just
|
1621
|
-
// get rid of the last
|
1622
|
-
// complex is that
|
1621
|
+
// get rid of the last SimpleSequence_Selector and replace it with this one. I think the reason this code is more
|
1622
|
+
// complex is that Sequence_Selector contains a combinator, but in ruby combinators have already been filtered
|
1623
1623
|
// out and aren't operated on.
|
1624
|
-
|
1624
|
+
Sequence_Selector* pNewSelector = pExtComplexSelector->cloneFully(ctx); // ->first();
|
1625
1625
|
|
1626
|
-
|
1626
|
+
Sequence_Selector* pNewInnerMost = SASS_MEMORY_NEW(ctx.mem, Sequence_Selector, pSelector->pstate(), Sequence_Selector::ANCESTOR_OF, pUnifiedSelector, NULL);
|
1627
1627
|
|
1628
|
-
|
1628
|
+
Sequence_Selector::Combinator combinator = pNewSelector->clear_innermost();
|
1629
1629
|
pNewSelector->set_innermost(pNewInnerMost, combinator);
|
1630
1630
|
|
1631
1631
|
#ifdef DEBUG
|
@@ -1642,7 +1642,7 @@ namespace Sass {
|
|
1642
1642
|
|
1643
1643
|
|
1644
1644
|
// if (pSelector && pSelector->has_line_feed()) pNewInnerMost->has_line_feed(true);
|
1645
|
-
// Set the sources on our new
|
1645
|
+
// Set the sources on our new Sequence_Selector to the sources of this simple sequence plus the thing we're extending.
|
1646
1646
|
DEBUG_PRINTLN(EXTEND_COMPOUND, "SOURCES SETTING ON NEW SEQ: " << complexSelectorToNode(pNewSelector, ctx))
|
1647
1647
|
|
1648
1648
|
DEBUG_EXEC(EXTEND_COMPOUND, SourcesSet oldSet = pNewSelector->sources(); printSourcesSet(oldSet, ctx, "SOURCES NEW SEQ BEGIN: "))
|
@@ -1669,8 +1669,8 @@ namespace Sass {
|
|
1669
1669
|
for (SelsNewSeqPairCollection::iterator holderIter = holder.begin(), holderIterEnd = holder.end(); holderIter != holderIterEnd; holderIter++) {
|
1670
1670
|
SelsNewSeqPair& pair = *holderIter;
|
1671
1671
|
|
1672
|
-
|
1673
|
-
|
1672
|
+
SimpleSequence_Selector* pSels = pair.first;
|
1673
|
+
Sequence_Selector* pNewSelector = pair.second;
|
1674
1674
|
|
1675
1675
|
|
1676
1676
|
// RUBY??: next [] if seen.include?(sels)
|
@@ -1679,7 +1679,7 @@ namespace Sass {
|
|
1679
1679
|
}
|
1680
1680
|
|
1681
1681
|
|
1682
|
-
std::set<
|
1682
|
+
std::set<SimpleSequence_Selector> recurseSeen(seen);
|
1683
1683
|
recurseSeen.insert(*pSels);
|
1684
1684
|
|
1685
1685
|
|
@@ -1709,33 +1709,19 @@ namespace Sass {
|
|
1709
1709
|
|
1710
1710
|
|
1711
1711
|
static bool complexSelectorHasExtension(
|
1712
|
-
|
1712
|
+
Sequence_Selector* pComplexSelector,
|
1713
1713
|
Context& ctx,
|
1714
|
-
ExtensionSubsetMap& subset_map
|
1714
|
+
ExtensionSubsetMap& subset_map,
|
1715
|
+
std::set<SimpleSequence_Selector>& seen) {
|
1715
1716
|
|
1716
1717
|
bool hasExtension = false;
|
1717
1718
|
|
1718
|
-
|
1719
|
+
Sequence_Selector* pIter = pComplexSelector;
|
1719
1720
|
|
1720
1721
|
while (!hasExtension && pIter) {
|
1721
|
-
|
1722
|
+
SimpleSequence_Selector* pHead = pIter->head();
|
1722
1723
|
|
1723
1724
|
if (pHead) {
|
1724
|
-
for (Simple_Selector* pSimple : *pHead) {
|
1725
|
-
if (Wrapped_Selector* ws = dynamic_cast<Wrapped_Selector*>(pSimple)) {
|
1726
|
-
if (Selector_List* sl = dynamic_cast<Selector_List*>(ws->selector())) {
|
1727
|
-
for (Complex_Selector* cs : sl->elements()) {
|
1728
|
-
while (cs) {
|
1729
|
-
if (complexSelectorHasExtension(cs, ctx, subset_map)) {
|
1730
|
-
hasExtension = true;
|
1731
|
-
break;
|
1732
|
-
}
|
1733
|
-
cs = cs->tail();
|
1734
|
-
}
|
1735
|
-
}
|
1736
|
-
}
|
1737
|
-
}
|
1738
|
-
}
|
1739
1725
|
SubsetMapEntries entries = subset_map.get_v(pHead->to_str_vec());
|
1740
1726
|
for (ExtensionPair ext : entries) {
|
1741
1727
|
// check if both selectors have the same media block parent
|
@@ -1783,10 +1769,10 @@ namespace Sass {
|
|
1783
1769
|
next [[sseq_or_op]] unless sseq_or_op.is_a?(SimpleSequence)
|
1784
1770
|
*/
|
1785
1771
|
static Node extendComplexSelector(
|
1786
|
-
|
1772
|
+
Sequence_Selector* pComplexSelector,
|
1787
1773
|
Context& ctx,
|
1788
1774
|
ExtensionSubsetMap& subset_map,
|
1789
|
-
std::set<
|
1775
|
+
std::set<SimpleSequence_Selector> seen, bool isReplace, bool isOriginal) {
|
1790
1776
|
|
1791
1777
|
Node complexSelector = complexSelectorToNode(pComplexSelector, ctx);
|
1792
1778
|
DEBUG_PRINTLN(EXTEND_COMPLEX, "EXTEND COMPLEX: " << complexSelector)
|
@@ -1806,7 +1792,7 @@ namespace Sass {
|
|
1806
1792
|
// RUBY: next [[sseq_or_op]] unless sseq_or_op.is_a?(SimpleSequence)
|
1807
1793
|
if (!sseqOrOp.isSelector()) {
|
1808
1794
|
// Wrap our Combinator in two collections to match ruby. This is essentially making a collection Node
|
1809
|
-
// with one collection child. The collection child represents a
|
1795
|
+
// with one collection child. The collection child represents a Sequence_Selector that is only a combinator.
|
1810
1796
|
Node outer = Node::createCollection();
|
1811
1797
|
Node inner = Node::createCollection();
|
1812
1798
|
outer.collection()->push_back(inner);
|
@@ -1815,7 +1801,7 @@ namespace Sass {
|
|
1815
1801
|
continue;
|
1816
1802
|
}
|
1817
1803
|
|
1818
|
-
|
1804
|
+
SimpleSequence_Selector* pCompoundSelector = sseqOrOp.selector()->head();
|
1819
1805
|
|
1820
1806
|
// RUBY: extended = sseq_or_op.do_extend(extends, parent_directives, replace, seen)
|
1821
1807
|
Node extended = extendCompoundSelector(pCompoundSelector, ctx, subset_map, seen, isReplace);
|
@@ -1823,9 +1809,9 @@ namespace Sass {
|
|
1823
1809
|
DEBUG_PRINTLN(EXTEND_COMPLEX, "EXTENDED: " << extended)
|
1824
1810
|
|
1825
1811
|
|
1826
|
-
// Prepend the
|
1812
|
+
// Prepend the SimpleSequence_Selector based on the choices logic; choices seems to be extend but with an ruby Array instead of a Sequence
|
1827
1813
|
// due to the member mapping: choices = extended.map {|seq| seq.members}
|
1828
|
-
|
1814
|
+
Sequence_Selector* pJustCurrentCompoundSelector = sseqOrOp.selector();
|
1829
1815
|
|
1830
1816
|
// RUBY: extended.first.add_sources!([self]) if original && !has_placeholder?
|
1831
1817
|
if (isOriginal && !pComplexSelector->has_placeholder()) {
|
@@ -1839,7 +1825,7 @@ namespace Sass {
|
|
1839
1825
|
for (NodeDeque::iterator iterator = extended.collection()->begin(), endIterator = extended.collection()->end();
|
1840
1826
|
iterator != endIterator; ++iterator) {
|
1841
1827
|
Node& childNode = *iterator;
|
1842
|
-
|
1828
|
+
Sequence_Selector* pExtensionSelector = nodeToComplexSelector(childNode, ctx);
|
1843
1829
|
if (pExtensionSelector->is_superselector_of(pJustCurrentCompoundSelector)) {
|
1844
1830
|
isSuperselector = true;
|
1845
1831
|
break;
|
@@ -1906,33 +1892,40 @@ namespace Sass {
|
|
1906
1892
|
/*
|
1907
1893
|
This is the equivalent of ruby's CommaSequence.do_extend.
|
1908
1894
|
*/
|
1909
|
-
|
1895
|
+
CommaSequence_Selector* Extend::extendSelectorList(CommaSequence_Selector* pSelectorList, Context& ctx, ExtensionSubsetMap& subset_map, bool isReplace, bool& extendedSomething) {
|
1896
|
+
std::set<SimpleSequence_Selector> seen;
|
1897
|
+
return extendSelectorList(pSelectorList, ctx, subset_map, isReplace, extendedSomething, seen);
|
1898
|
+
}
|
1899
|
+
|
1900
|
+
/*
|
1901
|
+
This is the equivalent of ruby's CommaSequence.do_extend.
|
1902
|
+
*/
|
1903
|
+
CommaSequence_Selector* Extend::extendSelectorList(CommaSequence_Selector* pSelectorList, Context& ctx, ExtensionSubsetMap& subset_map, bool isReplace, bool& extendedSomething, std::set<SimpleSequence_Selector>& seen) {
|
1910
1904
|
|
1911
|
-
|
1905
|
+
CommaSequence_Selector* pNewSelectors = SASS_MEMORY_NEW(ctx.mem, CommaSequence_Selector, pSelectorList->pstate(), pSelectorList->length());
|
1912
1906
|
|
1913
1907
|
extendedSomething = false;
|
1914
1908
|
|
1915
1909
|
for (size_t index = 0, length = pSelectorList->length(); index < length; index++) {
|
1916
|
-
|
1910
|
+
Sequence_Selector* pSelector = (*pSelectorList)[index];
|
1917
1911
|
|
1918
1912
|
// ruby sass seems to keep a list of things that have extensions and then only extend those. We don't currently do that.
|
1919
1913
|
// Since it's not that expensive to check if an extension exists in the subset map and since it can be relatively expensive to
|
1920
1914
|
// run through the extend code (which does a data model transformation), check if there is anything to extend before doing
|
1921
1915
|
// the extend. We might be able to optimize extendComplexSelector, but this approach keeps us closer to ruby sass (which helps
|
1922
1916
|
// when debugging).
|
1923
|
-
if (!complexSelectorHasExtension(pSelector, ctx, subset_map)) {
|
1917
|
+
if (!complexSelectorHasExtension(pSelector, ctx, subset_map, seen)) {
|
1924
1918
|
*pNewSelectors << pSelector;
|
1925
1919
|
continue;
|
1926
1920
|
}
|
1927
1921
|
|
1928
1922
|
extendedSomething = true;
|
1929
1923
|
|
1930
|
-
std::set<Compound_Selector> seen;
|
1931
|
-
|
1932
1924
|
Node extendedSelectors = extendComplexSelector(pSelector, ctx, subset_map, seen, isReplace, true);
|
1933
1925
|
if (!pSelector->has_placeholder()) {
|
1934
1926
|
if (!extendedSelectors.contains(complexSelectorToNode(pSelector, ctx), true /*simpleSelectorOrderDependent*/)) {
|
1935
1927
|
*pNewSelectors << pSelector;
|
1928
|
+
continue;
|
1936
1929
|
}
|
1937
1930
|
}
|
1938
1931
|
|
@@ -1951,32 +1944,46 @@ namespace Sass {
|
|
1951
1944
|
pNewSelectors = remove_placeholders.remove_placeholders(pNewSelectors);
|
1952
1945
|
|
1953
1946
|
// unwrap all wrapped selectors with inner lists
|
1954
|
-
for (
|
1947
|
+
for (Sequence_Selector* cur : *pNewSelectors) {
|
1955
1948
|
// process tails
|
1956
1949
|
while (cur) {
|
1957
1950
|
// process header
|
1958
|
-
if (cur->head()) {
|
1951
|
+
if (cur->head() && seen.find(*cur->head()) == seen.end()) {
|
1952
|
+
std::set<SimpleSequence_Selector> recseen(seen);
|
1953
|
+
recseen.insert(*cur->head());
|
1959
1954
|
// create a copy since we add multiple items if stuff get unwrapped
|
1960
|
-
|
1955
|
+
SimpleSequence_Selector* cpy_head = SASS_MEMORY_NEW(ctx.mem, SimpleSequence_Selector, cur->pstate());
|
1961
1956
|
for (Simple_Selector* hs : *cur->head()) {
|
1962
1957
|
if (Wrapped_Selector* ws = dynamic_cast<Wrapped_Selector*>(hs)) {
|
1963
|
-
if (
|
1958
|
+
if (CommaSequence_Selector* sl = dynamic_cast<CommaSequence_Selector*>(ws->selector())) {
|
1964
1959
|
// special case for ruby ass
|
1965
1960
|
if (sl->empty()) {
|
1966
1961
|
// this seems inconsistent but it is how ruby sass seems to remove parentheses
|
1967
|
-
*cpy_head << SASS_MEMORY_NEW(ctx.mem,
|
1962
|
+
*cpy_head << SASS_MEMORY_NEW(ctx.mem, Element_Selector, hs->pstate(), ws->name());
|
1968
1963
|
}
|
1969
1964
|
// has wrapped selectors
|
1970
1965
|
else {
|
1971
1966
|
// extend the inner list of wrapped selector
|
1972
|
-
|
1967
|
+
CommaSequence_Selector* ext_sl = extendSelectorList(sl, ctx, subset_map, recseen);
|
1973
1968
|
for (size_t i = 0; i < ext_sl->length(); i += 1) {
|
1974
|
-
if (
|
1969
|
+
if (Sequence_Selector* ext_cs = ext_sl->at(i)) {
|
1975
1970
|
// create clones for wrapped selector and the inner list
|
1976
1971
|
Wrapped_Selector* cpy_ws = SASS_MEMORY_NEW(ctx.mem, Wrapped_Selector, *ws);
|
1977
|
-
|
1972
|
+
CommaSequence_Selector* cpy_ws_sl = SASS_MEMORY_NEW(ctx.mem, CommaSequence_Selector, sl->pstate());
|
1978
1973
|
// remove parent selectors from inner selector
|
1979
|
-
if (ext_cs->first()
|
1974
|
+
if (ext_cs->first() && ext_cs->first()->head()->length() > 0) {
|
1975
|
+
Wrapped_Selector* ext_ws = dynamic_cast<Wrapped_Selector*>(ext_cs->first()->head()->first());
|
1976
|
+
if (ext_ws/* && ext_cs->length() == 1*/) {
|
1977
|
+
CommaSequence_Selector* ws_cs = dynamic_cast<CommaSequence_Selector*>(ext_ws->selector());
|
1978
|
+
SimpleSequence_Selector* ws_ss = ws_cs->first()->head();
|
1979
|
+
if (!(
|
1980
|
+
dynamic_cast<Pseudo_Selector*>(ws_ss->first()) ||
|
1981
|
+
dynamic_cast<Element_Selector*>(ws_ss->first()) ||
|
1982
|
+
dynamic_cast<Placeholder_Selector*>(ws_ss->first())
|
1983
|
+
)) continue;
|
1984
|
+
}
|
1985
|
+
*cpy_ws_sl << ext_cs->first();
|
1986
|
+
}
|
1980
1987
|
// assign list to clone
|
1981
1988
|
cpy_ws->selector(cpy_ws_sl);
|
1982
1989
|
// append the clone
|
@@ -2038,7 +2045,7 @@ namespace Sass {
|
|
2038
2045
|
template <typename ObjectType>
|
2039
2046
|
static void extendObjectWithSelectorAndBlock(ObjectType* pObject, Context& ctx, ExtensionSubsetMap& subset_map) {
|
2040
2047
|
|
2041
|
-
DEBUG_PRINTLN(EXTEND_OBJECT, "FOUND SELECTOR: " << static_cast<
|
2048
|
+
DEBUG_PRINTLN(EXTEND_OBJECT, "FOUND SELECTOR: " << static_cast<CommaSequence_Selector*>(pObject->selector())->to_string(ctx.c_options))
|
2042
2049
|
|
2043
2050
|
// Ruby sass seems to filter nodes that don't have any content well before we get here. I'm not sure the repercussions
|
2044
2051
|
// of doing so, so for now, let's just not extend things that won't be output later.
|
@@ -2048,10 +2055,10 @@ namespace Sass {
|
|
2048
2055
|
}
|
2049
2056
|
|
2050
2057
|
bool extendedSomething = false;
|
2051
|
-
|
2058
|
+
CommaSequence_Selector* pNewSelectorList = Extend::extendSelectorList(static_cast<CommaSequence_Selector*>(pObject->selector()), ctx, subset_map, false, extendedSomething);
|
2052
2059
|
|
2053
2060
|
if (extendedSomething && pNewSelectorList) {
|
2054
|
-
DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND ORIGINAL SELECTORS: " << static_cast<
|
2061
|
+
DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND ORIGINAL SELECTORS: " << static_cast<CommaSequence_Selector*>(pObject->selector())->to_string(ctx.c_options))
|
2055
2062
|
DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND SETTING NEW SELECTORS: " << pNewSelectorList->to_string(ctx.c_options))
|
2056
2063
|
pNewSelectorList->remove_parent_selectors();
|
2057
2064
|
pObject->selector(pNewSelectorList);
|
@@ -2076,8 +2083,8 @@ namespace Sass {
|
|
2076
2083
|
if (b->is_root()) {
|
2077
2084
|
// debug_subset_map(subset_map);
|
2078
2085
|
for(auto const &it : subset_map.values()) {
|
2079
|
-
|
2080
|
-
|
2086
|
+
Sequence_Selector* sel = it.first ? it.first->first() : NULL;
|
2087
|
+
SimpleSequence_Selector* ext = it.second ? it.second : NULL;
|
2081
2088
|
if (ext && (ext->extended() || ext->is_optional())) continue;
|
2082
2089
|
std::string str_sel(sel->to_string({ NESTED, 5 }));
|
2083
2090
|
std::string str_ext(ext->to_string({ NESTED, 5 }));
|
@@ -2110,7 +2117,7 @@ namespace Sass {
|
|
2110
2117
|
|
2111
2118
|
void Extend::operator()(Directive* a)
|
2112
2119
|
{
|
2113
|
-
//
|
2120
|
+
// CommaSequence_Selector* ls = dynamic_cast<CommaSequence_Selector*>(a->selector());
|
2114
2121
|
// selector_stack.push_back(ls);
|
2115
2122
|
if (a->block()) a->block()->perform(this);
|
2116
2123
|
// exp.selector_stack.pop_back();
|