kuchikikiki/
serializer.rs1use html5ever::QualName;
2use html5ever::serialize::TraversalScope::*;
3use html5ever::serialize::{Serialize, SerializeOpts, Serializer, TraversalScope, serialize};
4use std::fmt;
5use std::fs::File;
6use std::io;
7use std::io::Write;
8use std::path::Path;
9
10use crate::tree::{NodeData, NodeRef};
11
12impl Serialize for NodeRef {
13 fn serialize<S: Serializer>(
14 &self,
15 serializer: &mut S,
16 traversal_scope: TraversalScope,
17 ) -> io::Result<()> {
18 match (traversal_scope, self.data()) {
19 (ref scope, NodeData::Element(element)) => {
20 if *scope == IncludeNode {
21 let attrs = element.attributes.borrow();
22
23 let attrs = attrs
25 .map
26 .iter()
27 .map(|(name, attr)| {
28 (
29 QualName::new(
30 attr.prefix.clone(),
31 name.ns.clone(),
32 name.local.clone(),
33 ),
34 &attr.value,
35 )
36 })
37 .collect::<Vec<_>>();
38
39 serializer.start_elem(
40 element.name.clone(),
41 attrs.iter().map(|&(ref name, value)| (name, &**value)),
42 )?
43 }
44
45 let children = match element.template_contents.as_ref() {
46 Some(template_root) => template_root.children(),
47 None => self.children(),
48 };
49
50 for child in children {
51 Serialize::serialize(&child, serializer, IncludeNode)?
52 }
53
54 if *scope == IncludeNode {
55 serializer.end_elem(element.name.clone())?
56 }
57 Ok(())
58 }
59
60 (_, &NodeData::DocumentFragment) | (_, &NodeData::Document(_)) => {
61 for child in self.children() {
62 Serialize::serialize(&child, serializer, IncludeNode)?
63 }
64 Ok(())
65 }
66
67 (ChildrenOnly(_), _) => Ok(()),
68
69 (IncludeNode, NodeData::Doctype(doctype)) => serializer.write_doctype(&doctype.name),
70 (IncludeNode, NodeData::Text(text)) => serializer.write_text(&text.borrow()),
71 (IncludeNode, NodeData::Comment(text)) => serializer.write_comment(&text.borrow()),
72 (IncludeNode, NodeData::ProcessingInstruction(contents)) => {
73 let contents = contents.borrow();
74 serializer.write_processing_instruction(&contents.0, &contents.1)
75 }
76 }
77 }
78}
79
80impl fmt::Display for NodeRef {
81 #[inline]
82 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
83 let mut bytes = Vec::new();
85 self.serialize(&mut bytes).or(Err(fmt::Error))?;
86 let html = String::from_utf8(bytes).or(Err(fmt::Error))?;
87 f.write_str(&html)
88 }
89}
90
91impl NodeRef {
92 #[inline]
94 pub fn serialize<W: Write>(&self, writer: &mut W) -> io::Result<()> {
95 serialize(
96 writer,
97 self,
98 SerializeOpts {
99 traversal_scope: IncludeNode,
100 ..Default::default()
101 },
102 )
103 }
104
105 #[inline]
107 pub fn serialize_to_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
108 let mut file = File::create(&path)?;
109 self.serialize(&mut file)
110 }
111}