1 use html5ever::driver;
2 use html5ever::tendril::stream::TendrilSink;
3 use html5ever::tendril::StrTendril;
4 use html5ever::ExpandedName;
5 use html5ever::QualName;
6 use markup5ever::interface::{ElementFlags, NodeOrText, QuirksMode, TreeSink};
7 use markup5ever::{local_name, namespace_url, ns, Attribute};
8 use markup5ever_rcdom::{Handle, RcDom};
9 use std::borrow::Cow;
10 
11 pub struct LineCountingDOM {
12     pub line_vec: Vec<(QualName, u64)>,
13     pub current_line: u64,
14     pub rcdom: RcDom,
15 }
16 
17 impl TreeSink for LineCountingDOM {
18     type Output = Self;
19 
finish(self) -> Self20     fn finish(self) -> Self {
21         self
22     }
23 
24     type Handle = Handle;
25 
parse_error(&mut self, msg: Cow<'static, str>)26     fn parse_error(&mut self, msg: Cow<'static, str>) {
27         self.rcdom.parse_error(msg);
28     }
29 
get_document(&mut self) -> Handle30     fn get_document(&mut self) -> Handle {
31         self.rcdom.get_document()
32     }
33 
get_template_contents(&mut self, target: &Handle) -> Handle34     fn get_template_contents(&mut self, target: &Handle) -> Handle {
35         self.rcdom.get_template_contents(target)
36     }
37 
set_quirks_mode(&mut self, mode: QuirksMode)38     fn set_quirks_mode(&mut self, mode: QuirksMode) {
39         self.rcdom.set_quirks_mode(mode)
40     }
41 
same_node(&self, x: &Handle, y: &Handle) -> bool42     fn same_node(&self, x: &Handle, y: &Handle) -> bool {
43         self.rcdom.same_node(x, y)
44     }
45 
elem_name<'a>(&'a self, target: &'a Handle) -> ExpandedName<'a>46     fn elem_name<'a>(&'a self, target: &'a Handle) -> ExpandedName<'a> {
47         self.rcdom.elem_name(target)
48     }
49 
create_element( &mut self, name: QualName, attrs: Vec<Attribute>, flags: ElementFlags, ) -> Handle50     fn create_element(
51         &mut self,
52         name: QualName,
53         attrs: Vec<Attribute>,
54         flags: ElementFlags,
55     ) -> Handle {
56         self.line_vec.push((name.clone(), self.current_line));
57         self.rcdom.create_element(name, attrs, flags)
58     }
59 
create_comment(&mut self, text: StrTendril) -> Handle60     fn create_comment(&mut self, text: StrTendril) -> Handle {
61         self.rcdom.create_comment(text)
62     }
63 
create_pi(&mut self, target: StrTendril, content: StrTendril) -> Handle64     fn create_pi(&mut self, target: StrTendril, content: StrTendril) -> Handle {
65         self.rcdom.create_pi(target, content)
66     }
67 
append(&mut self, parent: &Handle, child: NodeOrText<Handle>)68     fn append(&mut self, parent: &Handle, child: NodeOrText<Handle>) {
69         self.rcdom.append(parent, child)
70     }
71 
append_before_sibling(&mut self, sibling: &Handle, child: NodeOrText<Handle>)72     fn append_before_sibling(&mut self, sibling: &Handle, child: NodeOrText<Handle>) {
73         self.rcdom.append_before_sibling(sibling, child)
74     }
75 
append_based_on_parent_node( &mut self, element: &Handle, prev_element: &Handle, child: NodeOrText<Handle>, )76     fn append_based_on_parent_node(
77         &mut self,
78         element: &Handle,
79         prev_element: &Handle,
80         child: NodeOrText<Handle>,
81     ) {
82         self.rcdom
83             .append_based_on_parent_node(element, prev_element, child)
84     }
85 
append_doctype_to_document( &mut self, name: StrTendril, public_id: StrTendril, system_id: StrTendril, )86     fn append_doctype_to_document(
87         &mut self,
88         name: StrTendril,
89         public_id: StrTendril,
90         system_id: StrTendril,
91     ) {
92         self.rcdom
93             .append_doctype_to_document(name, public_id, system_id);
94     }
95 
add_attrs_if_missing(&mut self, target: &Handle, attrs: Vec<Attribute>)96     fn add_attrs_if_missing(&mut self, target: &Handle, attrs: Vec<Attribute>) {
97         self.rcdom.add_attrs_if_missing(target, attrs);
98     }
99 
remove_from_parent(&mut self, target: &Handle)100     fn remove_from_parent(&mut self, target: &Handle) {
101         self.rcdom.remove_from_parent(target);
102     }
103 
reparent_children(&mut self, node: &Handle, new_parent: &Handle)104     fn reparent_children(&mut self, node: &Handle, new_parent: &Handle) {
105         self.rcdom.reparent_children(node, new_parent);
106     }
107 
mark_script_already_started(&mut self, target: &Handle)108     fn mark_script_already_started(&mut self, target: &Handle) {
109         self.rcdom.mark_script_already_started(target);
110     }
111 
set_current_line(&mut self, line_number: u64)112     fn set_current_line(&mut self, line_number: u64) {
113         self.current_line = line_number;
114     }
115 }
116 
117 #[test]
check_four_lines()118 fn check_four_lines() {
119     // Input
120     let sink = LineCountingDOM {
121         line_vec: vec![],
122         current_line: 1,
123         rcdom: RcDom::default(),
124     };
125     let mut result_tok = driver::parse_document(sink, Default::default());
126     result_tok.process(StrTendril::from("<a>\n"));
127     result_tok.process(StrTendril::from("</a>\n"));
128     result_tok.process(StrTendril::from("<b>\n"));
129     result_tok.process(StrTendril::from("</b>"));
130     // Actual Output
131     let actual = result_tok.finish();
132     // Expected Output
133     let expected = vec![
134         (QualName::new(None, ns!(html), local_name!("html")), 1),
135         (QualName::new(None, ns!(html), local_name!("head")), 1),
136         (QualName::new(None, ns!(html), local_name!("body")), 1),
137         (QualName::new(None, ns!(html), local_name!("a")), 1),
138         (QualName::new(None, ns!(html), local_name!("b")), 3),
139     ];
140     // Assertion
141     assert_eq!(actual.line_vec, expected);
142 }
143