node_html_parser/dom/element/
tree.rs1use super::content::collect_items;
2use super::content::parse_fragment;
3use super::main::HTMLElement;
4use crate::dom::node::{CowStr, Node, NodeOrStr};
5
6impl HTMLElement {
7 pub fn before_nodes(&mut self, mut nodes: Vec<Node>) {
10 let parent_ptr = match self.parent {
11 Some(p) => p,
12 None => return,
13 };
14 unsafe {
15 let parent = &mut *parent_ptr;
16 let idx = match self.index_in_parent() {
17 Some(i) => i,
18 None => return,
19 };
20 for n in nodes.iter_mut() {
21 Self::detach_node(n);
22 }
23 for (i, mut n) in nodes.into_iter().enumerate() {
24 if let Node::Element(ref mut e) = n {
25 e.parent = Some(parent_ptr);
26 }
27 parent.children.insert(idx + i, n);
28 }
29 }
30 }
31
32 pub fn next_element_sibling(&self) -> Option<&HTMLElement> {
34 let parent = self.parent()?;
35 let mut seen = false;
36 let self_ptr = self as *const HTMLElement;
37 for child in &parent.children {
38 if let Node::Element(e) = child {
39 let ptr: *const HTMLElement = &**e;
40 if seen {
41 return Some(e);
42 }
43 if ptr == self_ptr {
44 seen = true;
45 }
46 }
47 }
48 None
49 }
50 pub fn previous_element_sibling(&self) -> Option<&HTMLElement> {
52 let parent = self.parent()?;
53 let self_ptr = self as *const HTMLElement;
54 let mut prev: Option<&HTMLElement> = None;
55 for child in &parent.children {
56 if let Node::Element(e) = child {
57 let ptr: *const HTMLElement = &**e;
58 if ptr == self_ptr {
59 return prev;
60 }
61 prev = Some(e);
62 }
63 }
64 None
65 }
66
67 pub(super) fn index_in_parent(&self) -> Option<usize> {
68 let parent = self.parent()?;
69 let self_ptr = self as *const HTMLElement;
70 for (i, child) in parent.children.iter().enumerate() {
71 if let Node::Element(e) = child {
72 let ptr: *const HTMLElement = &**e;
73 if ptr == self_ptr {
74 return Some(i);
75 }
76 }
77 }
78 None
79 }
80
81 pub fn next_sibling(&self) -> Option<&Node> {
83 let parent = self.parent()?;
84 let idx = self.index_in_parent()?;
85 parent.children.get(idx + 1)
86 }
87 pub fn previous_sibling(&self) -> Option<&Node> {
89 let parent = self.parent()?;
90 let idx = self.index_in_parent()?;
91 if idx == 0 {
92 return None;
93 }
94 parent.children.get(idx - 1)
95 }
96 pub fn after_nodes(&mut self, mut nodes: Vec<Node>) {
98 let parent_ptr = match self.parent {
99 Some(p) => p,
100 None => return,
101 };
102 unsafe {
103 let parent = &mut *parent_ptr;
104 let idx = match self.index_in_parent() {
105 Some(i) => i,
106 None => return,
107 } + 1;
108 for n in nodes.iter_mut() {
109 Self::detach_node(n);
110 }
111 for (i, mut n) in nodes.into_iter().enumerate() {
112 if let Node::Element(ref mut e) = n {
113 e.parent = Some(parent_ptr);
114 }
115 parent.children.insert(idx + i, n);
116 }
117 }
118 }
119
120 pub fn prepend_nodes(&mut self, mut nodes: Vec<Node>) {
122 for n in nodes.iter_mut() {
123 Self::detach_node(n);
124 }
125 let self_ptr: *mut HTMLElement = self as *mut HTMLElement;
126 for n in nodes.iter_mut() {
127 if let Node::Element(e) = n {
128 e.parent = Some(self_ptr);
129 }
130 }
131 for (i, n) in nodes.into_iter().enumerate() {
132 self.children.insert(i, n);
133 }
134 }
135
136 pub fn append_nodes(&mut self, mut nodes: Vec<Node>) {
138 for n in nodes.iter_mut() {
139 Self::detach_node(n);
140 }
141 let self_ptr: *mut HTMLElement = self as *mut HTMLElement;
142 for mut n in nodes.into_iter() {
143 if let Node::Element(ref mut e) = n {
144 e.parent = Some(self_ptr);
145 }
146 self.children.push(n);
147 }
148 }
149
150 fn detach_node(node: &mut Node) {
151 match node {
152 Node::Element(e) => {
153 if let Some(parent_ptr) = e.parent {
154 unsafe {
155 let parent = &mut *parent_ptr;
156 let elem_ptr: *const HTMLElement = &**e;
157 parent.children.retain(|c| {
158 if let Node::Element(pe) = c {
159 (&**pe) as *const HTMLElement != elem_ptr
160 } else {
161 true
162 }
163 });
164 }
165 e.parent = None;
166 }
167 }
168 Node::Text(_) | Node::Comment(_) => { }
169 }
170 }
171
172 pub(super) fn insert_children_at(&mut self, index: usize, html: &str) {
174 let mut nodes = parse_fragment(html);
175 let self_ptr: *mut HTMLElement = self as *mut HTMLElement;
176 for n in nodes.iter_mut() {
177 if let Node::Element(e) = n {
178 e.parent = Some(self_ptr);
179 }
180 }
181 for (i, n) in nodes.into_iter().enumerate() {
182 self.children.insert(index + i, n);
183 }
184 }
185
186 pub(super) fn insert_as_sibling(&mut self, html: &str, after: bool) {
188 let parent_ptr = match self.parent {
189 Some(p) => p,
190 None => return,
191 };
192 unsafe {
193 let parent = &mut *parent_ptr;
194 let idx = match self.index_in_parent() {
195 Some(i) => i,
196 None => return,
197 };
198 let mut nodes = parse_fragment(html);
199 for n in nodes.iter_mut() {
200 if let Node::Element(e) = n {
201 e.parent = Some(parent_ptr);
202 }
203 }
204 let insert_pos = if after { idx + 1 } else { idx };
205 for (i, n) in nodes.into_iter().enumerate() {
206 parent.children.insert(insert_pos + i, n);
207 }
208 }
209 }
210
211 pub fn remove(&mut self) {
213 let parent_ptr = match self.parent {
214 Some(p) => p,
215 None => return,
216 };
217 unsafe {
218 let parent = &mut *parent_ptr;
219 let self_ptr = self as *const HTMLElement;
220 parent.children.retain(|n| {
221 if let Node::Element(e) = n {
222 let ptr: *const HTMLElement = &**e;
223 ptr != self_ptr
224 } else {
225 true
226 }
227 });
228 }
229 }
230 pub fn before(&mut self, html_fragment: &str) {
232 self.before_items(&[NodeOrStr::Str(CowStr(html_fragment))]);
233 }
234 pub fn before_items(&mut self, items: &[NodeOrStr]) {
235 self.insert_sibling_items(items, false);
236 }
237 pub fn after(&mut self, html_fragment: &str) {
239 self.after_items(&[NodeOrStr::Str(CowStr(html_fragment))]);
240 }
241 pub fn after_items(&mut self, items: &[NodeOrStr]) {
242 self.insert_sibling_items(items, true);
243 }
244 pub fn closest_in<'a>(
246 &'a self,
247 root: &'a HTMLElement,
248 selector: &str,
249 ) -> Option<&'a HTMLElement> {
250 if self.matches_selector(root, selector) {
252 return Some(self);
253 }
254 let target_ptr = self as *const HTMLElement;
256 let mut stack: Vec<&HTMLElement> = Vec::new();
257 fn dfs<'b>(
258 cur: &'b HTMLElement,
259 target: *const HTMLElement,
260 path: &mut Vec<&'b HTMLElement>,
261 ) -> bool {
262 path.push(cur);
263 let cur_ptr = cur as *const HTMLElement;
264 if cur_ptr == target {
265 return true;
266 }
267 for child in cur.children.iter() {
268 if let Node::Element(e) = child {
269 if dfs(e, target, path) {
270 return true;
271 }
272 }
273 }
274 path.pop();
275 false
276 }
277 if !dfs(root, target_ptr, &mut stack) {
278 return None;
279 }
280 for ancestor in stack[..stack.len() - 1].iter().rev() {
282 if ancestor.matches_selector(root, selector) {
283 return Some(ancestor);
284 }
285 }
286 None
287 }
288 pub fn prepend_child(&mut self, node: Node) {
289 let mut n = node;
290 if let Node::Element(ref mut e) = n {
291 let self_ptr: *mut HTMLElement = self as *mut HTMLElement;
292 e.parent = Some(self_ptr);
293 }
294 self.children.insert(0, n);
295 }
296 pub fn append_child_element(&mut self, child: HTMLElement) -> &mut HTMLElement {
298 let mut boxed = Box::new(child);
299 let self_ptr: *mut HTMLElement = self as *mut HTMLElement;
300 boxed.parent = Some(self_ptr);
301 self.children.push(Node::Element(boxed));
302 match self.children.last_mut().unwrap() {
303 Node::Element(ref mut e) => e,
304 _ => unreachable!(),
305 }
306 }
307 pub fn append_child_text(&mut self, text: &str) {
309 use crate::dom::text::TextNode;
310 self.children
311 .push(Node::Text(TextNode::new(text.to_string())));
312 }
313 pub fn remove_children_where<F: FnMut(&Node) -> bool>(&mut self, mut f: F) {
314 self.children.retain(|n| !f(n));
315 }
316
317 pub fn set_content_node(&mut self, node: Node) {
320 self.set_content_nodes(vec![node]);
321 }
322 pub fn append(&mut self, html_fragment: &str) {
324 self.append_items(&[NodeOrStr::Str(CowStr(html_fragment))]);
325 }
326 pub fn prepend(&mut self, html_fragment: &str) {
327 self.prepend_items(&[NodeOrStr::Str(CowStr(html_fragment))]);
328 }
329 pub fn append_items(&mut self, items: &[NodeOrStr]) {
330 let nodes = collect_items(items);
331 self.adopt_vec(nodes, None);
332 }
333 pub fn prepend_items(&mut self, items: &[NodeOrStr]) {
334 let nodes = collect_items(items);
335 self.adopt_vec(nodes, Some(0));
336 }
337 pub(super) fn insert_sibling_items(&mut self, items: &[NodeOrStr], after: bool) {
338 let parent_ptr = match self.parent {
339 Some(p) => p,
340 None => return,
341 };
342 unsafe {
343 let parent = &mut *parent_ptr;
344 let idx = match self.index_in_parent() {
345 Some(i) => i,
346 None => return,
347 };
348 let mut nodes = collect_items(items);
349 for n in nodes.iter_mut() {
350 if let Node::Element(e) = n {
351 e.parent = Some(parent_ptr);
352 }
353 }
354 let insert_pos = if after { idx + 1 } else { idx };
355 for (i, n) in nodes.into_iter().enumerate() {
356 parent.children.insert(insert_pos + i, n);
357 }
358 }
359 }
360
361 fn adopt_vec(&mut self, mut nodes: Vec<Node>, at: Option<usize>) {
362 let self_ptr: *mut HTMLElement = self as *mut HTMLElement;
363 for n in nodes.iter_mut() {
364 if let Node::Element(e) = n {
365 e.parent = Some(self_ptr);
366 }
367 }
368 match at {
369 Some(pos) => {
370 for (i, n) in nodes.into_iter().enumerate() {
371 self.children.insert(pos + i, n);
372 }
373 }
374 None => self.children.extend(nodes),
375 }
376 }
377 pub fn next_element_sibling_in<'a>(&'a self, root: &'a HTMLElement) -> Option<&'a HTMLElement> {
379 let target = self as *const HTMLElement;
380 fn find_parent<'b>(
382 cur: &'b HTMLElement,
383 target: *const HTMLElement,
384 ) -> Option<&'b HTMLElement> {
385 for child in &cur.children {
386 if let Node::Element(e) = child {
387 let ptr: *const HTMLElement = &**e;
388 if ptr == target {
389 return Some(cur);
390 }
391 if let Some(p) = find_parent(&**e, target) {
392 return Some(p);
393 }
394 }
395 }
396 None
397 }
398 let parent = find_parent(root, target)?;
399 let mut seen = false;
400 for child in &parent.children {
401 if let Node::Element(e) = child {
402 let ptr: *const HTMLElement = &**e;
403 if seen {
404 return Some(&**e);
405 }
406 if ptr == target {
407 seen = true;
408 }
409 }
410 }
411 None
412 }
413
414 pub fn previous_element_sibling_in<'a>(
416 &'a self,
417 root: &'a HTMLElement,
418 ) -> Option<&'a HTMLElement> {
419 let target = self as *const HTMLElement;
420 fn find_parent<'b>(
421 cur: &'b HTMLElement,
422 target: *const HTMLElement,
423 ) -> Option<&'b HTMLElement> {
424 for child in &cur.children {
425 if let Node::Element(e) = child {
426 let ptr: *const HTMLElement = &**e;
427 if ptr == target {
428 return Some(cur);
429 }
430 if let Some(p) = find_parent(&**e, target) {
431 return Some(p);
432 }
433 }
434 }
435 None
436 }
437 let parent = find_parent(root, target)?;
438 let mut prev: Option<&HTMLElement> = None;
439 for child in &parent.children {
440 if let Node::Element(e) = child {
441 let ptr: *const HTMLElement = &**e;
442 if ptr == target {
443 return prev;
444 }
445 prev = Some(&**e);
446 }
447 }
448 None
449 }
450
451 pub fn append_child(&mut self, node: Node) {
452 let mut n = node;
453 match &mut n {
455 Node::Element(e) => {
456 if let Some(parent_ptr) = e.parent {
457 unsafe {
458 let parent = &mut *parent_ptr;
459 let elem_ptr: *const HTMLElement = &**e;
460 parent.children.retain(|c| {
461 if let Node::Element(pe) = c {
462 (&**pe) as *const HTMLElement != elem_ptr
463 } else { true }
464 });
465 }
466 e.parent = None; }
468 let self_ptr: *mut HTMLElement = self as *mut HTMLElement;
469 e.parent = Some(self_ptr);
470 },
471 Node::Text(_) | Node::Comment(_) => { }
472 }
473 self.children.push(n);
474 }
475 pub fn first_child(&self) -> Option<&Node> {
476 self.children.first()
477 }
478
479 pub fn last_child(&self) -> Option<&Node> {
480 self.children.last()
481 }
482
483 pub fn first_element_child(&self) -> Option<&HTMLElement> {
484 for c in &self.children {
485 if let Node::Element(e) = c {
486 return Some(e);
487 }
488 }
489 None
490 }
491 pub fn last_element_child(&self) -> Option<&HTMLElement> {
492 for c in self.children.iter().rev() {
493 if let Node::Element(e) = c {
494 return Some(e);
495 }
496 }
497 None
498 }
499 pub fn first_element_child_mut(&mut self) -> Option<&mut HTMLElement> {
500 for child in self.children.iter_mut() {
501 if let Node::Element(e) = child {
502 return Some(e);
503 }
504 }
505 None
506 }
507
508 pub fn parent(&self) -> Option<&HTMLElement> {
510 self.parent.map(|p| unsafe { &*p })
511 }
512 pub fn children_elements(&self) -> Vec<&HTMLElement> {
513 self.children
514 .iter()
515 .filter_map(|c| {
516 if let Node::Element(e) = c {
517 Some(&**e)
518 } else {
519 None
520 }
521 })
522 .collect()
523 }
524 pub fn child_element_count(&self) -> usize {
525 self.children
526 .iter()
527 .filter(|c| matches!(c, Node::Element(_)))
528 .count()
529 }
530}