1extern crate markup5ever;
44extern crate tendril;
45
46use std::borrow::Cow;
47use std::cell::{Cell, RefCell};
48use std::collections::{HashSet, VecDeque};
49use std::default::Default;
50use std::fmt;
51use std::io;
52use std::mem;
53use std::rc::{Rc, Weak};
54
55use tendril::StrTendril;
56
57use markup5ever::interface::tree_builder;
58use markup5ever::interface::tree_builder::{ElementFlags, NodeOrText, QuirksMode, TreeSink};
59use markup5ever::serialize::TraversalScope;
60use markup5ever::serialize::TraversalScope::{ChildrenOnly, IncludeNode};
61use markup5ever::serialize::{Serialize, Serializer};
62use markup5ever::Attribute;
63use markup5ever::ExpandedName;
64use markup5ever::QualName;
65use markup5ever::interface::ElemName;
66use markup5ever::local_name;
67
68#[derive(Debug, Clone)]
70pub enum NodeData {
71 Document,
73
74 Doctype {
79 name: StrTendril,
80 public_id: StrTendril,
81 system_id: StrTendril,
82 },
83
84 Text { contents: RefCell<StrTendril> },
86
87 Comment { contents: StrTendril },
89
90 Element {
92 name: QualName,
93 attrs: RefCell<Vec<Attribute>>,
94
95 template_contents: RefCell<Option<Handle>>,
99
100 mathml_annotation_xml_integration_point: bool,
104 },
105
106 ProcessingInstruction {
108 target: StrTendril,
109 contents: StrTendril,
110 },
111}
112
113pub struct Node {
115 pub parent: Cell<Option<WeakHandle>>,
117 pub children: RefCell<Vec<Handle>>,
119 pub data: NodeData,
121}
122
123unsafe impl Send for Node {}
145unsafe impl Sync for Node {}
146
147impl Node {
148 pub fn new(data: NodeData) -> Rc<Self> {
150 Rc::new(Node {
151 data,
152 parent: Cell::new(None),
153 children: RefCell::new(Vec::new()),
154 })
155 }
156
157 fn get_option_element_nearest_ancestor_select(&self) -> Option<Rc<Self>> {
159 let mut did_see_ancestor_optgroup = false;
162
163 let mut current = self.parent().and_then(|parent| parent.upgrade())?;
165 loop {
166 if let NodeData::Element { name, .. } = ¤t.data {
167 if matches!(
169 name.local_name(),
170 &local_name!("datalist") | &local_name!("hr") | &local_name!("option")
171 ) {
172 return None;
173 }
174
175 if name.local_name() == &local_name!("optgroup") {
177 if did_see_ancestor_optgroup {
179 return None;
180 }
181
182 did_see_ancestor_optgroup = true;
184 }
185
186 if name.local_name() == &local_name!("select") {
188 return Some(current);
189 }
190 };
191
192 let Some(next_ancestor) = current.parent().and_then(|parent| parent.upgrade()) else {
194 break;
195 };
196 current = next_ancestor;
197 }
198
199 None
201 }
202
203 fn parent(&self) -> Option<Weak<Self>> {
204 let parent = self.parent.take();
205 self.parent.set(parent.clone());
206 parent
207 }
208
209 fn get_a_selects_enabled_selectedcontent(&self) -> Option<Rc<Self>> {
211 let NodeData::Element { name, attrs, .. } = &self.data else {
213 panic!("Trying to get selectedcontent of non-element");
214 };
215 debug_assert_eq!(name.local_name(), &local_name!("select"));
216 if attrs
217 .borrow()
218 .iter()
219 .any(|attribute| attribute.name.local == local_name!("multiple"))
220 {
221 return None;
222 }
223
224 let mut remaining = VecDeque::default();
228 remaining.extend(self.children.borrow().iter().cloned());
229 let mut selectedcontent = None;
230 while let Some(node) = remaining.pop_front() {
231 remaining.extend(node.children.borrow().iter().cloned());
232
233 let NodeData::Element { name, .. } = &self.data else {
234 continue;
235 };
236 if name.local_name() == &local_name!("selectedcontent") {
237 selectedcontent = Some(node);
238 break;
239 }
240 }
241 let selectedcontent = selectedcontent?;
242
243 Some(selectedcontent)
248 }
249
250 fn clone_an_option_into_selectedcontent(&self, selectedcontent: Rc<Self>) {
252 let mut document_fragment = Vec::new();
255
256 for child in self.children.borrow().iter() {
258 let child_clone = child.clone_with_subtree();
260
261 document_fragment.push(child_clone);
263 }
264
265 *selectedcontent.children.borrow_mut() = document_fragment;
267 }
268
269 fn clone_with_subtree(&self) -> Rc<Self> {
274 let children = self
275 .children
276 .borrow()
277 .iter()
278 .map(|child| child.clone_with_subtree())
279 .collect();
280 Rc::new(Self {
281 parent: Cell::new(self.parent()),
282 data: self.data.clone(),
283 children: RefCell::new(children),
284 })
285 }
286}
287
288impl Drop for Node {
289 fn drop(&mut self) {
290 let mut nodes = mem::take(&mut *self.children.borrow_mut());
291 while let Some(node) = nodes.pop() {
292 let children = mem::take(&mut *node.children.borrow_mut());
293 nodes.extend(children.into_iter());
294 if let NodeData::Element {
295 ref template_contents,
296 ..
297 } = node.data
298 {
299 if let Some(template_contents) = template_contents.borrow_mut().take() {
300 nodes.push(template_contents);
301 }
302 }
303 }
304 }
305}
306
307impl fmt::Debug for Node {
308 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
309 fmt.debug_struct("Node")
310 .field("data", &self.data)
311 .field("children", &self.children)
312 .finish()
313 }
314}
315
316pub type Handle = Rc<Node>;
318
319pub type WeakHandle = Weak<Node>;
321
322fn append(new_parent: &Handle, child: Handle) {
324 let previous_parent = child.parent.replace(Some(Rc::downgrade(new_parent)));
325 assert!(previous_parent.is_none());
327 new_parent.children.borrow_mut().push(child);
328}
329
330fn get_parent_and_index(target: &Handle) -> Option<(Handle, usize)> {
332 if let Some(weak) = target.parent.take() {
333 let parent = weak.upgrade().expect("dangling weak pointer");
334 target.parent.set(Some(weak));
335 let i = match parent
336 .children
337 .borrow()
338 .iter()
339 .enumerate()
340 .find(|&(_, child)| Rc::ptr_eq(child, target))
341 {
342 Some((i, _)) => i,
343 None => panic!("have parent but couldn't find in parent's children!"),
344 };
345 Some((parent, i))
346 } else {
347 None
348 }
349}
350
351fn append_to_existing_text(prev: &Handle, text: &str) -> bool {
352 match prev.data {
353 NodeData::Text { ref contents } => {
354 contents.borrow_mut().push_slice(text);
355 true
356 },
357 _ => false,
358 }
359}
360
361fn remove_from_parent(target: &Handle) {
362 if let Some((parent, i)) = get_parent_and_index(target) {
363 parent.children.borrow_mut().remove(i);
364 target.parent.set(None);
365 }
366}
367
368pub struct RcDom {
370 pub document: Handle,
372
373 pub errors: RefCell<Vec<Cow<'static, str>>>,
375
376 pub quirks_mode: Cell<QuirksMode>,
378}
379
380impl TreeSink for RcDom {
381 type Output = Self;
382 fn finish(self) -> Self {
383 self
384 }
385
386 type Handle = Handle;
387
388 type ElemName<'a>
389 = ExpandedName<'a>
390 where
391 Self: 'a;
392
393 fn parse_error(&self, msg: Cow<'static, str>) {
394 self.errors.borrow_mut().push(msg);
395 }
396
397 fn get_document(&self) -> Handle {
398 self.document.clone()
399 }
400
401 fn get_template_contents(&self, target: &Handle) -> Handle {
402 if let NodeData::Element {
403 ref template_contents,
404 ..
405 } = target.data
406 {
407 template_contents
408 .borrow()
409 .as_ref()
410 .expect("not a template element!")
411 .clone()
412 } else {
413 panic!("not a template element!")
414 }
415 }
416
417 fn set_quirks_mode(&self, mode: QuirksMode) {
418 self.quirks_mode.set(mode);
419 }
420
421 fn same_node(&self, x: &Handle, y: &Handle) -> bool {
422 Rc::ptr_eq(x, y)
423 }
424
425 fn elem_name<'a>(&self, target: &'a Handle) -> ExpandedName<'a> {
426 match target.data {
427 NodeData::Element { ref name, .. } => name.expanded(),
428 _ => panic!("not an element!"),
429 }
430 }
431
432 fn create_element(&self, name: QualName, attrs: Vec<Attribute>, flags: ElementFlags) -> Handle {
433 Node::new(NodeData::Element {
434 name,
435 attrs: RefCell::new(attrs),
436 template_contents: RefCell::new(if flags.template {
437 Some(Node::new(NodeData::Document))
438 } else {
439 None
440 }),
441 mathml_annotation_xml_integration_point: flags.mathml_annotation_xml_integration_point,
442 })
443 }
444
445 fn create_comment(&self, text: StrTendril) -> Handle {
446 Node::new(NodeData::Comment { contents: text })
447 }
448
449 fn create_pi(&self, target: StrTendril, data: StrTendril) -> Handle {
450 Node::new(NodeData::ProcessingInstruction {
451 target,
452 contents: data,
453 })
454 }
455
456 fn append(&self, parent: &Handle, child: NodeOrText<Handle>) {
457 if let NodeOrText::AppendText(text) = &child {
459 if let Some(h) = parent.children.borrow().last() {
460 if append_to_existing_text(h, text) {
461 return;
462 }
463 }
464 }
465
466 append(
467 parent,
468 match child {
469 NodeOrText::AppendText(text) => Node::new(NodeData::Text {
470 contents: RefCell::new(text),
471 }),
472 NodeOrText::AppendNode(node) => node,
473 },
474 );
475 }
476
477 fn append_before_sibling(&self, sibling: &Handle, child: NodeOrText<Handle>) {
478 let (parent, i) = get_parent_and_index(sibling)
479 .expect("append_before_sibling called on node without parent");
480
481 let child = match (child, i) {
482 (NodeOrText::AppendText(text), 0) => Node::new(NodeData::Text {
484 contents: RefCell::new(text),
485 }),
486
487 (NodeOrText::AppendText(text), i) => {
489 let children = parent.children.borrow();
490 let prev = &children[i - 1];
491 if append_to_existing_text(prev, &text) {
492 return;
493 }
494 Node::new(NodeData::Text {
495 contents: RefCell::new(text),
496 })
497 },
498
499 (NodeOrText::AppendNode(node), _) => node,
504 };
505
506 remove_from_parent(&child);
507
508 child.parent.set(Some(Rc::downgrade(&parent)));
509 parent.children.borrow_mut().insert(i, child);
510 }
511
512 fn append_based_on_parent_node(
513 &self,
514 element: &Self::Handle,
515 prev_element: &Self::Handle,
516 child: NodeOrText<Self::Handle>,
517 ) {
518 let parent = element.parent.take();
519 let has_parent = parent.is_some();
520 element.parent.set(parent);
521
522 if has_parent {
523 self.append_before_sibling(element, child);
524 } else {
525 self.append(prev_element, child);
526 }
527 }
528
529 fn append_doctype_to_document(
530 &self,
531 name: StrTendril,
532 public_id: StrTendril,
533 system_id: StrTendril,
534 ) {
535 append(
536 &self.document,
537 Node::new(NodeData::Doctype {
538 name,
539 public_id,
540 system_id,
541 }),
542 );
543 }
544
545 fn add_attrs_if_missing(&self, target: &Handle, attrs: Vec<Attribute>) {
546 let mut existing = if let NodeData::Element { ref attrs, .. } = target.data {
547 attrs.borrow_mut()
548 } else {
549 panic!("not an element")
550 };
551
552 let existing_names = existing
553 .iter()
554 .map(|e| e.name.clone())
555 .collect::<HashSet<_>>();
556 existing.extend(
557 attrs
558 .into_iter()
559 .filter(|attr| !existing_names.contains(&attr.name)),
560 );
561 }
562
563 fn remove_from_parent(&self, target: &Handle) {
564 remove_from_parent(target);
565 }
566
567 fn reparent_children(&self, node: &Handle, new_parent: &Handle) {
568 let mut children = node.children.borrow_mut();
569 let mut new_children = new_parent.children.borrow_mut();
570 for child in children.iter() {
571 let previous_parent = child.parent.replace(Some(Rc::downgrade(new_parent)));
572 assert!(Rc::ptr_eq(
573 node,
574 &previous_parent.unwrap().upgrade().expect("dangling weak")
575 ))
576 }
577 new_children.extend(mem::take(&mut *children));
578 }
579
580 fn is_mathml_annotation_xml_integration_point(&self, target: &Handle) -> bool {
581 if let NodeData::Element {
582 mathml_annotation_xml_integration_point,
583 ..
584 } = target.data
585 {
586 mathml_annotation_xml_integration_point
587 } else {
588 panic!("not an element!")
589 }
590 }
591
592 fn maybe_clone_an_option_into_selectedcontent(&self, option: &Self::Handle) {
593 let NodeData::Element { name, attrs, .. } = &option.data else {
594 panic!("\"maybe clone an option into selectedcontent\" called with non-element node");
595 };
596 debug_assert_eq!(name.local_name(), &local_name!("option"));
597
598 let select = option.get_option_element_nearest_ancestor_select();
600
601 if let Some(selectedcontent) =
607 select.and_then(|select| select.get_a_selects_enabled_selectedcontent())
608 {
609 if attrs
610 .borrow()
611 .iter()
612 .any(|attribute| attribute.name.local == local_name!("selected"))
613 {
614 option.clone_an_option_into_selectedcontent(selectedcontent);
615 }
616 }
617 }
618}
619
620impl Default for RcDom {
621 fn default() -> RcDom {
622 RcDom {
623 document: Node::new(NodeData::Document),
624 errors: Default::default(),
625 quirks_mode: Cell::new(tree_builder::NoQuirks),
626 }
627 }
628}
629
630enum SerializeOp {
631 Open(Handle),
632 Close(QualName),
633}
634
635pub struct SerializableHandle(Handle);
636
637impl From<Handle> for SerializableHandle {
638 fn from(h: Handle) -> SerializableHandle {
639 SerializableHandle(h)
640 }
641}
642
643impl Serialize for SerializableHandle {
644 fn serialize<S>(&self, serializer: &mut S, traversal_scope: TraversalScope) -> io::Result<()>
645 where
646 S: Serializer,
647 {
648 let mut ops = VecDeque::new();
649 match traversal_scope {
650 IncludeNode => ops.push_back(SerializeOp::Open(self.0.clone())),
651 ChildrenOnly(_) => ops.extend(
652 self.0
653 .children
654 .borrow()
655 .iter()
656 .map(|h| SerializeOp::Open(h.clone())),
657 ),
658 }
659
660 while let Some(op) = ops.pop_front() {
661 match op {
662 SerializeOp::Open(handle) => match handle.data {
663 NodeData::Element {
664 ref name,
665 ref attrs,
666 ..
667 } => {
668 serializer.start_elem(
669 name.clone(),
670 attrs.borrow().iter().map(|at| (&at.name, &at.value[..])),
671 )?;
672
673 ops.reserve(1 + handle.children.borrow().len());
674 ops.push_front(SerializeOp::Close(name.clone()));
675
676 for child in handle.children.borrow().iter().rev() {
677 ops.push_front(SerializeOp::Open(child.clone()));
678 }
679 },
680
681 NodeData::Doctype { ref name, .. } => serializer.write_doctype(name)?,
682
683 NodeData::Text { ref contents } => serializer.write_text(&contents.borrow())?,
684
685 NodeData::Comment { ref contents } => serializer.write_comment(contents)?,
686
687 NodeData::ProcessingInstruction {
688 ref target,
689 ref contents,
690 } => serializer.write_processing_instruction(target, contents)?,
691
692 NodeData::Document => panic!("Can't serialize Document node itself"),
693 },
694
695 SerializeOp::Close(name) => {
696 serializer.end_elem(name)?;
697 },
698 }
699 }
700
701 Ok(())
702 }
703}