1 // Copyright 2014-2017 The html5ever Project Developers. See the
2 // COPYRIGHT file at the top-level directory of this distribution.
4 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7 // option. This file may not be copied, modified, or distributed
8 // except according to those terms.
10 extern crate html5ever
;
11 extern crate typed_arena
;
13 use html5ever
::interface
::tree_builder
::{ElementFlags, NodeOrText, QuirksMode, TreeSink}
;
14 use html5ever
::tendril
::{StrTendril, TendrilSink}
;
15 use html5ever
::{parse_document, Attribute, ExpandedName, QualName}
;
17 use std
::cell
::{Cell, RefCell}
;
18 use std
::collections
::HashSet
;
19 use std
::io
::{self, Read}
;
23 let mut bytes
= Vec
::new();
24 io
::stdin().read_to_end(&mut bytes
).unwrap();
25 let arena
= typed_arena
::Arena
::new();
26 html5ever_parse_slice_into_arena(&bytes
, &arena
);
29 fn html5ever_parse_slice_into_arena
<'a
>(bytes
: &[u8], arena
: Arena
<'a
>) -> Ref
<'a
> {
32 document
: arena
.alloc(Node
::new(NodeData
::Document
)),
33 quirks_mode
: QuirksMode
::NoQuirks
,
35 parse_document(sink
, Default
::default())
40 type Arena
<'arena
> = &'arena typed_arena
::Arena
<Node
<'arena
>>;
42 type Ref
<'arena
> = &'arena Node
<'arena
>;
44 type Link
<'arena
> = Cell
<Option
<Ref
<'arena
>>>;
48 document
: Ref
<'arena
>,
49 quirks_mode
: QuirksMode
,
52 pub struct Node
<'arena
> {
54 next_sibling
: Link
<'arena
>,
55 previous_sibling
: Link
<'arena
>,
56 first_child
: Link
<'arena
>,
57 last_child
: Link
<'arena
>,
58 data
: NodeData
<'arena
>,
61 pub enum NodeData
<'arena
> {
65 public_id
: StrTendril
,
66 system_id
: StrTendril
,
69 contents
: RefCell
<StrTendril
>,
76 attrs
: RefCell
<Vec
<Attribute
>>,
77 template_contents
: Option
<Ref
<'arena
>>,
78 mathml_annotation_xml_integration_point
: bool
,
80 ProcessingInstruction
{
86 impl<'arena
> Node
<'arena
> {
87 fn new(data
: NodeData
<'arena
>) -> Self {
89 parent
: Cell
::new(None
),
90 previous_sibling
: Cell
::new(None
),
91 next_sibling
: Cell
::new(None
),
92 first_child
: Cell
::new(None
),
93 last_child
: Cell
::new(None
),
99 let parent
= self.parent
.take();
100 let previous_sibling
= self.previous_sibling
.take();
101 let next_sibling
= self.next_sibling
.take();
103 if let Some(next_sibling
) = next_sibling
{
104 next_sibling
.previous_sibling
.set(previous_sibling
);
105 } else if let Some(parent
) = parent
{
106 parent
.last_child
.set(previous_sibling
);
109 if let Some(previous_sibling
) = previous_sibling
{
110 previous_sibling
.next_sibling
.set(next_sibling
);
111 } else if let Some(parent
) = parent
{
112 parent
.first_child
.set(next_sibling
);
116 fn append(&'arena
self, new_child
: &'arena
Self) {
118 new_child
.parent
.set(Some(self));
119 if let Some(last_child
) = self.last_child
.take() {
120 new_child
.previous_sibling
.set(Some(last_child
));
121 debug_assert
!(last_child
.next_sibling
.get().is_none());
122 last_child
.next_sibling
.set(Some(new_child
));
124 debug_assert
!(self.first_child
.get().is_none());
125 self.first_child
.set(Some(new_child
));
127 self.last_child
.set(Some(new_child
));
130 fn insert_before(&'arena
self, new_sibling
: &'arena
Self) {
131 new_sibling
.detach();
132 new_sibling
.parent
.set(self.parent
.get());
133 new_sibling
.next_sibling
.set(Some(self));
134 if let Some(previous_sibling
) = self.previous_sibling
.take() {
135 new_sibling
.previous_sibling
.set(Some(previous_sibling
));
136 debug_assert
!(ptr
::eq
::<Node
>(
137 previous_sibling
.next_sibling
.get().unwrap(),
140 previous_sibling
.next_sibling
.set(Some(new_sibling
));
141 } else if let Some(parent
) = self.parent
.get() {
142 debug_assert
!(ptr
::eq
::<Node
>(parent
.first_child
.get().unwrap(), self));
143 parent
.first_child
.set(Some(new_sibling
));
145 self.previous_sibling
.set(Some(new_sibling
));
149 impl<'arena
> Sink
<'arena
> {
150 fn new_node(&self, data
: NodeData
<'arena
>) -> Ref
<'arena
> {
151 self.arena
.alloc(Node
::new(data
))
154 fn append_common
<P
, A
>(&self, child
: NodeOrText
<Ref
<'arena
>>, previous
: P
, append
: A
)
156 P
: FnOnce() -> Option
<Ref
<'arena
>>,
157 A
: FnOnce(Ref
<'arena
>),
159 let new_node
= match child
{
160 NodeOrText
::AppendText(text
) => {
161 // Append to an existing Text node if we have one.
163 data
: NodeData
::Text { ref contents }
,
167 contents
.borrow_mut().push_tendril(&text
);
170 self.new_node(NodeData
::Text
{
171 contents
: RefCell
::new(text
),
174 NodeOrText
::AppendNode(node
) => node
,
181 impl<'arena
> TreeSink
for Sink
<'arena
> {
182 type Handle
= Ref
<'arena
>;
183 type Output
= Ref
<'arena
>;
185 fn finish(self) -> Ref
<'arena
> {
189 fn parse_error(&mut self, _
: Cow
<'
static, str>) {}
191 fn get_document(&mut self) -> Ref
<'arena
> {
195 fn set_quirks_mode(&mut self, mode
: QuirksMode
) {
196 self.quirks_mode
= mode
;
199 fn same_node(&self, x
: &Ref
<'arena
>, y
: &Ref
<'arena
>) -> bool
{
200 ptr
::eq
::<Node
>(*x
, *y
)
203 fn elem_name
<'a
>(&self, target
: &'a Ref
<'arena
>) -> ExpandedName
<'a
> {
205 NodeData
::Element { ref name, .. }
=> name
.expanded(),
206 _
=> panic
!("not an element!"),
210 fn get_template_contents(&mut self, target
: &Ref
<'arena
>) -> Ref
<'arena
> {
211 if let NodeData
::Element
{
212 template_contents
: Some(ref contents
),
218 panic
!("not a template element!")
222 fn is_mathml_annotation_xml_integration_point(&self, target
: &Ref
<'arena
>) -> bool
{
223 if let NodeData
::Element
{
224 mathml_annotation_xml_integration_point
,
228 mathml_annotation_xml_integration_point
230 panic
!("not an element!")
237 attrs
: Vec
<Attribute
>,
240 self.new_node(NodeData
::Element
{
242 attrs
: RefCell
::new(attrs
),
243 template_contents
: if flags
.template
{
244 Some(self.new_node(NodeData
::Document
))
248 mathml_annotation_xml_integration_point
: flags
.mathml_annotation_xml_integration_point
,
252 fn create_comment(&mut self, text
: StrTendril
) -> Ref
<'arena
> {
253 self.new_node(NodeData
::Comment { contents: text }
)
256 fn create_pi(&mut self, target
: StrTendril
, data
: StrTendril
) -> Ref
<'arena
> {
257 self.new_node(NodeData
::ProcessingInstruction
{
263 fn append(&mut self, parent
: &Ref
<'arena
>, child
: NodeOrText
<Ref
<'arena
>>) {
266 || parent
.last_child
.get(),
267 |new_node
| parent
.append(new_node
),
271 fn append_before_sibling(&mut self, sibling
: &Ref
<'arena
>, child
: NodeOrText
<Ref
<'arena
>>) {
274 || sibling
.previous_sibling
.get(),
275 |new_node
| sibling
.insert_before(new_node
),
279 fn append_based_on_parent_node(
281 element
: &Ref
<'arena
>,
282 prev_element
: &Ref
<'arena
>,
283 child
: NodeOrText
<Ref
<'arena
>>,
285 if element
.parent
.get().is_some() {
286 self.append_before_sibling(element
, child
)
288 self.append(prev_element
, child
)
292 fn append_doctype_to_document(
295 public_id
: StrTendril
,
296 system_id
: StrTendril
,
298 self.document
.append(self.new_node(NodeData
::Doctype
{
305 fn add_attrs_if_missing(&mut self, target
: &Ref
<'arena
>, attrs
: Vec
<Attribute
>) {
306 let mut existing
= if let NodeData
::Element { ref attrs, .. }
= target
.data
{
309 panic
!("not an element")
312 let existing_names
= existing
314 .map(|e
| e
.name
.clone())
315 .collect
::<HashSet
<_
>>();
319 .filter(|attr
| !existing_names
.contains(&attr
.name
)),
323 fn remove_from_parent(&mut self, target
: &Ref
<'arena
>) {
327 fn reparent_children(&mut self, node
: &Ref
<'arena
>, new_parent
: &Ref
<'arena
>) {
328 let mut next_child
= node
.first_child
.get();
329 while let Some(child
) = next_child
{
330 debug_assert
!(ptr
::eq
::<Node
>(child
.parent
.get().unwrap(), *node
));
331 next_child
= child
.next_sibling
.get();
332 new_parent
.append(child
)