1use crate::document::Document;
4use html5ever::{parse_document, tendril::TendrilSink};
5use markup5ever_rcdom::RcDom;
6use std::io;
7
8pub fn parse(source: &str) -> Result<Document, io::Error> {
10 parse_bytes(source.as_bytes())
11}
12
13pub fn parse_bytes(mut source: &[u8]) -> Result<Document, io::Error> {
15 parse_document(RcDom::default(), Default::default())
16 .from_utf8()
17 .read_from(&mut source)
18 .map(|dom| Document::from_markup5ever(&dom.document))
19}
20
21#[cfg(test)]
22mod tests {
23 use super::*;
24 use crate::document::{Element, Node};
25 use alloc::sync::Arc;
26 use pretty_assertions::assert_eq;
27
28 #[test]
29 fn parse_empty_string() {
30 assert_eq!(
31 parse("").unwrap(),
32 Document::new(vec![Arc::new(Node::Element(Element::new(
33 "html".to_string(),
34 vec![],
35 vec![
36 Arc::new(Node::Element(Element::new(
37 "head".to_string(),
38 vec![],
39 vec![]
40 ))),
41 Arc::new(Node::Element(Element::new(
42 "body".to_string(),
43 vec![],
44 vec![]
45 ))),
46 ],
47 )))])
48 );
49 }
50
51 #[test]
52 fn parse_simple_html() {
53 assert_eq!(
54 parse("<html><body><p>Hello</p></body></html>").unwrap(),
55 Document::new(vec![Arc::new(Node::Element(Element::new(
56 "html".to_string(),
57 vec![],
58 vec![
59 Arc::new(Node::Element(Element::new(
60 "head".to_string(),
61 vec![],
62 vec![]
63 ))),
64 Arc::new(Node::Element(Element::new(
65 "body".to_string(),
66 vec![],
67 vec![Arc::new(Node::Element(Element::new(
68 "p".to_string(),
69 vec![],
70 vec![Arc::new(Node::Text("Hello".to_string()))],
71 )))],
72 ))),
73 ],
74 )))])
75 );
76 }
77
78 #[test]
79 fn parse_with_attributes() {
80 assert_eq!(
81 parse("<html><body><p class=\"foo\">Hello</p></body></html>").unwrap(),
82 Document::new(vec![Arc::new(Node::Element(Element::new(
83 "html".to_string(),
84 vec![],
85 vec![
86 Arc::new(Node::Element(Element::new(
87 "head".to_string(),
88 vec![],
89 vec![]
90 ))),
91 Arc::new(Node::Element(Element::new(
92 "body".to_string(),
93 vec![],
94 vec![Arc::new(Node::Element(Element::new(
95 "p".to_string(),
96 vec![("class".to_string(), "foo".to_string())],
97 vec![Arc::new(Node::Text("Hello".to_string()))],
98 )))],
99 ))),
100 ],
101 )))])
102 );
103 }
104
105 #[test]
106 fn parse_svg_document() {
107 assert_eq!(
108 parse(concat!(
109 r#"<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">"#,
110 r#"<a href="/foo"><rect/></a>"#,
111 r#"<image xlink:href="/bar.png"/>"#,
112 "</svg>"
113 ))
114 .unwrap(),
115 Document::new(vec![Arc::new(Node::Element(Element::new(
116 "html".to_string(),
117 vec![],
118 vec![
119 Arc::new(Node::Element(Element::new(
120 "head".to_string(),
121 vec![],
122 vec![]
123 ))),
124 Arc::new(Node::Element(Element::new(
125 "body".to_string(),
126 vec![],
127 vec![Arc::new(Node::Element(Element::new(
128 "svg".to_string(),
129 vec![],
141 vec![
142 Arc::new(Node::Element(Element::new(
143 "a".to_string(),
144 vec![("href".to_string(), "/foo".to_string())],
145 vec![Arc::new(Node::Element(Element::new(
146 "rect".to_string(),
147 vec![],
148 vec![]
149 )))],
150 ))),
151 Arc::new(Node::Element(Element::new(
152 "image".to_string(),
153 vec![("href".to_string(), "/bar.png".to_string())],
154 vec![],
155 ))),
156 ],
157 )))],
158 ))),
159 ],
160 )))])
161 );
162 }
163
164 #[test]
165 fn ignore_comments() {
166 assert_eq!(
167 parse("<html><body><!-- comment --><p>Hello</p></body></html>").unwrap(),
168 Document::new(vec![Arc::new(Node::Element(Element::new(
169 "html".to_string(),
170 vec![],
171 vec![
172 Arc::new(Node::Element(Element::new(
173 "head".to_string(),
174 vec![],
175 vec![]
176 ))),
177 Arc::new(Node::Element(Element::new(
178 "body".to_string(),
179 vec![],
180 vec![Arc::new(Node::Element(Element::new(
181 "p".to_string(),
182 vec![],
183 vec![Arc::new(Node::Text("Hello".to_string()))],
184 )))],
185 ))),
186 ],
187 )))])
188 );
189 }
190}