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	/// 下一个元素兄弟。
33	pub fn next_element_sibling(&self) -> Option<&HTMLElement> {
34		let parent = self.parent()?;
35		let mut seen = false;
36		let self_ptr = self as *const HTMLElement;
37		for child in &parent.children {
38			if let Node::Element(e) = child {
39				let ptr: *const HTMLElement = &**e;
40				if seen {
41					return Some(e);
42				}
43				if ptr == self_ptr {
44					seen = true;
45				}
46			}
47		}
48		None
49	}
50	/// 上一个元素兄弟。
51	pub fn previous_element_sibling(&self) -> Option<&HTMLElement> {
52		let parent = self.parent()?;
53		let self_ptr = self as *const HTMLElement;
54		let mut prev: Option<&HTMLElement> = None;
55		for child in &parent.children {
56			if let Node::Element(e) = child {
57				let ptr: *const HTMLElement = &**e;
58				if ptr == self_ptr {
59					return prev;
60				}
61				prev = Some(e);
62			}
63		}
64		None
65	}
66
67	pub(super) fn index_in_parent(&self) -> Option<usize> {
68		let parent = self.parent()?;
69		let self_ptr = self as *const HTMLElement;
70		for (i, child) in parent.children.iter().enumerate() {
71			if let Node::Element(e) = child {
72				let ptr: *const HTMLElement = &**e;
73				if ptr == self_ptr {
74					return Some(i);
75				}
76			}
77		}
78		None
79	}
80
81	/// 下一个兄弟节点(包含文本/注释)。
82	pub fn next_sibling(&self) -> Option<&Node> {
83		let parent = self.parent()?;
84		let idx = self.index_in_parent()?;
85		parent.children.get(idx + 1)
86	}
87	/// 上一个兄弟节点(包含文本/注释)。
88	pub fn previous_sibling(&self) -> Option<&Node> {
89		let parent = self.parent()?;
90		let idx = self.index_in_parent()?;
91		if idx == 0 {
92			return None;
93		}
94		parent.children.get(idx - 1)
95	}
96	/// Insert nodes after this element.
97	pub fn after_nodes(&mut self, mut nodes: Vec<Node>) {
98		let parent_ptr = match self.parent {
99			Some(p) => p,
100			None => return,
101		};
102		unsafe {
103			let parent = &mut *parent_ptr;
104			let idx = match self.index_in_parent() {
105				Some(i) => i,
106				None => return,
107			} + 1;
108			for n in nodes.iter_mut() {
109				Self::detach_node(n);
110			}
111			for (i, mut n) in nodes.into_iter().enumerate() {
112				if let Node::Element(ref mut e) = n {
113					e.parent = Some(parent_ptr);
114				}
115				parent.children.insert(idx + i, n);
116			}
117		}
118	}
119
120	/// Prepend nodes to this element's children.
121	pub fn prepend_nodes(&mut self, mut nodes: Vec<Node>) {
122		for n in nodes.iter_mut() {
123			Self::detach_node(n);
124		}
125		let self_ptr: *mut HTMLElement = self as *mut HTMLElement;
126		for n in nodes.iter_mut() {
127			if let Node::Element(e) = n {
128				e.parent = Some(self_ptr);
129			}
130		}
131		for (i, n) in nodes.into_iter().enumerate() {
132			self.children.insert(i, n);
133		}
134	}
135
136	/// Append nodes to this element's children.
137	pub fn append_nodes(&mut self, mut nodes: Vec<Node>) {
138		for n in nodes.iter_mut() {
139			Self::detach_node(n);
140		}
141		let self_ptr: *mut HTMLElement = self as *mut HTMLElement;
142		for mut n in nodes.into_iter() {
143			if let Node::Element(ref mut e) = n {
144				e.parent = Some(self_ptr);
145			}
146			self.children.push(n);
147		}
148	}
149
150	fn detach_node(node: &mut Node) {
151		match node {
152			Node::Element(e) => {
153				if let Some(parent_ptr) = e.parent {
154					unsafe {
155						let parent = &mut *parent_ptr;
156						let elem_ptr: *const HTMLElement = &**e;
157						parent.children.retain(|c| {
158							if let Node::Element(pe) = c {
159								(&**pe) as *const HTMLElement != elem_ptr
160							} else {
161								true
162							}
163						});
164					}
165					e.parent = None;
166				}
167			}
168			Node::Text(_) | Node::Comment(_) => { /* no parent pointer tracking */ }
169		}
170	}
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 { true }
464						});
465					}
466					e.parent = None; // 临时清空防止错误引用
467				}
468				let self_ptr: *mut HTMLElement = self as *mut HTMLElement;
469				e.parent = Some(self_ptr);
470			},
471			Node::Text(_) | Node::Comment(_) => { /* Text/Comment 按当前实现不跟踪 parent 指针 */ }
472		}
473		self.children.push(n);
474	}
475	pub fn first_child(&self) -> Option<&Node> {
476		self.children.first()
477	}
478
479	pub fn last_child(&self) -> Option<&Node> {
480		self.children.last()
481	}
482
483	pub fn first_element_child(&self) -> Option<&HTMLElement> {
484		for c in &self.children {
485			if let Node::Element(e) = c {
486				return Some(e);
487			}
488		}
489		None
490	}
491	pub fn last_element_child(&self) -> Option<&HTMLElement> {
492		for c in self.children.iter().rev() {
493			if let Node::Element(e) = c {
494				return Some(e);
495			}
496		}
497		None
498	}
499	pub fn first_element_child_mut(&mut self) -> Option<&mut HTMLElement> {
500		for child in self.children.iter_mut() {
501			if let Node::Element(e) = child {
502				return Some(e);
503			}
504		}
505		None
506	}
507
508	/// 返回父元素引用(只读)。
509	pub fn parent(&self) -> Option<&HTMLElement> {
510		self.parent.map(|p| unsafe { &*p })
511	}
512	pub fn children_elements(&self) -> Vec<&HTMLElement> {
513		self.children
514			.iter()
515			.filter_map(|c| {
516				if let Node::Element(e) = c {
517					Some(&**e)
518				} else {
519					None
520				}
521			})
522			.collect()
523	}
524	pub fn child_element_count(&self) -> usize {
525		self.children
526			.iter()
527			.filter(|c| matches!(c, Node::Element(_)))
528			.count()
529	}
530}