@@ -26,29 +26,29 @@ namespace Sass {
26
26
}
27
27
28
28
bool Complex_Selector::operator ==(const Complex_Selector& rhs) const {
29
- // TODO: We have to access the tail directly using tail_ since ADD_PROPERTY doesn't provide a const version.
29
+ // TODO: We have to access the tail directly using tail_ since ADD_PROPERTY doesn't provide a const version.
30
30
31
- const Complex_Selector* pOne = this ;
31
+ const Complex_Selector* pOne = this ;
32
32
const Complex_Selector* pTwo = &rhs;
33
33
34
34
// Consume any empty references at the beginning of the Complex_Selector
35
35
if (pOne->combinator () == Complex_Selector::ANCESTOR_OF && pOne->head ()->is_empty_reference ()) {
36
- pOne = pOne->tail_ ;
36
+ pOne = pOne->tail_ ;
37
37
}
38
38
if (pTwo->combinator () == Complex_Selector::ANCESTOR_OF && pTwo->head ()->is_empty_reference ()) {
39
- pTwo = pTwo->tail_ ;
39
+ pTwo = pTwo->tail_ ;
40
40
}
41
41
42
42
while (pOne && pTwo) {
43
- if (pOne->combinator () != pTwo->combinator ()) {
44
- return false ;
43
+ if (pOne->combinator () != pTwo->combinator ()) {
44
+ return false ;
45
45
}
46
46
47
47
if (*(pOne->head ()) != *(pTwo->head ())) {
48
- return false ;
48
+ return false ;
49
49
}
50
50
51
- pOne = pOne->tail_ ;
51
+ pOne = pOne->tail_ ;
52
52
pTwo = pTwo->tail_ ;
53
53
}
54
54
@@ -68,21 +68,21 @@ namespace Sass {
68
68
69
69
bool Simple_Selector::operator ==(const Simple_Selector& rhs) const
70
70
{
71
- // Compare the string representations for equality.
71
+ // Compare the string representations for equality.
72
72
73
- // Cast away const here. To_String should take a const object, but it doesn't.
74
- Simple_Selector* pLHS = const_cast <Simple_Selector*>(this );
73
+ // Cast away const here. To_String should take a const object, but it doesn't.
74
+ Simple_Selector* pLHS = const_cast <Simple_Selector*>(this );
75
75
Simple_Selector* pRHS = const_cast <Simple_Selector*>(&rhs);
76
76
77
77
To_String to_string;
78
78
return pLHS->perform (&to_string) == pRHS->perform (&to_string);
79
79
}
80
80
81
81
bool Simple_Selector::operator <(const Simple_Selector& rhs) const {
82
- // Use the string representation for ordering.
82
+ // Use the string representation for ordering.
83
83
84
- // Cast away const here. To_String should take a const object, but it doesn't.
85
- Simple_Selector* pLHS = const_cast <Simple_Selector*>(this );
84
+ // Cast away const here. To_String should take a const object, but it doesn't.
85
+ Simple_Selector* pLHS = const_cast <Simple_Selector*>(this );
86
86
Simple_Selector* pRHS = const_cast <Simple_Selector*>(&rhs);
87
87
88
88
To_String to_string;
@@ -217,32 +217,46 @@ namespace Sass {
217
217
set<string> lpsuedoset, rpsuedoset;
218
218
for (size_t i = 0 , L = length (); i < L; ++i)
219
219
{
220
- if ((*this )[i]->is_pseudo_element ()) {
221
- string pseudo ((*this )[i]->perform (&to_string));
220
+ if ((*this )[i]->is_pseudo_element ()) {
221
+ string pseudo ((*this )[i]->perform (&to_string));
222
222
pseudo = pseudo.substr (pseudo.find_first_not_of (" :" )); // strip off colons to ensure :after matches ::after since ruby sass is forgiving
223
- lpsuedoset.insert (pseudo);
223
+ lpsuedoset.insert (pseudo);
224
224
}
225
225
}
226
226
for (size_t i = 0 , L = rhs->length (); i < L; ++i)
227
227
{
228
- if ((*rhs)[i]->is_pseudo_element ()) {
229
- string pseudo ((*rhs)[i]->perform (&to_string));
228
+ if ((*rhs)[i]->is_pseudo_element ()) {
229
+ string pseudo ((*rhs)[i]->perform (&to_string));
230
230
pseudo = pseudo.substr (pseudo.find_first_not_of (" :" )); // strip off colons to ensure :after matches ::after since ruby sass is forgiving
231
- rpsuedoset.insert (pseudo);
231
+ rpsuedoset.insert (pseudo);
232
232
}
233
233
}
234
- if (lpsuedoset != rpsuedoset) {
234
+ if (lpsuedoset != rpsuedoset) {
235
235
return false ;
236
236
}
237
237
238
- // Check the Simple_Selectors
238
+ // Check the Simple_Selectors
239
239
240
240
set<string> lset, rset;
241
241
242
242
if (!lbase) // no lbase; just see if the left-hand qualifiers are a subset of the right-hand selector
243
243
{
244
244
for (size_t i = 0 , L = length (); i < L; ++i)
245
- { lset.insert ((*this )[i]->perform (&to_string)); }
245
+ {
246
+ Selector* lhs = (*this )[i];
247
+ // very special case for wrapped matches selector
248
+ if (Wrapped_Selector* wrapped = dynamic_cast <Wrapped_Selector*>(lhs)) {
249
+ if (wrapped->name () == " :matches(" || wrapped->name () == " :-moz-any(" ) {
250
+ if (Selector_List* list = dynamic_cast <Selector_List*>(wrapped->selector ())) {
251
+ if (Compound_Selector* comp = dynamic_cast <Compound_Selector*>(rhs)) {
252
+ if (list->is_superselector_of (comp)) return true ;
253
+ }
254
+ }
255
+ }
256
+ }
257
+ // match from here on as strings
258
+ lset.insert (lhs->perform (&to_string));
259
+ }
246
260
for (size_t i = 0 , L = rhs->length (); i < L; ++i)
247
261
{ rset.insert ((*rhs)[i]->perform (&to_string)); }
248
262
return includes (rset.begin (), rset.end (), lset.begin (), lset.end ());
@@ -274,33 +288,33 @@ namespace Sass {
274
288
set<string> lpsuedoset, rpsuedoset;
275
289
for (size_t i = 0 , L = length (); i < L; ++i)
276
290
{
277
- if ((*this )[i]->is_pseudo_element ()) {
278
- string pseudo ((*this )[i]->perform (&to_string));
291
+ if ((*this )[i]->is_pseudo_element ()) {
292
+ string pseudo ((*this )[i]->perform (&to_string));
279
293
pseudo = pseudo.substr (pseudo.find_first_not_of (" :" )); // strip off colons to ensure :after matches ::after since ruby sass is forgiving
280
- lpsuedoset.insert (pseudo);
294
+ lpsuedoset.insert (pseudo);
281
295
}
282
296
}
283
297
for (size_t i = 0 , L = rhs.length (); i < L; ++i)
284
298
{
285
- if (rhs[i]->is_pseudo_element ()) {
286
- string pseudo (rhs[i]->perform (&to_string));
299
+ if (rhs[i]->is_pseudo_element ()) {
300
+ string pseudo (rhs[i]->perform (&to_string));
287
301
pseudo = pseudo.substr (pseudo.find_first_not_of (" :" )); // strip off colons to ensure :after matches ::after since ruby sass is forgiving
288
- rpsuedoset.insert (pseudo);
302
+ rpsuedoset.insert (pseudo);
289
303
}
290
304
}
291
- if (lpsuedoset != rpsuedoset) {
305
+ if (lpsuedoset != rpsuedoset) {
292
306
return false ;
293
307
}
294
308
295
- // Check the base
309
+ // Check the base
296
310
297
311
const Simple_Selector* const lbase = base ();
298
312
const Simple_Selector* const rbase = rhs.base ();
299
313
300
314
if ((lbase && !rbase) ||
301
- (!lbase && rbase) ||
315
+ (!lbase && rbase) ||
302
316
((lbase && rbase) && (*lbase != *rbase))) {
303
- return false ;
317
+ return false ;
304
318
}
305
319
306
320
@@ -326,8 +340,6 @@ namespace Sass {
326
340
327
341
bool Complex_Selector::is_superselector_of (Compound_Selector* rhs)
328
342
{
329
- if (length () != 1 )
330
- { return false ; }
331
343
return base ()->is_superselector_of (rhs);
332
344
}
333
345
@@ -352,6 +364,16 @@ namespace Sass {
352
364
if (l_len == 1 )
353
365
{ return lhs->head ()->is_superselector_of (rhs->base ()); }
354
366
367
+ // we have to look one tail deeper, since we cary the
368
+ // combinator around for it (which is important here)
369
+ if (rhs->tail () && lhs->tail () && combinator () != Complex_Selector::ANCESTOR_OF) {
370
+ Complex_Selector* lhs_tail = lhs->tail ();
371
+ Complex_Selector* rhs_tail = rhs->tail ();
372
+ if (lhs_tail->combinator () != rhs_tail->combinator ()) return false ;
373
+ if (!lhs_tail->head ()->is_superselector_of (rhs_tail->head ())) return false ;
374
+ }
375
+
376
+
355
377
bool found = false ;
356
378
Complex_Selector* marker = rhs;
357
379
for (size_t i = 0 , L = rhs->length (); i < L; ++i) {
@@ -458,7 +480,7 @@ namespace Sass {
458
480
Complex_Selector* cpy = new (ctx.mem ) Complex_Selector (*this );
459
481
460
482
if (head ()) {
461
- cpy->head (head ()->clone (ctx));
483
+ cpy->head (head ()->clone (ctx));
462
484
}
463
485
464
486
if (tail ()) {
@@ -493,6 +515,50 @@ namespace Sass {
493
515
#endif
494
516
}
495
517
518
+ // it's a superselector if every selector of the right side
519
+ // list is a superselector of the given left side selector
520
+ bool Complex_Selector::is_superselector_of (Selector_List *sub)
521
+ {
522
+ // Check every rhs selector against left hand list
523
+ for (size_t i = 0 , L = sub->length (); i < L; ++i) {
524
+ if (!is_superselector_of ((*sub)[i])) return false ;
525
+ }
526
+ return true ;
527
+ }
528
+
529
+ // it's a superselector if every selector of the right side
530
+ // list is a superselector of the given left side selector
531
+ bool Selector_List::is_superselector_of (Selector_List *sub)
532
+ {
533
+ // Check every rhs selector against left hand list
534
+ for (size_t i = 0 , L = sub->length (); i < L; ++i) {
535
+ if (!is_superselector_of ((*sub)[i])) return false ;
536
+ }
537
+ return true ;
538
+ }
539
+
540
+ // it's a superselector if every selector on the right side
541
+ // is a superselector of any one of the left side selectors
542
+ bool Selector_List::is_superselector_of (Compound_Selector *sub)
543
+ {
544
+ // Check every lhs selector against right hand
545
+ for (size_t i = 0 , L = length (); i < L; ++i) {
546
+ if ((*this )[i]->is_superselector_of (sub)) return true ;
547
+ }
548
+ return false ;
549
+ }
550
+
551
+ // it's a superselector if every selector on the right side
552
+ // is a superselector of any one of the left side selectors
553
+ bool Selector_List::is_superselector_of (Complex_Selector *sub)
554
+ {
555
+ // Check every lhs selector against right hand
556
+ for (size_t i = 0 , L = length (); i < L; ++i) {
557
+ if ((*this )[i]->is_superselector_of (sub)) return true ;
558
+ }
559
+ return false ;
560
+ }
561
+
496
562
/* not used anymore - remove?
497
563
Selector_Placeholder* Selector_List::find_placeholder()
498
564
{
0 commit comments