pochoir_parser/tree/
tree_ref.rs

1use pochoir_common::Spanned;
2use pochoir_template_engine::{Escaping, TemplateBlock};
3use selectors::{
4    context::{MatchingForInvalidation, NeedsSelectorFlags, SelectorCaches},
5    matching,
6    parser::SelectorList,
7};
8use std::{borrow::Cow, fmt};
9
10use super::{build_selector_list, selection::InnerSelector, Tree, TreeNode, TreeRefId};
11use crate::{Error, Node, OwnedTree, ParsedNode, Result};
12
13/// A reference to a node in the tree.
14#[derive(Clone, Copy)]
15pub struct TreeRef<'a, 'b> {
16    /// A unique ID identifying the node in the tree.
17    pub id: TreeRefId,
18
19    /// The tree owning this node.
20    pub tree: &'b Tree<'a>,
21}
22
23impl<'a, 'b> TreeRef<'a, 'b> {
24    #[allow(clippy::panic)]
25    fn inner(&self) -> &TreeNode<'a> {
26        self.tree.nodes.get(&self.id).unwrap_or_else(|| {
27            panic!(
28                "failed to find the current node (id {:?}) in the tree",
29                self.id
30            )
31        })
32    }
33
34    pub fn id(&self) -> TreeRefId {
35        self.id
36    }
37
38    /// Get an immutable reference to the underlying [`ParsedNode`] containing the [`Node`] and the
39    /// location of the span of text where it was defined.
40    ///
41    /// # Panics
42    ///
43    /// Panics if the node does not exist in the tree (it could have been removed).
44    pub fn spanned_data(&self) -> &ParsedNode<'a> {
45        &self.inner().data
46    }
47
48    /// Get an immutable reference to the underlying [`Node`].
49    ///
50    /// # Panics
51    ///
52    /// Panics if the node does not exist in the tree (it could have been removed).
53    pub fn data(&self) -> &Node<'a> {
54        &self.inner().data
55    }
56
57    /// Get a reference to the parent of this node.
58    #[must_use]
59    pub fn parent(&self) -> Self {
60        Self {
61            id: self.inner().parent,
62            tree: self.tree,
63        }
64    }
65
66    /// Search all parents of the node until it finds a node matching the provided CSS selector.
67    ///
68    /// Returns `None` if the selector is invalid or if a node matching the selector could not be
69    /// found.
70    ///
71    /// This method is equivalent to the [`Element.closest`](https://developer.mozilla.org/en-US/docs/Web/API/Element/closest) method in Javascript.
72    pub fn closest(&self, selector: &str) -> Option<Self> {
73        let mut tree_ref = *self;
74        let selector_list = build_selector_list(selector).ok()?;
75
76        loop {
77            if tree_ref.is_matching(&selector_list) {
78                return Some(tree_ref);
79            } else if tree_ref.id == TreeRefId::Root {
80                return None;
81            }
82
83            tree_ref = tree_ref.parent();
84        }
85    }
86
87    /// Get a reference to the previous sibling of this node.
88    pub fn prev_sibling(&self) -> Option<Self> {
89        let parent = self.parent();
90        let mut children = parent.children().peekable();
91
92        let mut id = None;
93        while let Some(c) = children.next() {
94            if children.peek().is_some_and(|c| c.id == self.id) {
95                id = Some(c.id);
96                break;
97            }
98        }
99
100        id.map(|id| Self {
101            id,
102            tree: self.tree,
103        })
104    }
105
106    /// Get a reference to the next sibling of this node.
107    pub fn next_sibling(&self) -> Option<Self> {
108        let parent = self.parent();
109        let mut children = parent.children().peekable();
110
111        let mut id = None;
112        while let Some(c) = children.next() {
113            if c.id == self.id {
114                id = children.peek().map(|c| c.id);
115                break;
116            }
117        }
118
119        id.map(|id| Self {
120            id,
121            tree: self.tree,
122        })
123    }
124
125    /// Get a list of references of the children of this node.
126    pub fn children<'c>(&'c self) -> impl Iterator<Item = TreeRef<'a, 'b>> + 'c {
127        self.inner().children.iter().map(|id| self.tree.get(*id))
128    }
129
130    /// Get a cloned list of IDs of this node children.
131    pub fn children_id(&self) -> Vec<TreeRefId> {
132        self.inner().children.clone()
133    }
134
135    /// Search the first node matching the CSS selector in the tree, relatively to this node.
136    ///
137    /// The traversal order used is the same as in the [official DOM specification](https://dom.spec.whatwg.org/#concept-tree-order)
138    /// ie preorder, depth-first.
139    ///
140    /// It is similar to the `document.querySelector` function in JavaScript.
141    ///
142    /// # Errors
143    ///
144    /// Returns [`selectors::parser::SelectorParseError`] if the CSS selector is not a valid CSS selector
145    /// or `Ok(None)` if no node matching the CSS selector is found in the tree
146    pub fn select<'c>(
147        &self,
148        selector: &'c str,
149    ) -> std::result::Result<Option<TreeRef<'_, '_>>, crate::error::SelectorParseError<'c>> {
150        let selector_list = build_selector_list(selector)?;
151        Ok(self
152            .traverse_depth()
153            .find(|tree_ref| tree_ref.is_matching(&selector_list)))
154    }
155
156    /// Select several nodes in the tree, relatively to this node, using a CSS selector.
157    ///
158    /// It is similar to the `document.querySelectorAll` function in JavaScript.
159    ///
160    /// Returns an empty `Vec` if the selector is not a valid CSS selector.
161    pub fn select_all(&self, selector: &str) -> Vec<TreeRef<'_, '_>> {
162        if let Ok(selector_list) = build_selector_list(selector) {
163            self.traverse_depth()
164                .filter(|tree_ref| tree_ref.is_matching(&selector_list))
165                .collect()
166        } else {
167            vec![]
168        }
169    }
170
171    /// Get the element name of the [`TreeRef`].
172    ///
173    /// # Errors
174    ///
175    /// Returns [`Error::BadNodeType`] if the underlying node is not a [`Node::Element`].
176    ///
177    /// [`Node::Element`]: crate::Node::Element
178    pub fn name(&self) -> Result<Cow<'a, str>> {
179        if let Node::Element(ref name, _) = self.data() {
180            Ok(name.clone())
181        } else {
182            Err(Spanned::new(Error::BadNodeType {
183                expected: "Element",
184                found: self.data().node_type(),
185            }))
186        }
187    }
188
189    /// Get the text of the [`TreeRef`].
190    ///
191    /// Returns the concatenated text content of child nodes if it is a [`Node::Element`].
192    ///
193    /// Returns the text content if it is a [`Node::TemplateBlock(TemplateBlock::RawText(_))`](`Node::TemplateBlock`).
194    ///
195    /// All template expressions and statements just return their raw content with no spaces inside
196    /// their delimiters (will return `{{expr}}` even if it was `{{ expr }}`, `{!expr!}` event if
197    /// it was `{! expr !}` and `{%stmt%}` even if it was `{% stmt %}`).
198    ///
199    /// [`Node::Element`]: crate::Node::Element
200    /// [`Node::Text`]: crate::Node::Text
201    pub fn text(&self) -> Cow<'a, str> {
202        match self.data() {
203            Node::Element(_, _) => {
204                let children = self.children();
205                Cow::Owned(children.into_iter().map(|child| child.text()).collect())
206            }
207            Node::TemplateBlock(block) => Cow::Owned(match block {
208                TemplateBlock::RawText(t) => t.to_string(),
209                TemplateBlock::Expr(t, is_escaped) => {
210                    if *is_escaped {
211                        format!("{{{{{t}}}}}")
212                    } else {
213                        format!("{{!{t}!}}")
214                    }
215                }
216                TemplateBlock::Stmt(t) => format!("{{%{t}%}}"),
217            }),
218            _ => Cow::Borrowed(""),
219        }
220    }
221
222    /// Get the value of an attribute belonging to a [`Node::Element`].
223    ///
224    /// All template expressions and statements just return their raw content with no spaces inside
225    /// their delimiters (will return `{{expr}}` even if it was `{{ expr }}`, `{!expr!}` event if
226    /// it was `{! expr !}` and `{%stmt%}` even if it was `{% stmt %}`).
227    ///
228    /// # Errors
229    ///
230    /// Returns [`Error::BadNodeType`] if the underlying node is not a [`Node::Element`].
231    ///
232    /// Returns `None` if the attribute is not present.
233    ///
234    /// Returns `Some("")` if the attribute is present but does not have a value (e.g. in `<input
235    /// type="checkbox" checked>`, the `checked` HTML attribute is present but does not have a value).
236    ///
237    /// Returns `Some(value)` if the attribute is present and does have a value.
238    pub fn attr(&self, name: &str) -> Result<Option<String>> {
239        if let Node::Element(_, ref attrs) = self.data() {
240            Ok(attrs.get(Cow::Borrowed(name)).map(|a| {
241                a.iter()
242                    .map(|b| match &**b {
243                        TemplateBlock::RawText(t) => t.to_string(),
244                        TemplateBlock::Expr(t, is_escaped) => {
245                            if *is_escaped {
246                                format!("{{{{{t}}}}}")
247                            } else {
248                                format!("{{!{t}!}}")
249                            }
250                        }
251                        TemplateBlock::Stmt(t) => format!("{{%{t}%}}"),
252                    })
253                    .collect::<String>()
254            }))
255        } else {
256            Err(Spanned::new(Error::BadNodeType {
257                expected: "Element",
258                found: self.data().node_type(),
259            }))
260        }
261    }
262
263    /// Get the value of an attribute belonging to a [`Node::Element`].
264    ///
265    /// Template expressions and statements can be returned.
266    ///
267    /// # Errors
268    ///
269    /// Returns [`Error::BadNodeType`] if the underlying node is not a [`Node::Element`].
270    ///
271    /// Returns `None` if the attribute is not present.
272    pub fn attr_spanned(&self, name: &str) -> Result<Option<Vec<Spanned<TemplateBlock<'_>>>>> {
273        if let Node::Element(_, ref attrs) = self.data() {
274            Ok(attrs.get(Cow::Borrowed(name)).cloned())
275        } else {
276            Err(Spanned::new(Error::BadNodeType {
277                expected: "Element",
278                found: self.data().node_type(),
279            }))
280        }
281    }
282
283    /// Get all attributes belonging to a [`Node::Element`].
284    ///
285    /// All template expressions and statements just return their raw content with no spaces inside
286    /// their delimiters (will return `{{expr}}` even if it was `{{ expr }}`, `{!expr!}` event if
287    /// it was `{! expr !}` and `{%stmt%}` even if it was `{% stmt %}`).
288    ///
289    /// An empty attribute value means that an attribute key was given without a value. See
290    /// [`TreeRef::attr`] for more information.
291    ///
292    /// # Errors
293    ///
294    /// Returns [`Error::BadNodeType`] if the underlying node is not a [`Node::Element`].
295    pub fn attrs(&self) -> Result<impl Iterator<Item = (&Cow<'_, str>, String)>> {
296        if let Node::Element(_, ref attrs) = self.data() {
297            Ok(attrs.iter().map(|(k, v)| {
298                (
299                    &**k,
300                    v.iter()
301                        .map(|b| match &**b {
302                            TemplateBlock::RawText(t) => t.to_string(),
303                            TemplateBlock::Expr(t, is_escaped) => {
304                                if *is_escaped {
305                                    format!("{{{{{t}}}}}")
306                                } else {
307                                    format!("{{!{t}!}}")
308                                }
309                            }
310                            TemplateBlock::Stmt(t) => format!("{{%{t}%}}"),
311                        })
312                        .collect::<String>(),
313                )
314            }))
315        } else {
316            Err(Spanned::new(Error::BadNodeType {
317                expected: "Element",
318                found: self.data().node_type(),
319            }))
320        }
321    }
322
323    /// Get all attributes belonging to a [`Node::Element`].
324    ///
325    /// Template expressions and statements can be returned.
326    ///
327    /// # Errors
328    ///
329    /// Returns [`Error::BadNodeType`] if the underlying node is not a [`Node::Element`].
330    pub fn attrs_spanned(&self) -> Result<impl Iterator<Item = &crate::Attr<'_>>> {
331        if let Node::Element(_, ref attrs) = self.data() {
332            Ok(attrs.iter())
333        } else {
334            Err(Spanned::new(Error::BadNodeType {
335                expected: "Element",
336                found: self.data().node_type(),
337            }))
338        }
339    }
340
341    pub fn sub_tree(&self) -> Tree<'a> {
342        let mut tree = Tree::new(self.tree.file_path());
343
344        // Prevent any ID collision
345        tree.next_id = self.tree.next_id;
346
347        for tree_ref in self.traverse_depth() {
348            let parent_id = if tree_ref.parent().id() == self.id() {
349                TreeRefId::Root
350            } else {
351                tree_ref.parent().id()
352            };
353
354            tree.insert_with_id(
355                tree_ref.id(),
356                parent_id,
357                tree_ref.children_id(),
358                tree_ref.spanned_data().clone(),
359            );
360
361            if parent_id == TreeRefId::Root {
362                tree.get_mut(TreeRefId::Root)
363                    .inner_mut()
364                    .children
365                    .push(tree_ref.id());
366            }
367        }
368        tree
369    }
370
371    pub fn traverse_breadth(&self) -> impl Iterator<Item = TreeRef<'a, '_>> {
372        let parent = self.tree.get(self.id);
373
374        super::traverse::TraverseBreadthIter {
375            children: parent.children().collect(),
376            index: 0,
377        }
378    }
379
380    pub fn traverse_depth(&self) -> impl Iterator<Item = TreeRef<'a, '_>> {
381        let mut queue: Vec<TreeRef> = self.tree.get(self.id).children().collect();
382        queue.reverse();
383
384        super::traverse::TraverseDepthIter { queue }
385    }
386
387    pub fn is_matching(&self, selector_list: &SelectorList<InnerSelector>) -> bool {
388        let mut nth_index_cache = SelectorCaches::default();
389        let mut ctx = matching::MatchingContext::new(
390            matching::MatchingMode::Normal,
391            None,
392            &mut nth_index_cache,
393            matching::QuirksMode::NoQuirks,
394            NeedsSelectorFlags::No,
395            MatchingForInvalidation::No,
396        );
397
398        matching::matches_selector_list(selector_list, self, &mut ctx)
399    }
400}
401
402impl PartialEq for TreeRef<'_, '_> {
403    fn eq(&self, other: &Self) -> bool {
404        self.id == other.id
405    }
406}
407
408impl fmt::Debug for TreeRef<'_, '_> {
409    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
410        f.debug_struct("TreeRef")
411            .field("id", &self.id)
412            .field("__inner_node", &self.data())
413            .finish()
414    }
415}
416
417/// A mutable reference to a node in the tree.
418pub struct TreeRefMut<'a, 'b> {
419    /// A unique ID identifying the node in the tree.
420    pub id: TreeRefId,
421
422    /// The tree owning this node.
423    pub tree: &'b mut Tree<'a>,
424}
425
426impl<'a, 'b> TreeRefMut<'a, 'b> {
427    #[allow(clippy::panic)]
428    fn inner(&self) -> &TreeNode<'a> {
429        self.tree.nodes.get(&self.id).unwrap_or_else(|| {
430            panic!(
431                "failed to find the current node (id {:?}) in the tree (mutable)",
432                self.id
433            )
434        })
435    }
436
437    #[allow(clippy::panic)]
438    fn inner_mut(&mut self) -> &mut TreeNode<'a> {
439        self.tree.nodes.get_mut(&self.id).unwrap_or_else(|| {
440            panic!(
441                "failed to find the current node (id {:?}) in the tree (mutable)",
442                self.id
443            )
444        })
445    }
446
447    pub fn id(&self) -> TreeRefId {
448        self.id
449    }
450
451    pub fn as_ref(&self) -> TreeRef<'a, '_> {
452        TreeRef {
453            id: self.id,
454            tree: self.tree,
455        }
456    }
457
458    /// Get a mutable reference to the underlying [`Node`].
459    ///
460    /// # Panics
461    ///
462    /// Panics if the node does not exist in the tree (it could have been removed).
463    pub fn data(&mut self) -> &mut Node<'a> {
464        &mut self.inner_mut().data
465    }
466
467    /// Get an mutable reference to the underlying [`ParsedNode`] containing the [`Node`] and the
468    /// location of the span of text where it was defined.
469    ///
470    /// # Panics
471    ///
472    /// Panics if the node does not exist in the tree (it could have been removed).
473    pub fn spanned_data(&mut self) -> &mut ParsedNode<'a> {
474        &mut self.inner_mut().data
475    }
476
477    /// Get a reference to the parent of this node.
478    pub fn parent(&mut self) -> TreeRefMut<'a, '_> {
479        TreeRefMut {
480            id: self.inner().parent,
481            tree: self.tree,
482        }
483    }
484
485    /// Get a reference to the previous sibling of this node.
486    pub fn prev_sibling(&'b mut self) -> Option<Self> {
487        let parent = self.as_ref().parent();
488        let mut children = parent.children().peekable();
489
490        let mut id = None;
491        while let Some(c) = children.next() {
492            if children.peek().is_some_and(|c| c.id == self.id) {
493                id = Some(c.id);
494                break;
495            }
496        }
497
498        drop(children);
499        id.map(|id| Self {
500            id,
501            tree: self.tree,
502        })
503    }
504
505    /// Get a reference to the next sibling of this node.
506    pub fn next_sibling(&'b mut self) -> Option<Self> {
507        let parent = self.as_ref().parent();
508        let mut children = parent.children().peekable();
509
510        let mut id = None;
511        while let Some(c) = children.next() {
512            if c.id == self.id {
513                id = children.peek().map(|c| c.id);
514                break;
515            }
516        }
517
518        drop(children);
519        id.map(|id| Self {
520            id,
521            tree: self.tree,
522        })
523    }
524
525    /// Set the text of the [`TreeRef`] while escaping the content using the provided [`Escaping`]
526    /// variant (if you are lazy, you can use [`Escaping::default`] as a safe default).
527    ///
528    /// Replaces **all the children** with the provided text if it is a [`Node::Element`].
529    ///
530    /// Updates the text content if it is a [`Node::TemplateBlock(TemplateBlock::RawText(_))`](`Node::TemplateBlock`).
531    ///
532    /// Does nothing if the node is neither a [`Node::Element`] nor a [`Node::TemplateBlock(TemplateBlock::RawText(_))`](`Node::TemplateBlock`).
533    ///
534    /// [`Node::Element`]: crate::Node::Element
535    /// [`Node::Text`]: crate::Node::Text
536    pub fn set_text<T: Into<Cow<'a, str>>>(&mut self, new_text: T, escaping: Escaping) {
537        match self.as_ref().data() {
538            Node::Element(..) => {
539                // Remove all the children of this node
540                let children = self.as_ref().children_id();
541
542                for child in children {
543                    self.tree.get_mut(child).remove();
544                }
545
546                // Escape the text
547                let new_text_escaped = escaping.escape(new_text.into());
548
549                // Append a new text node and add it to the list of children
550                self.tree.insert(
551                    self.id,
552                    Spanned::new(Node::TemplateBlock(TemplateBlock::RawText(
553                        new_text_escaped,
554                    ))),
555                );
556            }
557            Node::TemplateBlock(_) => {
558                if let Node::TemplateBlock(TemplateBlock::RawText(ref mut t)) = self.data() {
559                    *t = new_text.into();
560                }
561            }
562            _ => (),
563        }
564    }
565
566    /// Set the value of an attribute belonging to a [`Node::Element`].
567    ///
568    /// The value of the attribute will be updated if it already exists or a new entry will be
569    /// inserted.
570    ///
571    /// The second argument should be `""` (an empty string) if the attribute has no value.
572    ///
573    /// This method does nothing if not called on a [`Node::Element`].
574    pub fn set_attr<A: Into<Cow<'a, str>>, B: Into<Cow<'a, str>>>(
575        &mut self,
576        key: A,
577        val: B,
578        escaping: Escaping,
579    ) {
580        if let Node::Element(_, ref mut attrs) = self.tree.get_mut(self.id).data() {
581            attrs.insert(
582                key.into(),
583                vec![Spanned::new(TemplateBlock::RawText(
584                    escaping.escape(val.into()),
585                ))],
586            );
587        }
588    }
589
590    /// Remove an attribute belonging to a [`Node::Element`].
591    ///
592    /// This method does nothing if the attribute key does not exist.
593    pub fn remove_attr<'c, A: Into<Cow<'c, str>>>(&mut self, key: A) {
594        if let Node::Element(_, ref mut attrs) = self.tree.get_mut(self.id).data() {
595            attrs.remove(key.into());
596        }
597    }
598
599    /// Replace the current [`Node`] with one or more [`Node`]s of a [`Tree`].
600    ///
601    /// This function consumes the [`TreeRefMut`] to avoid using a node that was removed.
602    ///
603    /// # Panics
604    ///
605    /// This function panics if the node is not found in its parent children. If it happens, it is
606    /// a bug in `pochoir-parser` not a bug in your code.
607    pub fn replace_node(self, tree: &Tree<'a>) {
608        // Get the index of the current node in its parent children
609        let current_index = self
610            .as_ref()
611            .parent()
612            .inner()
613            .children
614            .iter()
615            .position(|id| *id == self.id)
616            .expect("failed to find the node in its parent children");
617
618        let offset = self.tree.next_id();
619
620        // Remove the node and the reference of it in the parent list of children
621        let parent_id = self.as_ref().parent().id();
622
623        let mut inserted_nodes = 0;
624        let mut max_offset_node = offset;
625
626        for tree_ref in tree.traverse_depth() {
627            let is_root_node = tree_ref.parent().id() == TreeRefId::Root;
628            let children = tree_ref.children_id().iter().map(|c| *c + offset).collect();
629
630            self.tree.insert_with_id(
631                tree_ref.id + offset,
632                if is_root_node {
633                    parent_id
634                } else {
635                    tree_ref.parent().id() + offset
636                },
637                children,
638                tree_ref.spanned_data().clone(),
639            );
640
641            if tree_ref.id + offset > max_offset_node {
642                max_offset_node = tree_ref.id + offset;
643            }
644
645            if is_root_node {
646                self.tree
647                    .get_mut(parent_id)
648                    .inner_mut()
649                    .children
650                    .insert(current_index + inserted_nodes, tree_ref.id() + offset);
651
652                inserted_nodes += 1;
653            }
654        }
655
656        self.tree.next_id = max_offset_node + 1;
657
658        self.remove();
659    }
660
661    /// Prepend the [`Node`]s of a [`Tree`] to the list of children of the current node.
662    pub fn prepend_children(&mut self, tree: &Tree<'a>) {
663        let offset = self.tree.next_id();
664        let mut inserted_nodes = 0;
665        let mut max_offset_node = offset;
666
667        for tree_ref in tree.traverse_depth() {
668            let is_root_node = tree_ref.parent().id() == TreeRefId::Root;
669            let children = tree_ref.children_id().iter().map(|c| *c + offset).collect();
670
671            self.tree.insert_with_id(
672                tree_ref.id + offset,
673                if is_root_node {
674                    self.id()
675                } else {
676                    tree_ref.parent().id() + offset
677                },
678                children,
679                tree_ref.spanned_data().clone(),
680            );
681
682            if tree_ref.id + offset > max_offset_node {
683                max_offset_node = tree_ref.id + offset;
684            }
685
686            if is_root_node {
687                self.inner_mut()
688                    .children
689                    .insert(inserted_nodes, tree_ref.id() + offset);
690
691                inserted_nodes += 1;
692            }
693        }
694
695        self.tree.next_id = max_offset_node + 1;
696    }
697
698    /// Append the [`Node`]s of a [`Tree`] to the list of children of the current node.
699    pub fn append_children(&mut self, tree: &Tree<'a>) {
700        let offset = self.tree.next_id();
701        let mut max_offset_node = offset;
702
703        for tree_ref in tree.traverse_depth() {
704            let is_root_node = tree_ref.parent().id() == TreeRefId::Root;
705            let children = tree_ref.children_id().iter().map(|c| *c + offset).collect();
706
707            self.tree.insert_with_id(
708                tree_ref.id + offset,
709                if is_root_node {
710                    self.id()
711                } else {
712                    tree_ref.parent().id() + offset
713                },
714                children,
715                tree_ref.spanned_data().clone(),
716            );
717
718            if tree_ref.id + offset > max_offset_node {
719                max_offset_node = tree_ref.id + offset;
720            }
721
722            if is_root_node {
723                self.inner_mut().children.push(tree_ref.id() + offset);
724            }
725        }
726
727        self.tree.next_id = max_offset_node + 1;
728    }
729
730    /// Replace the current [`Node`] with one or more [`Node`]s of a [`OwnedTree`].
731    ///
732    /// This function consumes the [`TreeRefMut`] to avoid using a node that was removed.
733    ///
734    /// # Panics
735    ///
736    /// This function panics if the node is not found in its parent children. If it happens, it is
737    /// a bug in `pochoir-parser` not a bug in your code.
738    pub fn replace_node_owned(self, tree: &OwnedTree) {
739        // Get the index of the current node in its parent children
740        let current_index = self
741            .as_ref()
742            .parent()
743            .inner()
744            .children
745            .iter()
746            .position(|id| *id == self.id)
747            .expect("failed to find the node in its parent children");
748
749        let offset = self.tree.next_id();
750
751        // Remove the node and the reference of it in the parent list of children
752        let parent_id = self.as_ref().parent().id();
753
754        let mut inserted_nodes = 0;
755        let mut max_offset_node = offset;
756
757        for tree_ref in tree.get_tree().traverse_depth() {
758            let is_root_node = tree_ref.parent().id() == TreeRefId::Root;
759            let children = tree_ref.children_id().iter().map(|c| *c + offset).collect();
760
761            self.tree.insert_with_id(
762                tree_ref.id + offset,
763                if is_root_node {
764                    parent_id
765                } else {
766                    tree_ref.parent().id() + offset
767                },
768                children,
769                tree_ref
770                    .spanned_data()
771                    .clone()
772                    .map_spanned(Node::deep_clone),
773            );
774
775            if tree_ref.id + offset > max_offset_node {
776                max_offset_node = tree_ref.id + offset;
777            }
778
779            if is_root_node {
780                self.tree
781                    .get_mut(parent_id)
782                    .inner_mut()
783                    .children
784                    .insert(current_index + inserted_nodes, tree_ref.id() + offset);
785
786                inserted_nodes += 1;
787            }
788        }
789
790        self.tree.next_id = max_offset_node + 1;
791
792        self.remove();
793    }
794
795    /// Prepend the [`Node`]s of a [`OwnedTree`] to the list of children of the current node.
796    pub fn prepend_children_owned(&mut self, tree: &OwnedTree) {
797        let offset = self.tree.next_id();
798        let mut inserted_nodes = 0;
799        let mut max_offset_node = offset;
800
801        for tree_ref in tree.get_tree().traverse_depth() {
802            let is_root_node = tree_ref.parent().id() == TreeRefId::Root;
803            let children = tree_ref.children_id().iter().map(|c| *c + offset).collect();
804
805            self.tree.insert_with_id(
806                tree_ref.id + offset,
807                if is_root_node {
808                    self.id()
809                } else {
810                    tree_ref.parent().id() + offset
811                },
812                children,
813                tree_ref
814                    .spanned_data()
815                    .clone()
816                    .map_spanned(Node::deep_clone),
817            );
818
819            if tree_ref.id + offset > max_offset_node {
820                max_offset_node = tree_ref.id + offset;
821            }
822
823            if is_root_node {
824                self.inner_mut()
825                    .children
826                    .insert(inserted_nodes, tree_ref.id() + offset);
827
828                inserted_nodes += 1;
829            }
830        }
831
832        self.tree.next_id = max_offset_node + 1;
833    }
834
835    /// Append the [`Node`]s of a [`OwnedTree`] to the list of children of the current node.
836    pub fn append_children_owned(&mut self, tree: &OwnedTree) {
837        let offset = self.tree.next_id();
838        let mut max_offset_node = offset;
839
840        for tree_ref in tree.get_tree().traverse_depth() {
841            let is_root_node = tree_ref.parent().id() == TreeRefId::Root;
842            let children = tree_ref.children_id().iter().map(|c| *c + offset).collect();
843
844            self.tree.insert_with_id(
845                tree_ref.id + offset,
846                if is_root_node {
847                    self.id()
848                } else {
849                    tree_ref.parent().id() + offset
850                },
851                children,
852                tree_ref
853                    .spanned_data()
854                    .clone()
855                    .map_spanned(Node::deep_clone),
856            );
857
858            if tree_ref.id + offset > max_offset_node {
859                max_offset_node = tree_ref.id + offset;
860            }
861
862            if is_root_node {
863                self.inner_mut().children.push(tree_ref.id() + offset);
864            }
865        }
866
867        self.tree.next_id = max_offset_node + 1;
868    }
869
870    /// Replace the outer HTML of the [`TreeRefMut`].
871    ///
872    /// # Errors
873    ///
874    /// Returns an error if parsing the HTML failed.
875    pub fn replace_html<T: Into<Cow<'a, str>>>(self, file_path: &str, html: T) -> Result<()> {
876        let html = html.into();
877
878        if let Cow::Borrowed(html) = html {
879            let tree = crate::parse(file_path, html)?;
880            self.replace_node(&tree);
881        } else if let Cow::Owned(html) = html {
882            let tree = crate::parse_owned(file_path, &html)?;
883            self.replace_node_owned(&tree);
884        }
885        Ok(())
886    }
887
888    /// Prepend HTML as children of the current [`TreeRefMut`].
889    ///
890    /// # Errors
891    ///
892    /// Returns an error if parsing the HTML failed.
893    pub fn prepend_html<T: Into<Cow<'a, str>>>(&mut self, file_path: &str, html: T) -> Result<()> {
894        let html = html.into();
895
896        if let Cow::Borrowed(html) = html {
897            let tree = crate::parse(file_path, html)?;
898            self.prepend_children(&tree);
899        } else if let Cow::Owned(html) = html {
900            let tree = crate::parse_owned(file_path, &html)?;
901            self.prepend_children_owned(&tree);
902        }
903        Ok(())
904    }
905
906    /// Append HTML as children of the current [`TreeRefMut`].
907    ///
908    /// # Errors
909    ///
910    /// Returns an error if parsing the HTML failed.
911    pub fn append_html<T: Into<Cow<'a, str>>>(&mut self, file_path: &str, html: T) -> Result<()> {
912        let html = html.into();
913
914        if let Cow::Borrowed(html) = html {
915            let tree = crate::parse(file_path, html)?;
916            self.append_children(&tree);
917        } else if let Cow::Owned(html) = html {
918            let tree = crate::parse_owned(file_path, &html)?;
919            self.append_children_owned(&tree);
920        }
921
922        Ok(())
923    }
924
925    /// Remove the node from the tree.
926    ///
927    /// This function consumes the [`TreeRefMut`] to avoid using a node that was removed.
928    ///
929    /// # Panics
930    ///
931    /// This function panics if the node is not found in its parent children. If it happens, it is
932    /// a bug in `pochoir-parser` not a bug in your code.
933    pub fn remove(self) {
934        // Remove in parent
935        let node = &mut self.tree.get_mut(self.id);
936        let parent = &mut node.parent();
937        let parent_children = &mut parent.inner_mut().children;
938        let index = parent_children
939            .iter()
940            .position(|c| c == &self.id)
941            .expect("failed to find node in parent children");
942        parent_children.remove(index);
943
944        // Remove children
945        let node = self.tree.get(self.id);
946        let children = node.inner().children.clone();
947
948        for child in children {
949            self.tree.get_mut(child).remove();
950        }
951
952        // Remove from tree
953        self.tree.nodes.remove(&self.id);
954    }
955}
956
957impl PartialEq for TreeRefMut<'_, '_> {
958    fn eq(&self, other: &Self) -> bool {
959        self.id == other.id
960    }
961}
962
963impl fmt::Debug for TreeRefMut<'_, '_> {
964    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
965        f.debug_struct("TreeRefMut")
966            .field("id", &self.id)
967            .field("__inner_node", &self.as_ref().data())
968            .finish()
969    }
970}