1extern crate markup5ever;
47extern crate tendril;
48
49use std::borrow::Cow;
50use std::cell::{Cell, RefCell};
51use std::collections::{HashSet, VecDeque};
52use std::default::Default;
53use std::fmt;
54use std::io;
55use std::mem;
56use std::rc::{Rc, Weak};
57
58use tendril::StrTendril;
59
60use markup5ever::Attribute;
61use markup5ever::ExpandedName;
62use markup5ever::QualName;
63use markup5ever::interface::tree_builder;
64use markup5ever::interface::tree_builder::{ElementFlags, NodeOrText, QuirksMode, TreeSink};
65use markup5ever::serialize::TraversalScope;
66use markup5ever::serialize::TraversalScope::{ChildrenOnly, IncludeNode};
67use markup5ever::serialize::{Serialize, Serializer};
68
69#[derive(Debug)]
71pub enum NodeData {
72 Document,
74
75 Doctype {
80 name: StrTendril,
81 public_id: StrTendril,
82 system_id: StrTendril,
83 },
84
85 Text { contents: RefCell<StrTendril> },
87
88 Comment { contents: StrTendril },
90
91 Element {
93 name: QualName,
94 attrs: RefCell<Vec<Attribute>>,
95
96 template_contents: RefCell<Option<Handle>>,
100
101 mathml_annotation_xml_integration_point: bool,
105 },
106
107 ProcessingInstruction {
109 target: StrTendril,
110 contents: StrTendril,
111 },
112}
113
114pub struct Node {
116 pub parent: Cell<Option<WeakHandle>>,
118 pub children: RefCell<Vec<Handle>>,
120 pub data: NodeData,
122}
123
124impl Node {
125 pub fn new(data: NodeData) -> Rc<Self> {
127 Rc::new(Node {
128 data,
129 parent: Cell::new(None),
130 children: RefCell::new(Vec::new()),
131 })
132 }
133}
134
135impl Drop for Node {
136 fn drop(&mut self) {
137 let mut nodes = mem::take(&mut *self.children.borrow_mut());
138 while let Some(node) = nodes.pop() {
139 let children = mem::take(&mut *node.children.borrow_mut());
140 nodes.extend(children.into_iter());
141 if let NodeData::Element {
142 ref template_contents,
143 ..
144 } = node.data
145 && let Some(template_contents) = template_contents.borrow_mut().take() {
146 nodes.push(template_contents);
147 }
148 }
149 }
150}
151
152impl fmt::Debug for Node {
153 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
154 fmt.debug_struct("Node")
155 .field("data", &self.data)
156 .field("children", &self.children)
157 .finish()
158 }
159}
160
161pub type Handle = Rc<Node>;
163
164pub type WeakHandle = Weak<Node>;
166
167fn append(new_parent: &Handle, child: Handle) {
169 let previous_parent = child.parent.replace(Some(Rc::downgrade(new_parent)));
170 assert!(previous_parent.is_none());
172 new_parent.children.borrow_mut().push(child);
173}
174
175fn get_parent_and_index(target: &Handle) -> Option<(Handle, usize)> {
177 match target.parent.take() {
178 Some(weak) => {
179 let parent = weak.upgrade().expect("dangling weak pointer");
180 target.parent.set(Some(weak));
181 let i = match parent
182 .children
183 .borrow()
184 .iter()
185 .enumerate()
186 .find(|&(_, child)| Rc::ptr_eq(child, target))
187 {
188 Some((i, _)) => i,
189 None => panic!("have parent but couldn't find in parent's children!"),
190 };
191 Some((parent, i))
192 }
193 _ => None,
194 }
195}
196
197fn append_to_existing_text(prev: &Handle, text: &str) -> bool {
198 match prev.data {
199 NodeData::Text { ref contents } => {
200 contents.borrow_mut().push_slice(text);
201 true
202 }
203 _ => false,
204 }
205}
206
207fn remove_from_parent(target: &Handle) {
208 if let Some((parent, i)) = get_parent_and_index(target) {
209 parent.children.borrow_mut().remove(i);
210 target.parent.set(None);
211 }
212}
213
214pub struct RcDom {
216 pub document: Handle,
218
219 pub errors: RefCell<Vec<Cow<'static, str>>>,
221
222 pub quirks_mode: Cell<QuirksMode>,
224}
225
226impl TreeSink for RcDom {
227 type Output = Self;
228 fn finish(self) -> Self {
229 self
230 }
231
232 type Handle = Handle;
233
234 type ElemName<'a>
235 = ExpandedName<'a>
236 where
237 Self: 'a;
238
239 fn parse_error(&self, msg: Cow<'static, str>) {
240 self.errors.borrow_mut().push(msg);
241 }
242
243 fn get_document(&self) -> Handle {
244 self.document.clone()
245 }
246
247 fn get_template_contents(&self, target: &Handle) -> Handle {
248 if let NodeData::Element {
249 ref template_contents,
250 ..
251 } = target.data
252 {
253 template_contents
254 .borrow()
255 .as_ref()
256 .expect("not a template element!")
257 .clone()
258 } else {
259 panic!("not a template element!")
260 }
261 }
262
263 fn set_quirks_mode(&self, mode: QuirksMode) {
264 self.quirks_mode.set(mode);
265 }
266
267 fn same_node(&self, x: &Handle, y: &Handle) -> bool {
268 Rc::ptr_eq(x, y)
269 }
270
271 fn elem_name<'a>(&self, target: &'a Handle) -> ExpandedName<'a> {
272 match target.data {
273 NodeData::Element { ref name, .. } => name.expanded(),
274 _ => panic!("not an element!"),
275 }
276 }
277
278 fn create_element(&self, name: QualName, attrs: Vec<Attribute>, flags: ElementFlags) -> Handle {
279 Node::new(NodeData::Element {
280 name,
281 attrs: RefCell::new(attrs),
282 template_contents: RefCell::new(if flags.template {
283 Some(Node::new(NodeData::Document))
284 } else {
285 None
286 }),
287 mathml_annotation_xml_integration_point: flags.mathml_annotation_xml_integration_point,
288 })
289 }
290
291 fn create_comment(&self, text: StrTendril) -> Handle {
292 Node::new(NodeData::Comment { contents: text })
293 }
294
295 fn create_pi(&self, target: StrTendril, data: StrTendril) -> Handle {
296 Node::new(NodeData::ProcessingInstruction {
297 target,
298 contents: data,
299 })
300 }
301
302 fn append(&self, parent: &Handle, child: NodeOrText<Handle>) {
303 if let NodeOrText::AppendText(text) = &child
305 && let Some(h) = parent.children.borrow().last()
306 && append_to_existing_text(h, text) {
307 return;
308 }
309
310 append(
311 parent,
312 match child {
313 NodeOrText::AppendText(text) => Node::new(NodeData::Text {
314 contents: RefCell::new(text),
315 }),
316 NodeOrText::AppendNode(node) => node,
317 },
318 );
319 }
320
321 fn append_before_sibling(&self, sibling: &Handle, child: NodeOrText<Handle>) {
322 let (parent, i) = get_parent_and_index(sibling)
323 .expect("append_before_sibling called on node without parent");
324
325 let child = match (child, i) {
326 (NodeOrText::AppendText(text), 0) => Node::new(NodeData::Text {
328 contents: RefCell::new(text),
329 }),
330
331 (NodeOrText::AppendText(text), i) => {
333 let children = parent.children.borrow();
334 let prev = &children[i - 1];
335 if append_to_existing_text(prev, &text) {
336 return;
337 }
338 Node::new(NodeData::Text {
339 contents: RefCell::new(text),
340 })
341 }
342
343 (NodeOrText::AppendNode(node), _) => node,
348 };
349
350 remove_from_parent(&child);
351
352 child.parent.set(Some(Rc::downgrade(&parent)));
353 parent.children.borrow_mut().insert(i, child);
354 }
355
356 fn append_based_on_parent_node(
357 &self,
358 element: &Self::Handle,
359 prev_element: &Self::Handle,
360 child: NodeOrText<Self::Handle>,
361 ) {
362 let parent = element.parent.take();
363 let has_parent = parent.is_some();
364 element.parent.set(parent);
365
366 if has_parent {
367 self.append_before_sibling(element, child);
368 } else {
369 self.append(prev_element, child);
370 }
371 }
372
373 fn append_doctype_to_document(
374 &self,
375 name: StrTendril,
376 public_id: StrTendril,
377 system_id: StrTendril,
378 ) {
379 append(
380 &self.document,
381 Node::new(NodeData::Doctype {
382 name,
383 public_id,
384 system_id,
385 }),
386 );
387 }
388
389 fn add_attrs_if_missing(&self, target: &Handle, attrs: Vec<Attribute>) {
390 let mut existing = if let NodeData::Element { ref attrs, .. } = target.data {
391 attrs.borrow_mut()
392 } else {
393 panic!("not an element")
394 };
395
396 let existing_names = existing
397 .iter()
398 .map(|e| e.name.clone())
399 .collect::<HashSet<_>>();
400 existing.extend(
401 attrs
402 .into_iter()
403 .filter(|attr| !existing_names.contains(&attr.name)),
404 );
405 }
406
407 fn remove_from_parent(&self, target: &Handle) {
408 remove_from_parent(target);
409 }
410
411 fn reparent_children(&self, node: &Handle, new_parent: &Handle) {
412 let mut children = node.children.borrow_mut();
413 let mut new_children = new_parent.children.borrow_mut();
414 for child in children.iter() {
415 let previous_parent = child.parent.replace(Some(Rc::downgrade(new_parent)));
416 assert!(Rc::ptr_eq(
417 node,
418 &previous_parent.unwrap().upgrade().expect("dangling weak")
419 ))
420 }
421 new_children.extend(mem::take(&mut *children));
422 }
423
424 fn is_mathml_annotation_xml_integration_point(&self, target: &Handle) -> bool {
425 if let NodeData::Element {
426 mathml_annotation_xml_integration_point,
427 ..
428 } = target.data
429 {
430 mathml_annotation_xml_integration_point
431 } else {
432 panic!("not an element!")
433 }
434 }
435}
436
437impl Default for RcDom {
438 fn default() -> RcDom {
439 RcDom {
440 document: Node::new(NodeData::Document),
441 errors: Default::default(),
442 quirks_mode: Cell::new(tree_builder::NoQuirks),
443 }
444 }
445}
446
447enum SerializeOp {
448 Open(Handle),
449 Close(QualName),
450}
451
452pub struct SerializableHandle(Handle);
453
454impl From<Handle> for SerializableHandle {
455 fn from(h: Handle) -> SerializableHandle {
456 SerializableHandle(h)
457 }
458}
459
460impl Serialize for SerializableHandle {
461 fn serialize<S>(&self, serializer: &mut S, traversal_scope: TraversalScope) -> io::Result<()>
462 where
463 S: Serializer,
464 {
465 let mut ops = VecDeque::new();
466 match traversal_scope {
467 IncludeNode => ops.push_back(SerializeOp::Open(self.0.clone())),
468 ChildrenOnly(_) => ops.extend(
469 self.0
470 .children
471 .borrow()
472 .iter()
473 .map(|h| SerializeOp::Open(h.clone())),
474 ),
475 }
476
477 while let Some(op) = ops.pop_front() {
478 match op {
479 SerializeOp::Open(handle) => match handle.data {
480 NodeData::Element {
481 ref name,
482 ref attrs,
483 ..
484 } => {
485 serializer.start_elem(
486 name.clone(),
487 attrs.borrow().iter().map(|at| (&at.name, &at.value[..])),
488 )?;
489
490 ops.reserve(1 + handle.children.borrow().len());
491 ops.push_front(SerializeOp::Close(name.clone()));
492
493 for child in handle.children.borrow().iter().rev() {
494 ops.push_front(SerializeOp::Open(child.clone()));
495 }
496 }
497
498 NodeData::Doctype { ref name, .. } => serializer.write_doctype(name)?,
499
500 NodeData::Text { ref contents } => serializer.write_text(&contents.borrow())?,
501
502 NodeData::Comment { ref contents } => serializer.write_comment(contents)?,
503
504 NodeData::ProcessingInstruction {
505 ref target,
506 ref contents,
507 } => serializer.write_processing_instruction(target, contents)?,
508
509 NodeData::Document => panic!("Can't serialize Document node itself"),
510 },
511
512 SerializeOp::Close(name) => {
513 serializer.end_elem(name)?;
514 }
515 }
516 }
517
518 Ok(())
519 }
520}