nipper_trunk/
traversal.rs

1use crate::matcher::{MatchScope, Matcher, Matches};
2use crate::Document;
3use crate::Node;
4use crate::Selection;
5use std::collections::HashSet;
6use std::vec::IntoIter;
7
8impl Document {
9    /// Gets the descendants of the root document node in the current, filter by a selector.
10    /// It returns a new selection object containing these matched elements.
11    ///
12    /// # Panics
13    ///
14    /// Panics if failed to parse the given CSS selector.
15    pub fn select(&self, sel: &str) -> Selection {
16        let matcher = Matcher::new(sel).expect("Invalid CSS selector");
17        let root = self.tree.root();
18        Selection {
19            nodes: Matches::from_one(root, matcher.clone(), MatchScope::IncludeNode).collect(),
20        }
21    }
22
23    /// Alias for `select`, it gets the descendants of the root document node in the current, filter by a selector.
24    /// It returns a new selection object containing these matched elements.
25    ///
26    /// # Panics
27    ///
28    /// Panics if failed to parse the given CSS selector.
29    pub fn nip(&self, sel: &str) -> Selection {
30        self.select(sel)
31    }
32
33    /// Gets the descendants of the root document node in the current, filter by a selector.
34    /// It returns a new selection object containing these matched elements.
35    pub fn try_select(&self, sel: &str) -> Option<Selection> {
36        match Matcher::new(sel) {
37            Ok(matcher) => {
38                let root = self.tree.root();
39                let nodes: Vec<Node> =
40                    Matches::from_one(root, matcher.clone(), MatchScope::ChildrenOnly).collect();
41                if nodes.len() > 0 {
42                    Some(Selection { nodes })
43                } else {
44                    None
45                }
46            }
47            Err(_) => None,
48        }
49    }
50
51    /// Gets the descendants of the root document node in the current, filter by a matcher.
52    /// It returns a new selection object containing these matched elements.
53    pub fn select_matcher<'a, 'b>(&'a self, matcher: &'b Matcher) -> Selection<'a> {
54        let root = self.tree.root();
55        let nodes = Matches::from_one(root, matcher.clone(), MatchScope::IncludeNode).collect();
56
57        Selection { nodes }
58    }
59}
60
61impl<'a> Selection<'a> {
62    /// Gets the descendants of each element in the current set of matched
63    /// elements, filter by a selector. It returns a new Selection object
64    /// containing these matched elements.
65    ///
66    /// # Panics
67    ///
68    /// Panics if failed to parse the given CSS selector.
69    pub fn select(&self, sel: &str) -> Selection<'a> {
70        let matcher = Matcher::new(sel).expect("Invalid CSS seletor");
71        Selection {
72            nodes: Matches::from_list(
73                self.nodes.clone().into_iter(),
74                matcher,
75                MatchScope::ChildrenOnly,
76            )
77            .collect(),
78        }
79    }
80
81    /// Alias for `select`, it gets the descendants of each element in the current set of matched
82    /// elements, filter by a selector. It returns a new Selection object
83    /// containing these matched elements.
84    ///
85    /// # Panics
86    ///
87    /// Panics if failed to parse the given CSS selector.
88    pub fn nip(&self, sel: &str) -> Selection<'a> {
89        self.select(sel)
90    }
91
92    /// Gets the descendants of each element in the current set of matched
93    /// elements, filter by a selector. It returns a new Selection object
94    /// containing these matched elements.
95    pub fn try_select(&self, sel: &str) -> Option<Selection<'a>> {
96        match Matcher::new(sel) {
97            Ok(matcher) => {
98                let nodes: Vec<Node> = Matches::from_list(
99                    self.nodes.clone().into_iter(),
100                    matcher,
101                    MatchScope::ChildrenOnly,
102                )
103                .collect();
104                if nodes.len() > 0 {
105                    Some(Selection { nodes })
106                } else {
107                    None
108                }
109            }
110            Err(_) => None,
111        }
112    }
113
114    /// Gets the descendants of each element in the current set of matched
115    /// elements, filter by a matcher. It returns a new Selection object
116    /// containing these matched elements.
117    pub fn select_matcher(&self, matcher: &Matcher) -> Selection<'a> {
118        Selection {
119            nodes: Matches::from_list(
120                self.nodes.clone().into_iter(),
121                matcher.clone(),
122                MatchScope::ChildrenOnly,
123            )
124            .collect(),
125        }
126    }
127
128    /// Returns a slice of underlying nodes.
129    pub fn nodes(&self) -> &[Node<'a>] {
130        &self.nodes
131    }
132
133    /// Creates an iterator over these matched elements.
134    pub fn iter(&self) -> Selections<Node<'a>> {
135        Selections::new(self.nodes.clone().into_iter())
136    }
137
138    /// Gets the parent of each element in the selection. It returns a
139    /// mew Selection object containing these elements.
140    pub fn parent(&self) -> Selection<'a> {
141        let mut result = Vec::with_capacity(self.length());
142        let mut set = HashSet::with_capacity(self.length());
143
144        for node in self.nodes() {
145            if let Some(parent) = node.parent() {
146                if !set.contains(&parent.id) {
147                    set.insert(parent.id);
148                    result.push(parent);
149                }
150            }
151        }
152
153        Self { nodes: result }
154    }
155
156    /// Gets the child elements of each element in the selection.
157    /// It returns a new Selection object containing these elements.
158    pub fn children(&self) -> Selection<'a> {
159        let mut result = Vec::with_capacity(self.length());
160        let mut set = HashSet::with_capacity(self.length());
161
162        for node in self.nodes() {
163            for child in node.children() {
164                if !set.contains(&child.id) && child.is_element() {
165                    set.insert(child.id);
166                    result.push(child);
167                }
168            }
169        }
170
171        Self { nodes: result }
172    }
173
174    #[deprecated(since = "0.1.6", note = "Please use `next_sibling`")]
175    /// Gets the immediately following sibling of each element in the
176    /// selection. It returns a new Selection object containing these elements.
177    pub fn next(&self) -> Selection<'a> {
178        self.next_sibling()
179    }
180
181    /// Gets the immediately following sibling of each element in the
182    /// selection. It returns a new Selection object containing these elements.
183    pub fn next_sibling(&self) -> Selection<'a> {
184        let mut result = Vec::with_capacity(self.length());
185        let mut set = HashSet::with_capacity(self.length());
186
187        for node in self.nodes() {
188            if let Some(sibling) = node.next_element_sibling() {
189                if !set.contains(&sibling.id) {
190                    set.insert(sibling.id);
191                    result.push(sibling);
192                }
193            }
194        }
195
196        Self { nodes: result }
197    }
198
199    /// Gets the immediately previous sibling of each element in the
200    /// selection. It returns a new Selection object containing these elements.
201    pub fn prev_sibling(&self) -> Selection<'a> {
202        let mut result = Vec::with_capacity(self.length());
203        let mut set = HashSet::with_capacity(self.length());
204
205        for node in self.nodes() {
206            if let Some(sibling) = node.prev_element_sibling() {
207                if !set.contains(&sibling.id) {
208                    set.insert(sibling.id);
209                    result.push(sibling);
210                }
211            }
212        }
213
214        Self { nodes: result }
215    }
216
217    /// Reduces the set of matched elements to the first in the set.
218    /// It returns a new selection object, and an empty selection object if the
219    /// selection is empty.
220    pub fn first(&self) -> Selection<'a> {
221        if self.length() > 0 {
222            Selection::from(self.nodes[0].clone())
223        } else {
224            Default::default()
225        }
226    }
227
228    /// Reduces the set of matched elements to the last in the set.
229    /// It returns a new selection object, and an empty selection object if the
230    /// selection is empty.
231    pub fn last(&self) -> Selection<'a> {
232        if self.length() > 0 {
233            Selection::from(self.nodes[self.length() - 1].clone())
234        } else {
235            Default::default()
236        }
237    }
238
239    /// Retrieves the underlying node at the specified index.
240    pub fn get(&self, index: usize) -> Option<&Node<'a>> {
241        self.nodes.get(index)
242    }
243}
244
245/// Iterator over a collection of matched elements.
246pub struct Selections<I> {
247    iter: IntoIter<I>,
248}
249
250impl<I> Selections<I> {
251    fn new(iter: IntoIter<I>) -> Self {
252        Self { iter }
253    }
254}
255
256impl<'a> Iterator for Selections<Node<'a>> {
257    type Item = Selection<'a>;
258
259    fn next(&mut self) -> Option<Self::Item> {
260        self.iter.next().map(Selection::from)
261    }
262}
263
264impl<'a> DoubleEndedIterator for Selections<Node<'a>> {
265    fn next_back(&mut self) -> Option<Self::Item> {
266        self.iter.next_back().map(Selection::from)
267    }
268}