Skip to content

Commit

Permalink
Merge pull request #99 from adamreichold/bump-cssparser-selectors
Browse files Browse the repository at this point in the history
Bump cssparser to 0.28 and selectors to 0.23.
  • Loading branch information
cfvescovo committed Jan 10, 2023
2 parents 6e142c8 + 4972e90 commit a1ad314
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 50 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Expand Up @@ -15,11 +15,11 @@ repository = "https://github.com/causal-agent/scraper"
readme = "README.md"

[dependencies]
cssparser = "0.27"
cssparser = "0.28"
ego-tree = "0.6.2"
html5ever = "0.26"
matches = "0.1.9"
selectors = "0.22.0"
selectors = "0.23.0"
smallvec = "1.9.0"
tendril = "0.4.3"
indexmap = { version = "1.9.1", optional = true }
Expand Down
49 changes: 24 additions & 25 deletions src/element_ref/element.rs
@@ -1,10 +1,10 @@
use html5ever::{LocalName, Namespace};
use html5ever::Namespace;
use selectors::attr::{AttrSelectorOperation, CaseSensitivity, NamespaceConstraint};
use selectors::matching;
use selectors::{Element, OpaqueElement};

use super::ElementRef;
use crate::selector::{NonTSPseudoClass, PseudoElement, Simple};
use crate::selector::{CssLocalName, CssString, NonTSPseudoClass, PseudoElement, Simple};

