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