findBestRuleSetAndAdd method
Implementation
void findBestRuleSetAndAdd(Selector selector, CSSRule rule) {
// Enforce CSS rule: a pseudo-element must be the last simple selector
// in a compound selector. If any simple selector appears after a
// pseudo-element, the selector is invalid and must not match.
final List<SimpleSelectorSequence> seqs = selector.simpleSelectorSequences;
for (int i = 0; i < seqs.length; i++) {
final s = seqs[i].simpleSelector;
if (s is PseudoElementSelector || s is PseudoElementFunctionSelector) {
if (i != seqs.length - 1) {
// Invalid selector like `P:first-line.three`; drop this rule.
return;
}
break;
}
}
// Choose the best indexing key from the RIGHTMOST COMPOUND only, with
// priority: id > class > attribute > tag > legacy pseudo > universal.
// Build the rightmost compound by walking from the end until a combinator
// boundary.
final List<SimpleSelector> rightmost = <SimpleSelector>[];
for (final seq in seqs.reversed) {
rightmost.add(seq.simpleSelector);
if (seq.combinator != TokenKind.COMBINATOR_NONE) break;
}
String? id;
String? className;
String? attributeName;
String? tagName;
String? legacyPseudo;
// Scan for best key across the compound (no early break on pseudo).
for (final simple in rightmost) {
if (simple is IdSelector) {
id ??= simple.name;
} else if (simple is ClassSelector) {
className ??= simple.name;
} else if (simple is AttributeSelector) {
attributeName ??= simple.name;
} else if (simple is ElementSelector && !simple.isWildcard) {
tagName ??= simple.name;
} else if (simple is PseudoClassSelector || simple is PseudoElementSelector) {
final name = (simple as dynamic).name as String; // both have name
if (_isLegacyPsuedoClass(name)) legacyPseudo ??= name;
} else if (simple is PseudoClassFunctionSelector) {
// ignore function pseudos for bucketing
} else if (simple is NegationSelector) {
// ignore :not() for bucketing; prefer other keys if present
}
}
void insertRule(String key, CSSRule rule, CSSMap map) {
List<CSSRule>? rules = map[key] ?? [];
rules.add(rule);
map[key] = rules;
}
if (id != null && id.isNotEmpty) {
insertRule(id, rule, idRules);
return;
}
if (className != null && className.isNotEmpty) {
insertRule(className, rule, classRules);
return;
}
if (attributeName != null && attributeName.isNotEmpty) {
insertRule(attributeName.toUpperCase(), rule, attributeRules);
return;
}
if (tagName != null && tagName.isNotEmpty) {
insertRule(tagName.toUpperCase(), rule, tagRules);
return;
}
if (legacyPseudo != null) {
pseudoRules.add(rule);
return;
}
universalRules.add(rule);
}