1use std::rc::Rc;
2use html5ever::tendril::StrTendril;
3use markup5ever_rcdom::NodeData::{Element, Text};
4use markup5ever_rcdom::{Handle, Node};
5use html5ever::Attribute;
6use std::str::FromStr;
7
8pub fn get_tag_name(handle: Handle) -> Option<String> {
9 match handle.data {
10 Element { ref name, .. } => Some(name.local.as_ref().to_lowercase().to_string()),
11 _ => None,
12 }
13}
14
15pub fn get_attr<'a>(name: &str, handle: Handle) -> Option<String> {
16 match handle.data {
17 Element { name: _, ref attrs, .. } => attr(name, &attrs.borrow()),
18 _ => None,
19 }
20}
21
22pub fn attr(attr_name: &str, attrs: &Vec<Attribute>) -> Option<String> {
23 for attr in attrs.iter() {
24 if attr.name.local.as_ref() == attr_name {
25 return Some(attr.value.to_string())
26 }
27 }
28 None
29}
30
31pub fn set_attr(attr_name: &str, value: &str, handle: Handle) {
32 match handle.data {
33 Element { name: _, ref attrs, .. } => {
34 let attrs = &mut attrs.borrow_mut();
35 if let Some(index) = attrs.iter().position(|attr| {
36 let name = attr.name.local.as_ref();
37 name == attr_name
38 }) {
39 match StrTendril::from_str(value) {
40 Ok(value) => attrs[index] = Attribute {
41 name: attrs[index].name.clone(),
42 value: value,
43 },
44 Err(_) => (),
45 }
46 }
47 }
48 _ => (),
49 }
50}
51
52pub fn clean_attr(attr_name: &str, attrs: &mut Vec<Attribute>) {
53 if let Some(index) = attrs.iter().position(|attr| {
54 let name = attr.name.local.as_ref();
55 name == attr_name
56 }) {
57 attrs.remove(index);
58 }
59}
60
61pub fn is_empty(handle: Handle) -> bool {
62 for child in handle.children.borrow().iter() {
63 let c = child.clone();
64 match c.data {
65 Text { ref contents } => {
66 if contents.borrow().trim().len() > 0 {
67 return false
68 }
69 },
70 Element { ref name, .. } => {
71 let tag_name = name.local.as_ref();
72 match tag_name.to_lowercase().as_ref() {
73 "li" | "dt" | "dd" | "p" | "div" => {
74 if !is_empty(child.clone()) {
75 return false
76 }
77 },
78 _ => return false,
79 }
80 },
81 _ => ()
82 }
83 }
84 match get_tag_name(handle.clone()).unwrap_or_default().as_ref() {
85 "li" | "dt" | "dd" | "p" | "div" | "canvas" => true,
86 _ => false,
87 }
88}
89
90pub fn has_link(handle: Handle) -> bool {
91 if "a" == &get_tag_name(handle.clone()).unwrap_or_default() {
92 return true
93 }
94 for child in handle.children.borrow().iter() {
95 if has_link(child.clone()) {
96 return true
97 }
98 }
99 return false
100}
101
102pub fn extract_text(handle: Handle, text: &mut String, deep: bool) {
103 for child in handle.children.borrow().iter() {
104 let c = child.clone();
105 match c.data {
106 Text { ref contents } => {
107 text.push_str(contents.borrow().trim());
108 },
109 Element { .. } => {
110 if deep {
111 extract_text(child.clone(), text, deep);
112 }
113 },
114 _ => ()
115 }
116 }
117}
118
119pub fn text_len(handle: Handle) -> usize {
120 let mut len = 0;
121 for child in handle.children.borrow().iter() {
122 let c = child.clone();
123 match c.data {
124 Text { ref contents } => {
125 len += contents.borrow().trim().chars().count();
126 },
127 Element { .. } => {
128 len += text_len(child.clone());
129 },
130 _ => ()
131 }
132 }
133 len
134}
135
136pub fn find_node(handle: Handle, tag_name: &str, nodes: &mut Vec<Rc<Node>>) {
137 for child in handle.children.borrow().iter() {
138 let c = child.clone();
139 match c.data {
140 Element { ref name, .. } => {
141 let t = name.local.as_ref();
142 if t.to_lowercase() == tag_name {
143 nodes.push(child.clone());
144 };
145 find_node(child.clone(), tag_name, nodes)
146 },
147 _ => ()
148 }
149 }
150}
151
152pub fn has_nodes(handle: Handle, tag_names: &Vec<&'static str>) -> bool {
153 for child in handle.children.borrow().iter() {
154 let tag_name: &str = &get_tag_name(child.clone()).unwrap_or_default();
155 if tag_names.iter().any(|&n| n == tag_name) {
156 return true
157 }
158 if match child.clone().data {
159 Element { .. } => {
160 has_nodes(child.clone(), tag_names)
161 },
162 _ => false,
163 } {
164 return true
165 }
166 }
167 return false
168}
169
170pub fn text_children_count(handle: Handle) -> usize {
171 let mut count = 0;
172 for child in handle.children.borrow().iter() {
173 let c = child.clone();
174 match c.data {
175 Text { ref contents } => {
176 let s = contents.borrow();
177 if s.trim().len() >= 20 {
178 count += 1
179 }
180 },
181 _ => ()
182 }
183 }
184 count
185}