mirror of
https://github.com/danog/dart-sass.git
synced 2024-11-26 20:24:42 +01:00
Add _selectorPseudoIsSuperselector.
This commit is contained in:
parent
b5b4cd5a8b
commit
51c8213a6d
@ -2,6 +2,8 @@
|
||||
// MIT-style license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
import '../../extend/functions.dart';
|
||||
import '../../utils.dart';
|
||||
import '../selector.dart';
|
||||
|
||||
class ComplexSelector extends Selector {
|
||||
@ -27,6 +29,9 @@ class ComplexSelector extends Selector {
|
||||
: components = new List.unmodifiable(components),
|
||||
lineBreaks = new List.unmodifiable(lineBreaks);
|
||||
|
||||
bool isSuperselector(ComplexSelector other) =>
|
||||
complexIsSuperselector(components, other.components);
|
||||
|
||||
void _computeSpecificity() {
|
||||
_minSpecificity = 0;
|
||||
_maxSpecificity = 0;
|
||||
@ -38,6 +43,11 @@ class ComplexSelector extends Selector {
|
||||
}
|
||||
}
|
||||
|
||||
int get hashCode => listHash(components);
|
||||
|
||||
bool operator ==(other) =>
|
||||
other is ComplexSelector && listEquals(components, other.components);
|
||||
|
||||
String toString() => components.join(" ");
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
import '../../extend/functions.dart';
|
||||
import '../../utils.dart';
|
||||
import '../selector.dart';
|
||||
|
||||
class CompoundSelector extends Selector implements ComplexSelectorComponent {
|
||||
@ -35,5 +36,10 @@ class CompoundSelector extends Selector implements ComplexSelectorComponent {
|
||||
}
|
||||
}
|
||||
|
||||
int get hashCode => listHash(components);
|
||||
|
||||
bool operator ==(other) =>
|
||||
other is ComplexSelector && listEquals(components, other.components);
|
||||
|
||||
String toString() => components.join("");
|
||||
}
|
||||
|
@ -2,6 +2,8 @@
|
||||
// MIT-style license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
import '../../extend/functions.dart';
|
||||
import '../../utils.dart';
|
||||
import '../selector.dart';
|
||||
|
||||
class SelectorList extends Selector {
|
||||
@ -14,5 +16,13 @@ class SelectorList extends Selector {
|
||||
: components = new List.unmodifiable(components),
|
||||
lineBreaks = new List.unmodifiable(lineBreaks);
|
||||
|
||||
bool isSuperselector(SelectorList other) =>
|
||||
listIsSuperslector(components, other.components);
|
||||
|
||||
int get hashCode => listHash(components);
|
||||
|
||||
bool operator ==(other) =>
|
||||
other is ComplexSelector && listEquals(components, other.components);
|
||||
|
||||
String toString() => components.join(", ");
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import 'package:charcode/charcode.dart';
|
||||
|
||||
import '../selector.dart';
|
||||
|
||||
final _vendorPrefix = new Regex(r'^-[a-zA-Z0-9]+-');
|
||||
final _vendorPrefix = new RegExp(r'^-[a-zA-Z0-9]+-');
|
||||
|
||||
class PseudoSelector extends SimpleSelector {
|
||||
final String name;
|
||||
|
@ -61,6 +61,11 @@ SimpleSelector unifyUniversalAndElement(SimpleSelector selector1,
|
||||
new NamespacedIdentifier(name, namespace: namespace));
|
||||
}
|
||||
|
||||
bool listIsSuperslector(List<ComplexSelector> list1,
|
||||
List<ComplexSelector> list2) =>
|
||||
list2.every((complex1) =>
|
||||
list1.any((complex2) => complex2.isSuperselector(complex1)));
|
||||
|
||||
bool complexIsParentSuperselector(List<ComplexSelectorComponent> complex1,
|
||||
List<ComplexSelectorComponent> complex2) {
|
||||
// Try some simple heuristics to see if we can avoid allocations.
|
||||
@ -198,3 +203,70 @@ bool _simpleIsSuperselectorOfCompound(SimpleSelector simple,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool _selectorPseudoIsSuperselector(PseudoSelector pseudo1,
|
||||
CompoundSelector compound2, {Iterable<ComplexSelectorComponent> parents}) {
|
||||
switch (pseudo1.normalizedName) {
|
||||
case 'matches':
|
||||
case 'any':
|
||||
var pseudos = _selectorPseudosNamed(compound2, pseudo1.normalizedName);
|
||||
return pseudos.any((pseudo2) {
|
||||
return pseudo1.selector.isSuperselector(pseudo2.selector);
|
||||
}) || pseudo1.selector.components.any((complex1) {
|
||||
var complex2 = (parents?.toList() ?? [])..add(compound2);
|
||||
return complexIsSuperselector(complex1.components, complex2);
|
||||
});
|
||||
|
||||
case 'has':
|
||||
case 'host':
|
||||
case 'host-context':
|
||||
return _selectorPseudosNamed(compound2, pseudo1.normalizedName)
|
||||
.any((pseudo2) => pseudo1.selector.isSuperselector(pseudo2.selector));
|
||||
|
||||
case 'not':
|
||||
return pseudo1.selector.components.every((complex) {
|
||||
return compound2.components.every((simple2) {
|
||||
if (simple2 is TypeSelector) {
|
||||
var compound1 = complex.components.last;
|
||||
return compound1 is CompoundSelector &&
|
||||
compound1.components.any((simple1) =>
|
||||
simple1 is TypeSelector && simple1 != simple2);
|
||||
} else if (simple2 is IDSelector) {
|
||||
var compound1 = complex.components.last;
|
||||
return compound1 is CompoundSelector &&
|
||||
compound1.components.any((simple1) =>
|
||||
simple1 is IDSelector && simple1 != simple2);
|
||||
} else if (simple2 is PseudoSelector &&
|
||||
simple2.name == pseudo1.name &&
|
||||
simple2.selector != null) {
|
||||
return listIsSuperslector(simple2.selector.components, [complex]);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
case 'current':
|
||||
return _selectorPseudosNamed(compound2, 'current')
|
||||
.any((pseudo2) => pseudo1.selector == pseudo2.selector);
|
||||
|
||||
case 'nth-child':
|
||||
case 'nth-last-child':
|
||||
return compound2.components.any((pseudo2) =>
|
||||
pseudo2 is PseudoSelector &&
|
||||
pseudo2.name == pseudo1.name &&
|
||||
pseudo2.argument == pseudo1.argument &&
|
||||
pseudo1.selector.isSuperselector(pseudo2.selector));
|
||||
|
||||
default:
|
||||
throw "unreachable";
|
||||
}
|
||||
}
|
||||
|
||||
Iterable<PseudoSelector> _selectorPseudosNamed(CompoundSelector compound,
|
||||
String name) =>
|
||||
compound.components.where((simple) =>
|
||||
simple is PseudoSelector &&
|
||||
simple.type == PseudoType.klass &&
|
||||
simple.selector != null &&
|
||||
simple.name == name);
|
||||
|
@ -23,6 +23,8 @@ class LinkedListValue<T> extends LinkedListEntry<LinkedListValue<T>> {
|
||||
bool listEquals/*<T>*/(List/*<T>*/ list1, List/*<T>*/ list2) =>
|
||||
const ListEquality().equals(list1, list2);
|
||||
|
||||
int listHash(List list) => const ListEquality().hash(list);
|
||||
|
||||
FileSpan spanForList(List<AstNode> nodes) {
|
||||
if (nodes.isEmpty) return null;
|
||||
return nodes.first.span.expand(nodes.last.span);
|
||||
|
Loading…
Reference in New Issue
Block a user