#[allow(unused_imports)]
use html5ever::namespace_url;
use html5ever::{local_name, ns};
use selectors::attr::{AttrSelectorOperation, CaseSensitivity, NamespaceConstraint};
use selectors::context::MatchingContext;
use selectors::matching::ElementSelectorFlags;
use selectors::parser::SelectorImpl;
use selectors::OpaqueElement;
use std::ops::Deref;
use super::node_data::NodeData;
use super::NodeRef;
use crate::css::CssLocalName;
use crate::matcher::{InnerSelector, NonTSPseudoClass};
impl selectors::Element for NodeRef<'_> {
type Impl = InnerSelector;
fn add_element_unique_hashes(&self, _filter: &mut selectors::bloom::BloomFilter) -> bool {
false
}
fn has_custom_state(&self, _name: &<Self::Impl as SelectorImpl>::Identifier) -> bool {
false
}
#[inline]
fn opaque(&self) -> OpaqueElement {
let nodes = self.tree.nodes.borrow();
let node = nodes.get(self.id.value).expect("element not in the tree!");
OpaqueElement::new(node)
}
#[inline]
fn parent_element(&self) -> Option<Self> {
self.parent()
}
#[inline]
fn parent_node_is_shadow_root(&self) -> bool {
false
}
#[inline]
fn containing_shadow_host(&self) -> Option<Self> {
None
}
#[inline]
fn is_pseudo_element(&self) -> bool {
false
}
#[inline]
fn prev_sibling_element(&self) -> Option<Self> {
self.prev_element_sibling()
}
#[inline]
fn next_sibling_element(&self) -> Option<Self> {
self.next_element_sibling()
}
#[inline]
fn is_html_element_in_html_document(&self) -> bool {
self.query_or(false, |node| {
if let NodeData::Element(ref e) = node.data {
return e.name.ns == ns!(html);
}
false
})
}
#[inline]
fn has_local_name(&self, local_name: &<Self::Impl as SelectorImpl>::BorrowedLocalName) -> bool {
self.query_or(false, |node| {
if let NodeData::Element(ref e) = node.data {
return &e.name.local == local_name.deref();
}
false
})
}
#[inline]
fn has_namespace(&self, ns: &<Self::Impl as SelectorImpl>::BorrowedNamespaceUrl) -> bool {
self.query_or(false, |node| {
if let NodeData::Element(ref e) = node.data {
return &e.name.ns == ns;
}
false
})
}
fn is_same_type(&self, other: &Self) -> bool {
self.tree
.compare_node(&self.id, &other.id, |a, b| {
if let (NodeData::Element(ref e1), NodeData::Element(ref e2)) = (&a.data, &b.data) {
e1.name == e2.name
} else {
false
}
})
.unwrap_or(false)
}
fn attr_matches(
&self,
ns: &NamespaceConstraint<&<Self::Impl as SelectorImpl>::NamespaceUrl>,
local_name: &<Self::Impl as SelectorImpl>::LocalName,
operation: &AttrSelectorOperation<&<Self::Impl as SelectorImpl>::AttrValue>,
) -> bool {
self.query_or(false, |node| {
if let NodeData::Element(ref e) = node.data {
return e.attrs.iter().any(|attr| match *ns {
NamespaceConstraint::Specific(url) if *url != attr.name.ns => false,
_ => *local_name.as_ref() == attr.name.local && operation.eval_str(&attr.value),
});
}
false
})
}
fn match_non_ts_pseudo_class(
&self,
pseudo: &<Self::Impl as SelectorImpl>::NonTSPseudoClass,
_context: &mut MatchingContext<Self::Impl>,
) -> bool {
use self::NonTSPseudoClass::*;
match pseudo {
Active | Focus | Hover | Enabled | Disabled | Checked | Indeterminate | Visited => {
false
}
AnyLink | Link => self.query_or(false, |n| n.is_link()),
OnlyText => self.has_only_text(),
HasText(s) => self.has_text(s.as_str()),
Contains(s) => self.text().contains(s.as_str()),
}
}
fn match_pseudo_element(
&self,
_pe: &<Self::Impl as SelectorImpl>::PseudoElement,
_context: &mut MatchingContext<Self::Impl>,
) -> bool {
false
}
fn is_link(&self) -> bool {
false
}
fn is_html_slot_element(&self) -> bool {
true
}
fn has_id(
&self,
name: &<Self::Impl as SelectorImpl>::Identifier,
case_sensitivity: CaseSensitivity,
) -> bool {
self.query_or(false, |node| {
if let NodeData::Element(ref e) = node.data {
return e.attrs.iter().any(|attr| {
attr.name.local == local_name!("id")
&& case_sensitivity.eq(name.as_bytes(), attr.value.as_bytes())
});
}
false
})
}
fn has_class(
&self,
name: &<Self::Impl as SelectorImpl>::LocalName,
case_sensitivity: CaseSensitivity,
) -> bool {
self.query_or(false, |node| {
node.as_element()
.is_some_and(|e| e.has_class_bytes(name.as_bytes(), case_sensitivity))
})
}
fn imported_part(&self, _name: &CssLocalName) -> Option<CssLocalName> {
None
}
fn is_part(&self, _name: &CssLocalName) -> bool {
false
}
fn is_empty(&self) -> bool {
self.is_empty_element()
}
fn is_root(&self) -> bool {
self.is_document()
}
fn first_element_child(&self) -> Option<Self> {
self.first_element_child()
}
fn apply_selector_flags(&self, _flags: ElementSelectorFlags) {}
}