1use crate::dom_tree::{Node, NodeData};
2use crate::matcher::InnerSelector;
3use markup5ever::{namespace_url, ns};
4use selectors::attr::AttrSelectorOperation;
5use selectors::attr::CaseSensitivity;
6use selectors::attr::NamespaceConstraint;
7use selectors::context::MatchingContext;
8use selectors::matching::ElementSelectorFlags;
9use selectors::parser::SelectorImpl;
10use selectors::OpaqueElement;
11use std::ops::Deref;
12
13impl<'a> selectors::Element for Node<'a> {
14 type Impl = InnerSelector;
15
16 fn opaque(&self) -> OpaqueElement {
18 OpaqueElement::new(&self.id)
19 }
20
21 fn parent_element(&self) -> Option<Self> {
22 self.parent()
23 }
24
25 fn parent_node_is_shadow_root(&self) -> bool {
27 false
28 }
29
30 fn containing_shadow_host(&self) -> Option<Self> {
32 None
33 }
34
35 fn is_pseudo_element(&self) -> bool {
37 false
38 }
39
40 fn prev_sibling_element(&self) -> Option<Self> {
42 self.prev_element_sibling()
43 }
44
45 fn next_sibling_element(&self) -> Option<Self> {
47 self.next_element_sibling()
48 }
49
50 fn is_html_element_in_html_document(&self) -> bool {
51 self.query(|node| {
52 if let NodeData::Element(ref e) = node.data {
53 return e.name.ns == ns!(html);
54 }
55
56 false
57 })
58 }
59
60 fn has_local_name(&self, local_name: &<Self::Impl as SelectorImpl>::BorrowedLocalName) -> bool {
61 self.query(|node| {
62 if let NodeData::Element(ref e) = node.data {
63 return &e.name.local == local_name;
64 }
65
66 false
67 })
68 }
69
70 fn has_namespace(&self, ns: &<Self::Impl as SelectorImpl>::BorrowedNamespaceUrl) -> bool {
72 self.query(|node| {
73 if let NodeData::Element(ref e) = node.data {
74 return &e.name.ns == ns;
75 }
76
77 false
78 })
79 }
80
81 fn is_same_type(&self, other: &Self) -> bool {
83 self.tree.compare_node(&self.id, &other.id, |a, b| {
84 if let NodeData::Element(ref e1) = a.data {
85 return match b.data {
86 NodeData::Element(ref e2) => e1.name == e2.name,
87 _ => false,
88 };
89 }
90
91 false
92 })
93 }
94
95 fn attr_matches(
96 &self,
97 ns: &NamespaceConstraint<&<Self::Impl as SelectorImpl>::NamespaceUrl>,
98 local_name: &<Self::Impl as SelectorImpl>::LocalName,
99 operation: &AttrSelectorOperation<&<Self::Impl as SelectorImpl>::AttrValue>,
100 ) -> bool {
101 self.query(|node| {
102 if let NodeData::Element(ref e) = node.data {
103 return e.attrs.iter().any(|attr| match *ns {
104 NamespaceConstraint::Specific(url) if *url != attr.name.ns => false,
105 _ => *local_name == attr.name.local && operation.eval_str(&attr.value),
106 });
107 }
108
109 false
110 })
111 }
112
113 fn match_non_ts_pseudo_class<F>(
114 &self,
115 _pc: &<Self::Impl as SelectorImpl>::NonTSPseudoClass,
116 _context: &mut MatchingContext<Self::Impl>,
117 _flags_setter: &mut F,
118 ) -> bool
119 where
120 F: FnMut(&Self, ElementSelectorFlags),
121 {
122 false
123 }
124
125 fn match_pseudo_element(
126 &self,
127 _pe: &<Self::Impl as SelectorImpl>::PseudoElement,
128 _context: &mut MatchingContext<Self::Impl>,
129 ) -> bool {
130 false
131 }
132
133 fn is_link(&self) -> bool {
135 self.query(|node| {
136 if let NodeData::Element(ref e) = node.data {
137 return &e.name.local == "link";
138 }
139
140 false
141 })
142 }
143
144 fn is_html_slot_element(&self) -> bool {
146 true
147 }
148
149 fn has_id(
150 &self,
151 name: &<Self::Impl as SelectorImpl>::Identifier,
152 case_sensitivity: CaseSensitivity,
153 ) -> bool {
154 self.query(|node| {
155 if let NodeData::Element(ref e) = node.data {
156 return e.attrs.iter().any(|attr| {
157 attr.name.local.deref() == "id"
158 && case_sensitivity.eq(name.as_bytes(), attr.value.as_bytes())
159 });
160 }
161
162 false
163 })
164 }
165
166 fn has_class(
167 &self,
168 name: &<Self::Impl as SelectorImpl>::ClassName,
169 case_sensitivity: CaseSensitivity,
170 ) -> bool {
171 self.query(|node| {
172 if let NodeData::Element(ref e) = node.data {
173 return e
174 .attrs
175 .iter()
176 .find(|a| a.name.local.deref() == "class")
177 .map_or(vec![], |a| a.value.deref().split_whitespace().collect())
178 .iter()
179 .any(|c| case_sensitivity.eq(name.as_bytes(), c.as_bytes()));
180 }
181
182 false
183 })
184 }
185
186 fn exported_part(
188 &self,
189 _name: &<Self::Impl as SelectorImpl>::PartName,
190 ) -> Option<<Self::Impl as SelectorImpl>::PartName> {
191 None
192 }
193
194 fn imported_part(
196 &self,
197 _name: &<Self::Impl as SelectorImpl>::PartName,
198 ) -> Option<<Self::Impl as SelectorImpl>::PartName> {
199 None
200 }
201
202 fn is_part(&self, _name: &<Self::Impl as SelectorImpl>::PartName) -> bool {
203 false
204 }
205
206 fn is_empty(&self) -> bool {
208 !self
209 .children()
210 .iter()
211 .any(|child| child.is_element() || child.is_text())
212 }
213
214 fn is_root(&self) -> bool {
216 self.is_document()
217 }
218}