mirror of
https://github.com/danog/dart-sass.git
synced 2024-11-26 20:24:42 +01:00
Add selector specificity.
This commit is contained in:
parent
efaf64020f
commit
a88670da4e
@ -11,7 +11,7 @@ export 'selector/list.dart';
|
||||
export 'selector/namespaced_identifier.dart';
|
||||
export 'selector/placeholder.dart';
|
||||
export 'selector/pseudo.dart';
|
||||
export 'selector/simple.dart';
|
||||
export 'selector/simple.dart' hide baseSpecificity;
|
||||
export 'selector/type.dart';
|
||||
export 'selector/universal.dart';
|
||||
|
||||
|
@ -10,11 +10,34 @@ class ComplexSelector extends Selector {
|
||||
// Indices of [components] that are followed by line breaks.
|
||||
final List<int> lineBreaks;
|
||||
|
||||
int get minSpecificity {
|
||||
if (_minSpecificity == null) _computeSpecificity();
|
||||
return _minSpecificity;
|
||||
}
|
||||
int _minSpecificity;
|
||||
|
||||
int get maxSpecificity {
|
||||
if (_maxSpecificity == null) _computeSpecificity();
|
||||
return _maxSpecificity;
|
||||
}
|
||||
int _maxSpecificity;
|
||||
|
||||
ComplexSelector(Iterable<ComplexSelectorComponent> components,
|
||||
{Iterable<int> lineBreaks})
|
||||
: components = new List.unmodifiable(components),
|
||||
lineBreaks = new List.unmodifiable(lineBreaks);
|
||||
|
||||
void _computeSpecificity() {
|
||||
_minSpecificity = 0;
|
||||
_maxSpecificity = 0;
|
||||
for (var component in components) {
|
||||
if (component is CompoundSelector) {
|
||||
_minSpecificity += component.minSpecificity;
|
||||
_maxSpecificity += component.maxSpecificity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String toString() => components.join(" ");
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,18 @@ import '../selector.dart';
|
||||
class CompoundSelector extends Selector implements ComplexSelectorComponent {
|
||||
final List<SimpleSelector> components;
|
||||
|
||||
int get minSpecificity {
|
||||
if (_minSpecificity == null) _computeSpecificity();
|
||||
return _minSpecificity;
|
||||
}
|
||||
int _minSpecificity;
|
||||
|
||||
int get maxSpecificity {
|
||||
if (_maxSpecificity == null) _computeSpecificity();
|
||||
return _maxSpecificity;
|
||||
}
|
||||
int _maxSpecificity;
|
||||
|
||||
CompoundSelector(Iterable<SimpleSelector> components)
|
||||
: components = new List.unmodifiable(components);
|
||||
|
||||
@ -15,5 +27,14 @@ class CompoundSelector extends Selector implements ComplexSelectorComponent {
|
||||
|
||||
bool isSuperselector(CompoundSelector selector);
|
||||
|
||||
void _computeSpecificity() {
|
||||
_minSpecificity = 0;
|
||||
_maxSpecificity = 0;
|
||||
for (var simple in components) {
|
||||
_minSpecificity += simple.minSpecificity;
|
||||
_maxSpecificity += simple.maxSpecificity;
|
||||
}
|
||||
}
|
||||
|
||||
String toString() => components.join("");
|
||||
}
|
||||
|
@ -2,11 +2,15 @@
|
||||
// MIT-style license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
import 'dart:math' as math;
|
||||
|
||||
import '../selector.dart';
|
||||
|
||||
class IDSelector extends SimpleSelector {
|
||||
final String name;
|
||||
|
||||
int get minSpecificity => math.pow(super.minSpecificity, 2);
|
||||
|
||||
IDSelector(this.name);
|
||||
|
||||
List<SimpleSelector> unify(List<SimpleSelector> compound) {
|
||||
|
@ -2,6 +2,8 @@
|
||||
// MIT-style license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:charcode/charcode.dart';
|
||||
|
||||
import '../selector.dart';
|
||||
@ -15,6 +17,18 @@ class PseudoSelector extends SimpleSelector {
|
||||
|
||||
final SelectorList selector;
|
||||
|
||||
int get minSpecificity {
|
||||
if (_minSpecificity == null) _computeSpecificity();
|
||||
return _minSpecificity;
|
||||
}
|
||||
int _minSpecificity;
|
||||
|
||||
int get maxSpecificity {
|
||||
if (_maxSpecificity == null) _computeSpecificity();
|
||||
return _maxSpecificity;
|
||||
}
|
||||
int _maxSpecificity;
|
||||
|
||||
PseudoSelector(this.name, this.type, {this.argument, this.selector});
|
||||
|
||||
List<SimpleSelector> unify(List<SimpleSelector> compound) {
|
||||
@ -40,6 +54,36 @@ class PseudoSelector extends SimpleSelector {
|
||||
return result;
|
||||
}
|
||||
|
||||
void _computeSpecificity() {
|
||||
if (type == PseudoType.element) {
|
||||
_minSpecificity = 1;
|
||||
_maxSpecificity = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (selector == null) {
|
||||
_minSpecificity = super.minSpecificity;
|
||||
_maxSpecificity = super.maxSpecificity;
|
||||
}
|
||||
|
||||
if (name == 'not') {
|
||||
_minSpecificity = 0;
|
||||
_maxSpecificity = 0;
|
||||
for (var complex in selector.members) {
|
||||
_minSpecificity = math.max(_minSpecificity, complex.minSpecificity);
|
||||
_maxSpecificity = math.max(_maxSpecificity, complex.maxSpecificity);
|
||||
}
|
||||
} else {
|
||||
// This is higher than any selector's specificity can actually be.
|
||||
_minSpecificity = math.pow(super.minSpecificity, 3);
|
||||
_maxSpecificity = 0;
|
||||
for (var complex in selector.members) {
|
||||
_minSpecificity = math.min(_minSpecificity, complex.minSpecificity);
|
||||
_maxSpecificity = math.max(_maxSpecificity, complex.maxSpecificity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This intentionally uses identity for the selector list, if one is available.
|
||||
bool operator==(other) =>
|
||||
other is PseudoSelector &&
|
||||
|
@ -5,6 +5,13 @@
|
||||
import '../selector.dart';
|
||||
|
||||
abstract class SimpleSelector extends Selector {
|
||||
// 1000 is the base used for calculating selector specificity.
|
||||
//
|
||||
// The spec says this should be "sufficiently high"; it's extremely unlikely
|
||||
// that any single selector sequence will contain 1,000 simple selectors.
|
||||
int get minSpecificity => 1000;
|
||||
int get maxSpecificity => minSpecificity;
|
||||
|
||||
List<SimpleSelector> unify(List<SimpleSelector> compound) {
|
||||
if (compound.contains(this)) return compound;
|
||||
|
||||
|
@ -7,6 +7,8 @@ import '../selector.dart';
|
||||
class TypeSelector extends SimpleSelector {
|
||||
final NamespacedIdentifier name;
|
||||
|
||||
int get minSpecificity => 1;
|
||||
|
||||
TypeSelector(this.name);
|
||||
|
||||
List<SimpleSelector> unify(List<SimpleSelector> compound) {
|
||||
|
@ -8,6 +8,8 @@ import '../selector.dart';
|
||||
class UniversalSelector extends SimpleSelector {
|
||||
final String namespace;
|
||||
|
||||
int get minSpecificity => 0;
|
||||
|
||||
UniversalSelector({this.namespace});
|
||||
|
||||
List<SimpleSelector> unify(List<SimpleSelector> compound) {
|
||||
|
Loading…
Reference in New Issue
Block a user