Skip to main content

node_html_parser/dom/element/
tree.rs

1use super::content::collect_items;
2use super::content::parse_fragment;
3use super::main::HTMLElement;
4use crate::dom::node::{CowStr, Node, NodeOrStr};
5
6impl HTMLElement {
7	// ---- Public multi-node insertion (parity with JS variadic before/after/prepend/append) ----
8	/// Insert nodes (elements/text/comments) before this element in the parent's children list.
9	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	/// Insert nodes after this element.
33	pub fn after_nodes(&mut self, mut nodes: Vec<Node>) {
34		let parent_ptr = match self.parent {
35			Some(p) => p,
36			None => return,
37		};
38		unsafe {
39			let parent = &mut *parent_ptr;
40			let idx = match self.index_in_parent() {
41				Some(i) => i,
42				None => return,
43			} + 1;
44			for n in nodes.iter_mut() {
45				Self::detach_node(n);
46			}
47			for (i, mut n) in nodes.into_iter().enumerate() {
48				if let Node::Element(ref mut e) = n {
49					e.parent = Some(parent_ptr);
50				}
51				parent.children.insert(idx + i, n);
52			}
53		}
54	}
55
56	/// Prepend nodes to this element's children.
57	pub fn prepend_nodes(&mut self, mut nodes: Vec<Node>) {
58		for n in nodes.iter_mut() {
59			Self::detach_node(n);
60		}
61		let self_ptr: *mut HTMLElement = self as *mut HTMLElement;
62		for n in nodes.iter_mut() {
63			if let Node::Element(e) = n {
64				e.parent = Some(self_ptr);
65			}
66		}
67		for (i, n) in nodes.into_iter().enumerate() {
68			self.children.insert(i, n);
69		}
70	}
71
72	/// Append nodes to this element's children.
73	pub fn append_nodes(&mut self, mut nodes: Vec<Node>) {
74		for n in nodes.iter_mut() {
75			Self::detach_node(n);
76		}
77		let self_ptr: *mut HTMLElement = self as *mut HTMLElement;
78		for mut n in nodes.into_iter() {
79			if let Node::Element(ref mut e) = n {
80				e.parent = Some(self_ptr);
81			}
82			self.children.push(n);
83		}
84	}
85
86	fn detach_node(node: &mut Node) {
87		match node {
88			Node::Element(e) => {
89				if let Some(parent_ptr) = e.parent {
90					unsafe {
91						let parent = &mut *parent_ptr;
92						let elem_ptr: *const HTMLElement = &**e;
93						parent.children.retain(|c| {
94							if let Node::Element(pe) = c {
95								(&**pe) as *const HTMLElement != elem_ptr
96							} else {
97								true
98							}
99						});
100					}
101					e.parent = None;
102				}
103			}
104			Node::Text(_) | Node::Comment(_) => { /* no parent pointer tracking */ }
105		}
106	}
107
108	/// 下一个元素兄弟。
109	pub fn next_element_sibling(&self) -> Option<&HTMLElement> {
110		let parent = self.parent()?;
111		let mut seen = false;
112		let self_ptr = self as *const HTMLElement;
113		for child in &parent.children {
114			if let Node::Element(e) = child {
115				let ptr: *const HTMLElement = &**e;
116				if seen {
117					return Some(e);
118				}
119				if ptr == self_ptr {
120					seen = true;
121				}
122			}
123		}
124		None
125	}
126	/// 上一个元素兄弟。
127	pub fn previous_element_sibling(&self) -> Option<&HTMLElement> {
128		let parent = self.parent()?;
129		let self_ptr = self as *const HTMLElement;
130		let mut prev: Option<&HTMLElement> = None;
131		for child in &parent.children {
132			if let Node::Element(e) = child {
133				let ptr: *const HTMLElement = &**e;
134				if ptr == self_ptr {
135					return prev;
136				}
137				prev = Some(e);
138			}
139		}
140		None
141	}
142
143	pub(super) fn index_in_parent(&self) -> Option<usize> {
144		let parent = self.parent()?;
145		let self_ptr = self as *const HTMLElement;
146		for (i, child) in parent.children.iter().enumerate() {
147			if let Node::Element(e) = child {
148				let ptr: *const HTMLElement = &**e;
149				if ptr == self_ptr {
150					return Some(i);
151				}
152			}
153		}
154		None
155	}
156
157	/// 下一个兄弟节点(包含文本/注释)。
158	pub fn next_sibling(&self) -> Option<&Node> {
159		let parent = self.parent()?;
160		let idx = self.index_in_parent()?;
161		parent.children.get(idx + 1)
162	}
163	/// 上一个兄弟节点(包含文本/注释)。
164	pub fn previous_sibling(&self) -> Option<&Node> {
165		let parent = self.parent()?;
166		let idx = self.index_in_parent()?;
167		if idx == 0 {
168			return None;
169		}
170		parent.children.get(idx - 1)
171	}
172	/// 内部:在当前元素 children 指定 index 插入片段(仅用于自身 afterbegin/beforeend)。
173	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	/// 内部:作为兄弟插入;after=true 表示 afterend
187	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	/// remove() 移除自身
212	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	/// before(html_fragment) 在自身前插入兄弟
231	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	/// after(html_fragment) 在自身后插入兄弟
238	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	/// 由于当前结构不存 parent 指针,需要传入 root,用 DFS 寻找祖先链。
245	pub fn closest_in<'a>(
246		&'a self,
247		root: &'a HTMLElement,
248		selector: &str,
249	) -> Option<&'a HTMLElement> {
250		// 1. 若自身匹配,直接返回
251		if self.matches_selector(root, selector) {
252			return Some(self);
253		}
254		// 2. 构造从 root 到 self 的路径,再从倒数第二个往上测试
255		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		// stack 包含 root..self,去掉最后一个 self,从上往下倒序(接近 self 的祖先优先)
281		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	/// JS 风格 appendChild(Element) -> 返回子元素可变引用以便链式操作
297	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	/// JS appendChild(TextNode) 等价:直接加入文本节点
308	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	/// JS 兼容别名:attributes() => 已解码的小写属性映射。
318
319	pub fn set_content_node(&mut self, node: Node) {
320		self.set_content_nodes(vec![node]);
321	}
322	/// --- Variadic mutation helpers (支持字符串与已存在 Node) ---
323	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	/// 获取下一个元素兄弟(模拟 JS nextElementSibling),需要 root (当前无 parent 指针)。
378	pub fn next_element_sibling_in<'a>(&'a self, root: &'a HTMLElement) -> Option<&'a HTMLElement> {
379		let target = self as *const HTMLElement;
380		// DFS 找到父节点
381		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	/// 获取上一个元素兄弟(模拟 JS previousElementSibling)。
415	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		// 若节点已有父,先从旧父移除(与 JS appendChild 行为一致)
454		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 {
464								true
465							}
466						});
467					}
468					e.parent = None; // 临时清空防止错误引用
469				}
470				let self_ptr: *mut HTMLElement = self as *mut HTMLElement;
471				e.parent = Some(self_ptr);
472			}
473			Node::Text(_) | Node::Comment(_) => { /* Text/Comment 按当前实现不跟踪 parent 指针 */
474			}
475		}
476		self.children.push(n);
477	}
478	pub fn first_child(&self) -> Option<&Node> {
479		self.children.first()
480	}
481
482	pub fn last_child(&self) -> Option<&Node> {
483		self.children.last()
484	}
485
486	pub fn first_element_child(&self) -> Option<&HTMLElement> {
487		for c in &self.children {
488			if let Node::Element(e) = c {
489				return Some(e);
490			}
491		}
492		None
493	}
494	pub fn last_element_child(&self) -> Option<&HTMLElement> {
495		for c in self.children.iter().rev() {
496			if let Node::Element(e) = c {
497				return Some(e);
498			}
499		}
500		None
501	}
502	pub fn first_element_child_mut(&mut self) -> Option<&mut HTMLElement> {
503		for child in self.children.iter_mut() {
504			if let Node::Element(e) = child {
505				return Some(e);
506			}
507		}
508		None
509	}
510
511	/// 返回父元素引用(只读)。
512	pub fn parent(&self) -> Option<&HTMLElement> {
513		self.parent.map(|p| unsafe { &*p })
514	}
515	pub fn children_elements(&self) -> Vec<&HTMLElement> {
516		self.children
517			.iter()
518			.filter_map(|c| {
519				if let Node::Element(e) = c {
520					Some(&**e)
521				} else {
522					None
523				}
524			})
525			.collect()
526	}
527	pub fn child_element_count(&self) -> usize {
528		self.children
529			.iter()
530			.filter(|c| matches!(c, Node::Element(_)))
531			.count()
532	}
533}