node_html_parser/dom/element/
content.rs1use super::main::HTMLElement;
2use crate::dom::node::{CowStr, Node, NodeOrStr};
3use crate::dom::text::TextNode;
4
5impl HTMLElement {
6 pub fn insert_adjacent_html(&mut self, position: &str, html: &str) -> Result<(), String> {
12 let pos = position.to_lowercase();
13 match pos.as_str() {
14 "afterbegin" => self.insert_children_at(0, html),
15 "beforeend" => {
16 let len = self.children.len();
17 self.insert_children_at(len, html);
18 }
19 "beforebegin" => self.insert_as_sibling(html, false),
20 "afterend" => self.insert_as_sibling(html, true),
21 _ => {
22 return Err(format!(
23 "The value provided ('{}') is not one of 'beforebegin', 'afterbegin', 'beforeend', or 'afterend'",
24 position
25 ));
26 }
27 }
28 Ok(())
29 }
30
31 pub fn replace_with(&mut self, html_fragment: &str) {
33 self.replace_with_items(&[NodeOrStr::Str(CowStr(html_fragment))]);
34 }
35 pub fn replace_with_items(&mut self, items: &[NodeOrStr]) {
36 let parent_ptr = match self.parent {
37 Some(p) => p,
38 None => return,
39 };
40 unsafe {
41 let parent = &mut *parent_ptr;
42 let idx = match self.index_in_parent() {
43 Some(i) => i,
44 None => return,
45 };
46 let mut nodes = collect_items(items);
47 for n in nodes.iter_mut() {
48 if let Node::Element(e) = n {
49 e.parent = Some(parent_ptr);
50 }
51 }
52 parent.children.remove(idx);
54 for (i, n) in nodes.into_iter().enumerate() {
55 parent.children.insert(idx + i, n);
56 }
57 }
58 }
59
60 pub fn text(&self) -> String {
61 html_escape::decode_html_entities(&self.raw_text()).to_string()
62 }
63 pub fn inner_text(&self) -> String {
65 self.raw_text()
66 }
67 pub fn text_content(&self) -> String {
69 self.text()
70 }
71 pub fn set_text_content(&mut self, val: &str) {
73 self.children.clear();
75 self.children
76 .push(Node::Text(TextNode::new(val.to_string())));
77 }
78 pub fn set_content_str(&mut self, content: &str, comment_override: Option<bool>) {
79 let allow_comment = comment_override.unwrap_or(self.parse_comment);
80 let (mut nodes, parsed_inner) = parse_fragment_with_opts(
81 content,
82 self.parse_comment,
83 self.parse_lowercase,
84 comment_override,
85 );
86 if !allow_comment {
87 nodes.retain(|n| !matches!(n, Node::Comment(_)));
89 }
90 let fallback = if nodes.is_empty() {
92 parsed_inner.as_str()
93 } else {
94 content
95 };
96 self.replace_children_with(nodes, fallback);
97 }
98
99 fn replace_children_with(&mut self, mut nodes: Vec<Node>, raw_fallback: &str) {
100 if nodes.is_empty() {
101 use crate::dom::text::TextNode;
102 nodes.push(Node::Text(TextNode::new(raw_fallback.to_string())));
103 }
104 let self_ptr: *mut HTMLElement = self as *mut HTMLElement;
105 for n in nodes.iter_mut() {
106 if let Node::Element(e) = n {
107 e.parent = Some(self_ptr);
108 }
109 }
110 self.children.clear();
111 self.children.extend(nodes);
112 }
113
114 pub fn set_content(&mut self, content: &str) {
116 self.set_content_str(content, None);
117 }
118 pub fn set_content_nodes(&mut self, mut nodes: Vec<Node>) {
119 let self_ptr: *mut HTMLElement = self as *mut HTMLElement;
120 for n in nodes.iter_mut() {
121 if let Node::Element(e) = n {
122 e.parent = Some(self_ptr);
123 }
124 }
125 self.children.clear();
126 self.children.extend(nodes);
127 }
128}
129
130fn parse_fragment_with_opts(
131 html: &str,
132 base_comment: bool,
133 lower: bool,
134 override_comment: Option<bool>,
135) -> (Vec<Node>, String) {
136 use crate::parser::{parse_with_options, Options};
137 let mut opts = Options::default();
138 opts.comment = override_comment.unwrap_or(base_comment);
140 opts.lower_case_tag_name = lower;
141 let mut root = parse_with_options(html, &opts);
142 let fallback_inner = root.inner_html();
143 (root.children.drain(..).collect(), fallback_inner)
144}
145pub(super) fn parse_fragment(html: &str) -> Vec<Node> {
146 use crate::parser::{parse_with_options, Options};
147 let mut opts = Options::default();
148 if html.contains("<!--") {
149 opts.comment = true;
150 }
151 let mut root = parse_with_options(html, &opts);
152 root.children.drain(..).collect()
153}
154
155pub(super) fn collect_items(items: &[NodeOrStr]) -> Vec<Node> {
156 let mut out = Vec::new();
157 for it in items {
158 match it {
159 NodeOrStr::Str(s) => {
160 let mut frag = parse_fragment(&s.0);
161 out.extend(frag.drain(..));
162 }
163 NodeOrStr::Existing(n) => out.push(n.clone()), }
165 }
166 out
167}