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}