html_editor/operation/
edit.rs

1use super::Selector;
2use crate::{Element, Node};
3
4/// Insert and remove elements by [`Selector`], and trim the DOM.
5pub trait Editable {
6    /// Remove all empty text nodes from `self`.
7    ///
8    /// ```
9    /// use html_editor::parse;
10    /// use html_editor::operation::*;
11    ///
12    /// let html = r#"
13    ///     <!DOCTYPE html>
14    ///     <html>
15    ///         <head></head>
16    ///         <body></body>
17    ///     </html>"#;
18    ///
19    /// let html = parse(html).unwrap().trim().html();
20    /// assert_eq!(html, r#"<!DOCTYPE html><html><head></head><body></body></html>"#)
21    /// ```
22    fn trim(&mut self) -> &mut Self;
23
24    /// Insert `node` as the last child to all elements that matches the `selector`.
25    ///
26    /// ```
27    /// use html_editor::{parse, Node};
28    /// use html_editor::operation::*;
29    ///
30    /// let html = r#"<div><span>Ok</span></div>"#;
31    ///
32    /// let selector = Selector::from("div");
33    /// let html = parse(html)
34    ///     .unwrap()
35    ///     .insert_to(&selector, Node::new_element(
36    ///         "span",
37    ///         vec![],
38    ///         vec![Node::Text("Cancel".to_string())]
39    ///     ))
40    ///     .html();
41    ///
42    /// assert_eq!(html, r#"<div><span>Ok</span><span>Cancel</span></div>"#)
43    /// ```
44    fn insert_to(&mut self, selector: &Selector, target: Node) -> &mut Self;
45
46    /// Remove all elements that matches the `selector`.
47    ///
48    /// ```
49    /// use html_editor::parse;
50    /// use html_editor::operation::*;
51    ///
52    /// let html = r#"
53    /// <div>
54    ///     <div class="recommend"></div>
55    ///     <div class="results"></div>
56    ///     <div class="ad"></div>
57    /// </div>"#;
58    ///
59    /// let selector = Selector::from(".ad");
60    /// let html = parse(html).unwrap().remove_by(&selector).html();
61    ///
62    /// assert_eq!(html, r#"
63    /// <div>
64    ///     <div class="recommend"></div>
65    ///     <div class="results"></div>
66    ///    
67    /// </div>"#)
68    /// ```
69    fn remove_by(&mut self, selector: &Selector) -> &mut Self;
70
71    /// Replace all elements that matches the `selector` with new nodes.
72    ///
73    /// ```
74    /// use html_editor::{parse, Node, operation::*};
75    ///
76    /// let html = r#"
77    /// <div>
78    ///     <p>Hello</p>
79    /// </div>"#;
80    ///
81    /// let selector = Selector::from("p");
82    /// let html = parse(html)
83    ///     .unwrap()
84    ///     .replace_with(&selector, |p| {
85    ///         let new_text = format!("{} World!", p.children[0].html());
86    ///         Node::Comment(new_text)
87    ///     })
88    ///     .html();
89    ///
90    /// assert_eq!(html, r#"
91    /// <div>
92    ///     <!--Hello World!-->
93    /// </div>"#)
94    /// ```
95    fn replace_with(&mut self, selector: &Selector, f: fn(el: &Element) -> Node) -> &mut Self;
96}
97
98impl Editable for Vec<Node> {
99    fn trim(&mut self) -> &mut Self {
100        self.retain(|node| match node {
101            Node::Doctype(..) => true,
102            Node::Comment(..) => false,
103            Node::Text(text) => !text.trim().is_empty(),
104            Node::Element { .. } => true,
105        });
106        for node in self.iter_mut() {
107            if let Node::Element(el) = node {
108                el.children.trim();
109            }
110        }
111        self
112    }
113
114    fn insert_to(&mut self, selector: &Selector, target: Node) -> &mut Self {
115        for node in self.iter_mut() {
116            if let Node::Element(el) = node {
117                el.children.insert_to(selector, target.clone());
118                if selector.matches(&Element {
119                    name: el.name.clone(),
120                    attrs: el.attrs.clone(),
121                    children: vec![],
122                }) {
123                    el.children.push(target.clone());
124                }
125            }
126        }
127        self
128    }
129
130    fn remove_by(&mut self, selector: &Selector) -> &mut Self {
131        self.retain(|node| {
132            if let Node::Element(el) = node {
133                let element = Element {
134                    name: el.name.clone(),
135                    attrs: el.attrs.clone(),
136                    children: vec![],
137                };
138                return !selector.matches(&element);
139            }
140            true
141        });
142        for node in self.iter_mut() {
143            if let Node::Element(el) = node {
144                el.remove_by(selector);
145            }
146        }
147        self
148    }
149
150    fn replace_with(&mut self, selector: &Selector, f: fn(el: &Element) -> Node) -> &mut Self {
151        for node in self.iter_mut() {
152            if let Node::Element(ref mut el) = node {
153                if selector.matches(el) {
154                    *node = f(el);
155                } else {
156                    el.replace_with(selector, f);
157                }
158            }
159        }
160        self
161    }
162}
163
164impl Editable for Element {
165    fn trim(&mut self) -> &mut Self {
166        self.children.trim();
167        self
168    }
169
170    fn insert_to(&mut self, selector: &Selector, target: Node) -> &mut Self {
171        self.children.insert_to(selector, target.clone());
172        if selector.matches(self) {
173            self.children.push(target);
174        }
175        self
176    }
177
178    fn remove_by(&mut self, selector: &Selector) -> &mut Self {
179        self.children.remove_by(selector);
180        self
181    }
182
183    fn replace_with(&mut self, selector: &Selector, f: fn(el: &Element) -> Node) -> &mut Self {
184        self.children.replace_with(selector, f);
185        self
186    }
187}