blitz_dom/
query_selector.rs

1use selectors::SelectorList;
2use smallvec::SmallVec;
3use style::dom_apis::{MayUseInvalidation, QueryAll, QueryFirst, query_selector};
4use style::selector_parser::{SelectorImpl, SelectorParser};
5use style_traits::ParseError;
6
7use crate::{BaseDocument, Node};
8
9impl BaseDocument {
10    /// Find the first node that matches the selector specified as a string
11    /// Returns:
12    ///   - Err(_) if parsing the selector fails
13    ///   - Ok(None) if nothing matches
14    ///   - Ok(Some(node_id)) with the first node ID that matches if one is found
15    pub fn query_selector<'input>(
16        &self,
17        selector: &'input str,
18    ) -> Result<Option<usize>, ParseError<'input>> {
19        let selector_list = self.try_parse_selector_list(selector)?;
20        Ok(self.query_selector_raw(&selector_list))
21    }
22
23    /// Find the first node that matches the selector(s) specified in selector_list
24    pub fn query_selector_raw(&self, selector_list: &SelectorList<SelectorImpl>) -> Option<usize> {
25        let root_node = self.root_node();
26        let mut result = None;
27        query_selector::<&Node, QueryFirst>(
28            root_node,
29            selector_list,
30            &mut result,
31            MayUseInvalidation::Yes,
32        );
33
34        result.map(|node| node.id)
35    }
36
37    /// Find all nodes that match the selector specified as a string
38    /// Returns:
39    ///   - `Err(_)` if parsing the selector fails
40    ///   - `Ok(SmallVec<usize>)` with all matching nodes otherwise
41    pub fn query_selector_all<'input>(
42        &self,
43        selector: &'input str,
44    ) -> Result<SmallVec<[usize; 32]>, ParseError<'input>> {
45        let selector_list = self.try_parse_selector_list(selector)?;
46        Ok(self.query_selector_all_raw(&selector_list))
47    }
48
49    /// Find all nodes that match the selector(s) specified in selector_list
50    pub fn query_selector_all_raw(
51        &self,
52        selector_list: &SelectorList<SelectorImpl>,
53    ) -> SmallVec<[usize; 32]> {
54        let root_node = self.root_node();
55        let mut results = SmallVec::new();
56        query_selector::<&Node, QueryAll>(
57            root_node,
58            selector_list,
59            &mut results,
60            MayUseInvalidation::Yes,
61        );
62
63        results.iter().map(|node| node.id).collect()
64    }
65
66    pub fn try_parse_selector_list<'input>(
67        &self,
68        input: &'input str,
69    ) -> Result<SelectorList<SelectorImpl>, ParseError<'input>> {
70        let url_extra_data = self.url.url_extra_data();
71        SelectorParser::parse_author_origin_no_namespace(input, &url_extra_data)
72    }
73}