1use super::*;
2use std::collections::VecDeque;
3
4impl Hatmel {
5 pub fn get(&self, handle: Handle) -> Option<&Content> {
6 self.nodes.get(handle).map(|n| &n.content)
7 }
8 pub fn children(&self, handle: Handle) -> impl DoubleEndedIterator<Item = Handle> + '_ {
10 self.children
11 .get(&handle)
12 .map(|v| &v[..])
13 .unwrap_or_default()
14 .iter()
15 .cloned()
16 }
17 pub fn parent(&self, handle: Handle) -> Option<Handle> {
19 self.parents.get(&handle).cloned()
20 }
21 pub fn ancestors(&self, adept: Handle) -> ParentIter {
22 ParentIter::new(self, adept)
23 }
24 pub fn get_element_name(&self, node: Handle) -> Option<(&str, &str)> {
26 self.nodes.get(node)?.content.element_name()
27 }
28 pub fn get_element_attribute(&self, node: Handle, name: &str, ns: &str) -> Option<&str> {
30 let attrs = self.nodes.get(node)?.content.attributes();
31 attrs
32 .rev()
33 .filter(|a| &a.name == name && namespace_equals_or_html(&a.namespace, ns))
34 .map(|a| a.value.as_ref())
35 .next()
36 }
37 pub fn siblings_after(&self, handle: Handle) -> impl DoubleEndedIterator<Item = Handle> + '_ {
39 self.parent(handle)
40 .and_then(|p| self.children.get(&p).map(|all| &all[..]))
41 .and_then(|all| {
42 all.iter()
43 .position(|c| c == &handle)
44 .map(|mypos| &all[mypos.saturating_add(1)..])
45 })
46 .unwrap_or_default()
47 .iter()
48 .cloned()
49 }
50 pub fn siblings_before(&self, handle: Handle) -> impl DoubleEndedIterator<Item = Handle> + '_ {
52 self.parent(handle)
53 .and_then(|p| self.children.get(&p).map(|all| &all[..]))
54 .and_then(|all| {
55 all.iter()
56 .position(|c| c == &handle)
57 .map(|mypos| &all[..mypos])
58 })
59 .unwrap_or_default()
60 .iter()
61 .cloned()
62 }
63 pub fn get_title(&self) -> StrTendril {
65 let title: Option<StrTendril> = (|| {
66 let html = self
67 .as_element(0, "html", "")
68 .or_else(|| self.children_as_elements(0, "html", "").into_iter().next())?;
69 let head = self
70 .children_as_elements(html, "head", "")
71 .into_iter()
72 .next()?;
73 let title = self
74 .children_as_elements(head, "title", "")
75 .into_iter()
76 .next()?;
77 Some(self.get_text(title))
78 })();
79 title.unwrap_or_default()
80 }
81
82 fn as_element(&self, node: Handle, local_name: &str, name_space: &str) -> Option<Handle> {
83 let (ln, ns) = self.get_element_name(node)?;
84 if local_name != ln {
85 return None;
86 }
87 if !namespace_equals_or_html(name_space, ns) {
88 return None;
89 }
90 Some(node)
91 }
92 fn children_as_elements<'a>(
93 &'a self,
94 node: Handle,
95 local_name: &'a str,
96 name_space: &'a str,
97 ) -> impl IntoIterator<Item = Handle> + 'a {
98 self.children[&node]
99 .iter()
100 .filter_map(move |c| self.as_element(*c, local_name, name_space))
101 }
102 pub fn get_text(&self, node: Handle) -> StrTendril {
104 let mut s = StrTendril::new();
105
106 let mut nodes = VecDeque::from(vec![node]);
107 while let Some(node) = nodes.pop_front() {
108 match &self.nodes[node].content {
109 Content::Comment { .. }
111 | Content::ProcessingInstruction { .. }
112 | Content::DocType { .. }
113 | Content::Element(Element {
114 kind: ElementKind::Template,
115 ..
116 }) => {}
117
118 Content::Element { .. } | Content::Document => {
120 nodes = self
122 .children(node)
123 .chain(nodes.into_iter())
124 .collect::<Vec<Handle>>()
125 .into()
126 }
127
128 Content::Text { text } => s.push_slice(text.as_str()),
130 }
131 }
132 s
133 }
134}
135
136#[derive(Debug)]
137
138pub struct ParentIter<'a> {
139 adept: Option<Handle>,
140 doc: &'a Hatmel,
141}
142impl<'a> ParentIter<'a> {
143 fn new(doc: &'a Hatmel, adept: Handle) -> Self {
144 Self {
145 doc,
146 adept: Some(adept),
147 }
148 }
149}
150impl<'a> Iterator for ParentIter<'a> {
151 type Item = Handle;
152
153 fn next(&mut self) -> Option<Self::Item> {
154 if let Some(adept) = self.adept {
155 self.adept = self.doc.parent(adept);
156 }
157 self.adept
158 }
159}
160
161#[derive(Debug, Default, Clone)]
162pub struct HandleIter<'a> {
163 curr: Arc<AtomicUsize>,
164 end: Handle,
165 phantom: PhantomData<Cow<'a, ()>>,
167}
168impl<'a> HandleIter<'a> {
169 pub(crate) fn new(range: std::ops::Range<usize>) -> Self {
170 Self {
171 curr: Arc::new(AtomicUsize::new(range.start)),
172 end: range.end,
173 phantom: PhantomData,
174 }
175 }
176}
177impl<'a> Iterator for HandleIter<'a> {
178 type Item = Handle;
179
180 fn next(&mut self) -> Option<Self::Item> {
181 if self.curr.load(std::sync::atomic::Ordering::SeqCst) >= self.end {
182 return None;
183 }
184 let next = self
185 .curr
186 .as_ref()
187 .fetch_add(1, std::sync::atomic::Ordering::SeqCst);
188 if next >= self.end {
189 return None;
190 }
191 Some(next)
192 }
193}