matchedPseudoRules method

List<CSSStyleRule> matchedPseudoRules(
  1. RuleSet ruleSet,
  2. Element element, {
  3. SelectorAncestorTokenSet? ancestorTokens,
  4. SelectorEvaluator? evaluator,
})

Implementation

List<CSSStyleRule> matchedPseudoRules(RuleSet ruleSet, Element element,
    {SelectorAncestorTokenSet? ancestorTokens,
    SelectorEvaluator? evaluator}) {
  final SelectorEvaluator resolvedEvaluator = evaluator ?? SelectorEvaluator();
  final SelectorAncestorTokenSet? resolvedAncestorTokens = ancestorTokens ??
      (DebugFlags.enableCssAncestryFastPath
          ? _buildAncestorTokens(element)
          : null);

  // Collect candidates from all indexed buckets because many pseudo-element
  // selectors (e.g., ".foo div::before") are indexed under tag/class/id
  // buckets for matching efficiency.
  final List<CSSStyleRule> candidates = [];

  // #id
  String? id = element.id;
  if (id != null) {
    _collectMatchingRulesForList(
      ruleSet.idRules[id],
      element,
      evaluator: resolvedEvaluator,
      includePseudo: true,
      enableAncestryFastPath: DebugFlags.enableCssAncestryFastPath,
      ancestorTokens: resolvedAncestorTokens,
      matchedRules: candidates,
    );
  }

  // .class
  for (final String className in element.classList) {
    _collectMatchingRulesForList(
      ruleSet.classRules[className],
      element,
      evaluator: resolvedEvaluator,
      includePseudo: true,
      enableAncestryFastPath: DebugFlags.enableCssAncestryFastPath,
      ancestorTokens: resolvedAncestorTokens,
      matchedRules: candidates,
    );
  }

  // [attr]
  for (final String attribute in element.attributes.keys) {
    _collectMatchingRulesForList(
      ruleSet.attributeRules[attribute.toUpperCase()],
      element,
      evaluator: resolvedEvaluator,
      includePseudo: true,
      enableAncestryFastPath: DebugFlags.enableCssAncestryFastPath,
      ancestorTokens: resolvedAncestorTokens,
      matchedRules: candidates,
    );
  }

  // tag
  final String tagLookup = element.tagName.toUpperCase();
  _collectMatchingRulesForList(
    ruleSet.tagRules[tagLookup],
    element,
    evaluator: resolvedEvaluator,
    includePseudo: true,
    enableAncestryFastPath: DebugFlags.enableCssAncestryFastPath,
    ancestorTokens: resolvedAncestorTokens,
    matchedRules: candidates,
  );

  // universal
  _collectMatchingRulesForList(
    ruleSet.universalRules,
    element,
    evaluator: resolvedEvaluator,
    includePseudo: true,
    enableAncestryFastPath: DebugFlags.enableCssAncestryFastPath,
    ancestorTokens: resolvedAncestorTokens,
    matchedRules: candidates,
  );

  // legacy pseudo bucket (for selectors without a better rightmost key)
  _collectMatchingRulesForList(
    ruleSet.pseudoRules,
    element,
    evaluator: resolvedEvaluator,
    includePseudo: true,
    enableAncestryFastPath: DebugFlags.enableCssAncestryFastPath,
    ancestorTokens: resolvedAncestorTokens,
    matchedRules: candidates,
  );

  // Deduplicate while preserving order.
  final List<CSSStyleRule> list = [];
  final Set<CSSStyleRule> seen = LinkedHashSet<CSSStyleRule>.identity();
  for (final CSSStyleRule rule in candidates) {
    if (seen.add(rule)) {
      list.add(rule);
    }
  }

  return list;
}