1use crate::document::{Node, NodeKind};
17
18fn is_attribute_or_namespace(kind: NodeKind) -> bool {
19 matches!(kind, NodeKind::Attribute | NodeKind::Namespace)
20}
21
22fn ancestor_vec<'a, N: Node<'a>>(n: N) -> Vec<N> {
25 let mut out = Vec::new();
26 let mut cur = n.parent();
27 while let Some(p) = cur {
28 out.push(p);
29 cur = p.parent();
30 }
31 out
32}
33
34fn descendant_vec<'a, N: Node<'a>>(n: N) -> Vec<N> {
36 let mut out = Vec::new();
37 for c in n.children() {
38 out.push(c);
39 out.extend(descendant_vec(c));
40 }
41 out
42}
43
44fn descendant_or_self_vec<'a, N: Node<'a>>(n: N) -> Vec<N> {
46 let mut out = vec![n];
47 out.extend(descendant_vec(n));
48 out
49}
50
51fn root_of<'a, N: Node<'a>>(n: N) -> N {
53 let mut cur = n;
54 while let Some(p) = cur.parent() {
55 cur = p;
56 }
57 cur
58}
59
60pub fn child<'a, N: Node<'a>>(n: N) -> impl Iterator<Item = N> + 'a {
62 n.children()
63}
64
65pub fn descendant<'a, N: Node<'a>>(n: N) -> impl Iterator<Item = N> + 'a {
68 descendant_vec(n).into_iter()
69}
70
71pub fn descendant_or_self<'a, N: Node<'a>>(n: N) -> impl Iterator<Item = N> + 'a {
74 descendant_or_self_vec(n).into_iter()
75}
76
77pub fn parent<'a, N: Node<'a>>(n: N) -> impl Iterator<Item = N> + 'a {
80 n.parent().into_iter()
81}
82
83pub fn ancestor<'a, N: Node<'a>>(n: N) -> impl Iterator<Item = N> + 'a {
89 ancestor_vec(n).into_iter()
90}
91
92pub fn ancestor_or_self<'a, N: Node<'a>>(n: N) -> impl Iterator<Item = N> + 'a {
96 let mut out = vec![n];
97 out.extend(ancestor_vec(n));
98 out.into_iter()
99}
100
101pub fn following_sibling<'a, N: Node<'a>>(n: N) -> impl Iterator<Item = N> + 'a {
105 let mut out = Vec::new();
106 if !is_attribute_or_namespace(n.kind())
107 && let Some(parent) = n.parent()
108 {
109 let mut found = false;
110 for c in parent.children() {
111 if found {
112 out.push(c);
113 } else if c == n {
114 found = true;
115 }
116 }
117 }
118 out.into_iter()
119}
120
121pub fn preceding_sibling<'a, N: Node<'a>>(n: N) -> impl Iterator<Item = N> + 'a {
126 let mut out = Vec::new();
127 if !is_attribute_or_namespace(n.kind())
128 && let Some(parent) = n.parent()
129 {
130 for c in parent.children() {
131 if c == n {
132 break;
133 }
134 out.push(c);
135 }
136 }
137 out.reverse();
138 out.into_iter()
139}
140
141fn following_vec<'a, N: Node<'a>>(n: N) -> Vec<N> {
145 let all = descendant_or_self_vec(root_of(n));
146 let idx = all
147 .iter()
148 .position(|x| *x == n)
149 .expect("n must be reachable from its own document root via children()");
150 let subtree_len = 1 + descendant_vec(n).len();
151 all.into_iter().skip(idx + subtree_len).collect()
152}
153
154fn preceding_vec<'a, N: Node<'a>>(n: N) -> Vec<N> {
157 let all = descendant_or_self_vec(root_of(n));
158 let idx = all
159 .iter()
160 .position(|x| *x == n)
161 .expect("n must be reachable from its own document root via children()");
162 let ancestors = ancestor_vec(n);
163 let mut out: Vec<N> = all[..idx]
164 .iter()
165 .copied()
166 .filter(|c| !ancestors.contains(c))
167 .collect();
168 out.reverse();
169 out
170}
171
172pub fn following<'a, N: Node<'a>>(n: N) -> impl Iterator<Item = N> + 'a {
184 let out: Vec<N> = if is_attribute_or_namespace(n.kind()) {
185 let owner = n
186 .parent()
187 .expect("attribute/namespace node must have an owner element as parent");
188 let mut v = descendant_vec(owner);
189 v.extend(following_vec(owner));
190 v
191 } else {
192 following_vec(n)
193 };
194 out.into_iter()
195}
196
197pub fn preceding<'a, N: Node<'a>>(n: N) -> impl Iterator<Item = N> + 'a {
208 let out: Vec<N> = if is_attribute_or_namespace(n.kind()) {
209 let owner = n
210 .parent()
211 .expect("attribute/namespace node must have an owner element as parent");
212 preceding_vec(owner)
213 } else {
214 preceding_vec(n)
215 };
216 out.into_iter()
217}
218
219pub fn attribute<'a, N: Node<'a>>(n: N) -> impl Iterator<Item = N> + 'a {
222 let out: Vec<N> = if n.kind() == NodeKind::Element {
223 n.attributes().collect()
224 } else {
225 Vec::new()
226 };
227 out.into_iter()
228}
229
230pub fn namespace<'a, N: Node<'a>>(n: N) -> impl Iterator<Item = N> + 'a {
233 let out: Vec<N> = if n.kind() == NodeKind::Element {
234 n.namespaces().collect()
235 } else {
236 Vec::new()
237 };
238 out.into_iter()
239}
240
241pub fn self_axis<'a, N: Node<'a>>(n: N) -> impl Iterator<Item = N> + 'a {
243 std::iter::once(n)
244}
245
246#[cfg(test)]
247mod tests {
248 use super::*;
249 use crate::document::fixture::build;
250
251 #[test]
252 fn child_axis_on_nested_tree() {
253 let f = build();
254 let body = f.doc.node(f.body);
255 let got: Vec<_> = child(body).collect();
256 assert_eq!(
257 got,
258 vec![
259 f.doc.node(f.text0),
260 f.doc.node(f.span),
261 f.doc.node(f.comment),
262 f.doc.node(f.pi),
263 f.doc.node(f.text2),
264 ]
265 );
266 }
267
268 #[test]
269 fn descendant_axis_on_nested_tree() {
270 let f = build();
271 let html = f.doc.node(f.html);
272 let got: Vec<_> = descendant(html).collect();
273 assert_eq!(
274 got,
275 vec![
276 f.doc.node(f.body),
277 f.doc.node(f.text0),
278 f.doc.node(f.span),
279 f.doc.node(f.text1),
280 f.doc.node(f.comment),
281 f.doc.node(f.pi),
282 f.doc.node(f.text2),
283 ]
284 );
285 }
286
287 #[test]
288 fn descendant_or_self_axis_on_nested_tree() {
289 let f = build();
290 let span = f.doc.node(f.span);
291 let got: Vec<_> = descendant_or_self(span).collect();
292 assert_eq!(got, vec![span, f.doc.node(f.text1)]);
293 }
294
295 #[test]
296 fn parent_ancestor_ancestor_or_self_from_leaf_nearest_first() {
297 let f = build();
298 let text1 = f.doc.node(f.text1); let span = f.doc.node(f.span);
300 let body = f.doc.node(f.body);
301 let html = f.doc.node(f.html);
302 let root = f.doc.node(0);
303
304 assert_eq!(parent(text1).collect::<Vec<_>>(), vec![span]);
305 assert_eq!(
306 ancestor(text1).collect::<Vec<_>>(),
307 vec![span, body, html, root],
308 "ancestor must be nearest-parent-first, not root-first"
309 );
310 assert_eq!(
311 ancestor_or_self(text1).collect::<Vec<_>>(),
312 vec![text1, span, body, html, root]
313 );
314 }
315
316 #[test]
317 fn ancestor_of_root_is_empty() {
318 let f = build();
319 let root = f.doc.node(0);
320 assert_eq!(ancestor(root).collect::<Vec<_>>(), Vec::new());
321 }
322
323 #[test]
324 fn following_and_preceding_sibling_order_on_multiple_siblings() {
325 let f = build();
326 let comment = f.doc.node(f.comment);
327 assert_eq!(
329 following_sibling(comment).collect::<Vec<_>>(),
330 vec![f.doc.node(f.pi), f.doc.node(f.text2)]
331 );
332 assert_eq!(
333 preceding_sibling(comment).collect::<Vec<_>>(),
334 vec![f.doc.node(f.span), f.doc.node(f.text0)],
335 "preceding-sibling must be nearest-sibling-first"
336 );
337 }
338
339 #[test]
340 fn following_excludes_attribute_and_namespace_nodes() {
341 let f = build();
342 let span = f.doc.node(f.span);
343 let got: Vec<_> = following(span).collect();
349 assert_eq!(
350 got,
351 vec![f.doc.node(f.comment), f.doc.node(f.pi), f.doc.node(f.text2)]
352 );
353 assert!(!got.contains(&f.doc.node(f.span_attr)));
354 }
355
356 #[test]
357 fn preceding_excludes_attribute_and_namespace_nodes() {
358 let f = build();
359 let text0 = f.doc.node(f.text0);
360 let got: Vec<_> = preceding(text0).collect();
364 assert_eq!(got, Vec::new());
365 }
366
367 #[test]
368 fn preceding_excludes_a_preceding_siblings_own_attribute_node() {
369 let f = build();
370 let text1 = f.doc.node(f.text1);
371 let got: Vec<_> = preceding(text1).collect();
377 assert_eq!(got, vec![f.doc.node(f.text0)]);
378 assert!(!got.contains(&f.doc.node(f.span_attr)));
379 }
380
381 #[test]
382 fn preceding_reverse_document_order_excluding_ancestors() {
383 let f = build();
384 let text2 = f.doc.node(f.text2);
385 let got: Vec<_> = preceding(text2).collect();
386 assert_eq!(
387 got,
388 vec![
389 f.doc.node(f.pi),
390 f.doc.node(f.comment),
391 f.doc.node(f.text1),
392 f.doc.node(f.span),
393 f.doc.node(f.text0),
394 ],
395 "preceding must be reverse document order and exclude ancestors (body, html, root)"
396 );
397 assert!(!got.contains(&f.doc.node(f.body)));
398 assert!(!got.contains(&f.doc.node(f.html)));
399 }
400
401 #[test]
402 fn attribute_and_namespace_axes_on_element_with_both() {
403 let f = build();
404 let html = f.doc.node(f.html);
405 assert_eq!(
406 attribute(html).collect::<Vec<_>>(),
407 vec![f.doc.node(f.html_lang), f.doc.node(f.html_id)]
408 );
409 assert_eq!(
410 namespace(html).collect::<Vec<_>>(),
411 vec![f.doc.node(f.html_ns)]
412 );
413
414 let body = f.doc.node(f.body);
415 assert_eq!(
416 attribute(body).collect::<Vec<_>>(),
417 vec![f.doc.node(f.body_class)]
418 );
419 assert_eq!(
420 namespace(body).collect::<Vec<_>>(),
421 vec![f.doc.node(f.body_ns)]
422 );
423 }
424
425 #[test]
426 fn self_axis_is_trivial() {
427 let f = build();
428 let body = f.doc.node(f.body);
429 assert_eq!(self_axis(body).collect::<Vec<_>>(), vec![body]);
430 }
431
432 #[test]
433 fn attribute_node_has_no_attribute_namespace_or_sibling_axes() {
434 let f = build();
435 let lang = f.doc.node(f.html_lang);
436 assert_eq!(attribute(lang).collect::<Vec<_>>(), Vec::new());
437 assert_eq!(namespace(lang).collect::<Vec<_>>(), Vec::new());
438 assert_eq!(following_sibling(lang).collect::<Vec<_>>(), Vec::new());
439 assert_eq!(preceding_sibling(lang).collect::<Vec<_>>(), Vec::new());
440 }
441
442 #[test]
443 fn following_and_preceding_from_an_attribute_context_node() {
444 let f = build();
445 let lang = f.doc.node(f.html_lang);
446 assert_eq!(
449 following(lang).collect::<Vec<_>>(),
450 vec![
451 f.doc.node(f.body),
452 f.doc.node(f.text0),
453 f.doc.node(f.span),
454 f.doc.node(f.text1),
455 f.doc.node(f.comment),
456 f.doc.node(f.pi),
457 f.doc.node(f.text2),
458 ]
459 );
460 assert_eq!(preceding(lang).collect::<Vec<_>>(), Vec::new());
463 }
464}