diff --git a/src/interpreter/style.rs b/src/interpreter/style.rs index f0971de..f23b23c 100644 --- a/src/interpreter/style.rs +++ b/src/interpreter/style.rs @@ -541,6 +541,62 @@ impl StyleSheet { self.index.is_some() } + pub fn query_index<'a>( + &'a self, + type_name: &str, + el_id: Option<&str>, + el_classes: &[&str], + active_pseudo: &[&str], + structural: &StructuralContext, + ancestors: &[AncestorInfo], + preceding_siblings: &[AncestorInfo], + el_attributes: &HashMap, + ) -> Option>> { + let index = self.index.as_ref()?; + + let mut candidates: HashSet = HashSet::with_capacity(32); + + candidates.extend(&index.universal_rules); + + if let Some(rules) = index.by_tag.get(type_name) { + candidates.extend(rules); + } + + for cls in el_classes { + if let Some(rules) = index.by_class.get(*cls) { + candidates.extend(rules); + } + } + + if let Some(id) = el_id { + if let Some(rules) = index.by_id.get(id) { + candidates.extend(rules); + } + } + + for (_, rule_id) in &index.complex_rules { + candidates.insert(*rule_id); + } + + let mut matched: Vec<(RuleId, &StyleRule)> = candidates + .iter() + .filter(|&&rule_id| { + let rule = &index.rules[rule_id]; + rule.selector + .matches(type_name, el_id, el_classes, active_pseudo, structural, ancestors, preceding_siblings, el_attributes) + }) + .map(|&rule_id| (rule_id, &index.rules[rule_id])) + .collect(); + + matched.sort_by(|(i, _a), (j, _b)| { + index.rule_specificities[*i] + .cmp(&index.rule_specificities[*j]) + .then_with(|| i.cmp(j)) + }); + + Some(matched.into_iter().map(|(_, rule)| &rule.properties).collect()) + } + pub fn matching_rules<'a>( &'a self, type_name: &str, @@ -552,6 +608,10 @@ impl StyleSheet { preceding_siblings: &[AncestorInfo], el_attributes: &HashMap, ) -> Vec<&'a HashMap> { + if let Some(matched) = self.query_index(type_name, el_id, el_classes, active_pseudo, structural, ancestors, preceding_siblings, el_attributes) { + return matched; + } + let mut matched: Vec<(usize, &StyleRule)> = self .rules .iter()