/// Note: will never match against non-tree-structure pseudo-classes.
impl<'a> Element for ElementRef<'a> {
Expand All @@ -30,19 +30,15 @@ impl<'a> Element for ElementRef<'a> {
false
}

fn is_part(&self, _name: &LocalName) -> bool {
fn is_part(&self, _name: &CssLocalName) -> bool {
false
}

fn is_same_type(&self, other: &Self) -> bool {
self.value().name == other.value().name
}

fn exported_part(&self, _: &LocalName) -> Option<LocalName> {
None
}

fn imported_part(&self, _: &LocalName) -> Option<LocalName> {
fn imported_part(&self, _: &CssLocalName) -> Option<CssLocalName> {
None
}

Expand All @@ -63,8 +59,8 @@ impl<'a> Element for ElementRef<'a> {
self.value().name.ns == ns!(html)
}

fn has_local_name(&self, name: &LocalName) -> bool {
&self.value().name.local == name
fn has_local_name(&self, name: &CssLocalName) -> bool {
self.value().name.local == name.0
}

fn has_namespace(&self, namespace: &Namespace) -> bool {
Expand All @@ -74,12 +70,12 @@ impl<'a> Element for ElementRef<'a> {
fn attr_matches(
&self,
ns: &NamespaceConstraint<&Namespace>,
local_name: &LocalName,
operation: &AttrSelectorOperation<&String>,
local_name: &CssLocalName,
operation: &AttrSelectorOperation<&CssString>,
) -> bool {
self.value().attrs.iter().any(|(key, value)| {
!matches!(*ns, NamespaceConstraint::Specific(url) if *url != key.ns)
&& *local_name == key.local
&& local_name.0 == key.local
&& operation.eval_str(value)
})
}
Expand Down Expand Up @@ -109,15 +105,15 @@ impl<'a> Element for ElementRef<'a> {
true
}

fn has_id(&self, id: &LocalName, case_sensitivity: CaseSensitivity) -> bool {
fn has_id(&self, id: &CssLocalName, case_sensitivity: CaseSensitivity) -> bool {
match self.value().id {
Some(ref val) => case_sensitivity.eq(id.as_bytes(), val.as_bytes()),
Some(ref val) => case_sensitivity.eq(id.0.as_bytes(), val.as_bytes()),
None => false,
}
}

fn has_class(&self, name: &LocalName, case_sensitivity: CaseSensitivity) -> bool {
self.value().has_class(name, case_sensitivity)
fn has_class(&self, name: &CssLocalName, case_sensitivity: CaseSensitivity) -> bool {
self.value().has_class(&name.0, case_sensitivity)
}

fn is_empty(&self) -> bool {
Expand All @@ -135,14 +131,12 @@ impl<'a> Element for ElementRef<'a> {
#[cfg(test)]
mod tests {
use crate::html::Html;
use crate::selector::Selector;
use crate::selector::{CssLocalName, Selector};
use selectors::attr::CaseSensitivity;
use selectors::Element;

#[test]
fn test_has_id() {
use html5ever::LocalName;

let html = "<p id='link_id_456'>hey there</p>";
let fragment = Html::parse_fragment(html);
let sel = Selector::parse("p").unwrap();
Expand All @@ -151,7 +145,7 @@ mod tests {
assert_eq!(
true,
element.has_id(
&LocalName::from("link_id_456"),
&CssLocalName::from("link_id_456"),
CaseSensitivity::CaseSensitive
)
);
Expand All @@ -162,7 +156,7 @@ mod tests {
assert_eq!(
false,
element.has_id(
&LocalName::from("any_link_id"),
&CssLocalName::from("any_link_id"),
CaseSensitivity::CaseSensitive
)
);
Expand All @@ -185,14 +179,16 @@ mod tests {

#[test]
fn test_has_class() {
use html5ever::LocalName;
let html = "<p class='my_class'>hey there</p>";
let fragment = Html::parse_fragment(html);
let sel = Selector::parse("p").unwrap();
let element = fragment.select(&sel).next().unwrap();
assert_eq!(
true,
element.has_class(&LocalName::from("my_class"), CaseSensitivity::CaseSensitive)
element.has_class(
&CssLocalName::from("my_class"),
CaseSensitivity::CaseSensitive
)
);

let html = "<p>hey there</p>";
Expand All @@ -201,7 +197,10 @@ mod tests {
let element = fragment.select(&sel).next().unwrap();
assert_eq!(
false,
element.has_class(&LocalName::from("my_class"), CaseSensitivity::CaseSensitive)
element.has_class(
&CssLocalName::from("my_class"),
CaseSensitivity::CaseSensitive
)
);
}
}
73 changes: 50 additions & 23 deletions src/selector.rs
Expand Up @@ -7,7 +7,7 @@ use smallvec::SmallVec;

use html5ever::{LocalName, Namespace};
use selectors::parser::SelectorParseErrorKind;
use selectors::{matching, parser, visitor};
use selectors::{matching, parser};

use crate::error::SelectorErrorKind;
use crate::ElementRef;
Expand Down Expand Up @@ -67,15 +67,13 @@ impl<'i> parser::Parser<'i> for Parser {
pub struct Simple;

impl parser::SelectorImpl for Simple {
type AttrValue = String;
type Identifier = LocalName;
type ClassName = LocalName;
type PartName = LocalName;
type LocalName = LocalName;
type NamespacePrefix = LocalName;
type AttrValue = CssString;
type Identifier = CssLocalName;
type LocalName = CssLocalName;
type NamespacePrefix = CssLocalName;
type NamespaceUrl = Namespace;
type BorrowedNamespaceUrl = Namespace;
type BorrowedLocalName = LocalName;
type BorrowedLocalName = CssLocalName;

type NonTSPseudoClass = NonTSPseudoClass;
type PseudoElement = PseudoElement;
Expand All @@ -84,6 +82,50 @@ impl parser::SelectorImpl for Simple {
type ExtraMatchingData = String;
}

/// Wraps [`String`] so that it can be used with [`selectors`]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CssString(pub String);

impl<'a> From<&'a str> for CssString {
fn from(val: &'a str) -> Self {
Self(val.to_owned())
}
}

impl AsRef<str> for CssString {
fn as_ref(&self) -> &str {
&self.0
}
}

impl cssparser::ToCss for CssString {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
where
W: fmt::Write,
{
cssparser::serialize_string(&self.0, dest)
}
}

/// Wraps [`LocalName`] so that it can be used with [`selectors`]
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct CssLocalName(pub LocalName);

impl<'a> From<&'a str> for CssLocalName {
fn from(val: &'a str) -> Self {
Self(val.into())
}
}

impl cssparser::ToCss for CssLocalName {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
where
W: fmt::Write,
{
dest.write_str(&self.0)
}
}

/// Non Tree-Structural Pseudo-Class.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NonTSPseudoClass {}
Expand All @@ -98,21 +140,6 @@ impl parser::NonTSPseudoClass for NonTSPseudoClass {
fn is_user_action_state(&self) -> bool {
false
}

fn has_zero_specificity(&self) -> bool {
false
}
}

impl parser::Visit for NonTSPseudoClass {
type Impl = Simple;

fn visit<V>(&self, _visitor: &mut V) -> bool
where
V: visitor::SelectorVisitor<Impl = Self::Impl>,
{
true
}
}

impl cssparser::ToCss for NonTSPseudoClass {
Expand Down

0 comments on commit a1ad314

Please sign in to comment.