Skip to content

Commit

Permalink
feat: impl attribute matching
Browse files Browse the repository at this point in the history
  • Loading branch information
huanghongxun committed Jan 2, 2025
1 parent 370f395 commit 7643c11
Show file tree
Hide file tree
Showing 11 changed files with 363 additions and 101 deletions.
18 changes: 9 additions & 9 deletions float-pigment-css/src/group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -790,21 +790,21 @@ impl StyleSheetGroup {
/// Query a single node selector (usually for testing only).
///
/// Note that the font size and `em` values will be converted to `px` values.
pub fn query_single<L: LengthNum>(
pub fn query_single<L: LengthNum, T: StyleNode>(
&self,
query: &StyleQuery,
query: T,
media_query_status: &MediaQueryStatus<L>,
node_properties: &mut NodeProperties,
) {
self.query_ancestor_path(&[query.clone()], media_query_status, node_properties, None)
self.query_ancestor_path(&[query], media_query_status, node_properties, None)
}

/// Find rules that matches the query.
///
/// The query is a `&[StyleQuery]` which means all selector information of the ancestors and the node itself.
pub fn for_each_matched_rule<L: LengthNum>(
pub fn for_each_matched_rule<L: LengthNum, T: StyleNode>(
&self,
query: &[StyleQuery],
query: &[T],
media_query_status: &MediaQueryStatus<L>,
mut f: impl FnMut(MatchedRuleRef, Option<&LinkedStyleSheet>),
) {
Expand All @@ -824,9 +824,9 @@ impl StyleSheetGroup {
/// Get a rule list that matches the query.
///
/// The query is a `&[StyleQuery]` which means all selector information of the ancestors and the node itself.
pub fn query_matched_rules<L: LengthNum>(
pub fn query_matched_rules<L: LengthNum, T: StyleNode>(
&self,
query: &[StyleQuery],
query: &[T],
media_query_status: &MediaQueryStatus<L>,
) -> MatchedRuleList {
let mut rules = vec![];
Expand All @@ -845,9 +845,9 @@ impl StyleSheetGroup {
///
/// The query is a `&[StyleQuery]` which means all selector information of the ancestors and the node itself.
/// Note that the font size and `em` values will be converted to `px` values.
pub fn query_ancestor_path<L: LengthNum>(
pub fn query_ancestor_path<L: LengthNum, T: StyleNode>(
&self,
query: &[StyleQuery],
query: &[T],
media_query_status: &MediaQueryStatus<L>,
node_properties: &mut NodeProperties,
parent_node_properties: Option<&NodeProperties>,
Expand Down
4 changes: 2 additions & 2 deletions float-pigment-css/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1611,15 +1611,15 @@ fn parse_attribute_selector<'a, 't: 'a, 'i: 't>(
// [name=value]
Ok(&Token::Delim('=')) => AttributeOperator::Exact,
// [name~=value]
Ok(&Token::IncludeMatch) => AttributeOperator::Contain,
Ok(&Token::IncludeMatch) => AttributeOperator::List,
// [name|=value]
Ok(&Token::DashMatch) => AttributeOperator::Hyphen,
// [name^=value]
Ok(&Token::PrefixMatch) => AttributeOperator::Begin,
// [name$=value]
Ok(&Token::SuffixMatch) => AttributeOperator::End,
// [name*=value]
Ok(&Token::SubstringMatch) => AttributeOperator::List,
Ok(&Token::SubstringMatch) => AttributeOperator::Contain,
Ok(_) => {
return Err(location.new_custom_error(CustomError::UnexpectedTokenInAttributeSelector))
}
Expand Down
131 changes: 121 additions & 10 deletions float-pigment-css/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,17 +85,65 @@ impl<L: LengthNum> MediaQueryStatus<L> {
}
}

pub trait StyleNodeClass {
fn name(&self) -> &str;
fn scope(&self) -> Option<NonZeroUsize>;
}

impl StyleNodeClass for (String, Option<NonZeroUsize>) {
fn name(&self) -> &str {
&self.0
}

fn scope(&self) -> Option<NonZeroUsize> {
self.1
}
}

pub trait StyleNode {
type Class: StyleNodeClass;
type ClassIter<'a>: Iterator<Item = &'a Self::Class>
where
Self: 'a;

fn style_scope(&self) -> Option<NonZeroUsize>;
fn extra_style_scope(&self) -> Option<NonZeroUsize>;
fn host_style_scope(&self) -> Option<NonZeroUsize>;
fn tag_name(&self) -> &str;
fn id(&self) -> Option<&str>;
fn classes(&self) -> Self::ClassIter<'_>;
fn attribute(&self, name: &str) -> Option<&str>;

fn contain_scope(&self, scope: Option<NonZeroUsize>) -> bool {
scope.is_none()
|| self.style_scope() == scope
|| self.extra_style_scope() == scope
|| self.host_style_scope() == scope
}
}

/// Represents node information, used for matching rules.
#[derive(Clone, Debug)]
#[derive(Debug)]
pub struct StyleQuery<'a> {
pub(super) style_scope: Option<NonZeroUsize>,
pub(super) extra_style_scope: Option<NonZeroUsize>,
pub(super) host_style_scope: Option<NonZeroUsize>,
pub(super) tag_name: &'a str,
pub(super) id: &'a str,
pub(super) classes: &'a [(String, Option<NonZeroUsize>)],
#[allow(unused)]
pub(super) attributes: &'a [String], // TODO support attributes
}

impl Clone for StyleQuery<'_> {
fn clone(&self) -> Self {
Self {
style_scope: self.style_scope,
extra_style_scope: self.extra_style_scope,
host_style_scope: self.host_style_scope,
tag_name: self.tag_name,
id: self.id,
classes: self.classes,
}
}
}

impl<'a> StyleQuery<'a> {
Expand All @@ -107,7 +155,6 @@ impl<'a> StyleQuery<'a> {
tag_name: &'a str,
id: &'a str,
classes: &'a [(String, Option<NonZeroUsize>)],
attributes: &'a [String],
) -> Self {
Self {
style_scope,
Expand All @@ -116,15 +163,79 @@ impl<'a> StyleQuery<'a> {
tag_name,
id,
classes,
attributes,
}
}
}

impl<'a> StyleNode for StyleQuery<'a> {
type Class = (String, Option<NonZeroUsize>);
type ClassIter<'c>
= core::slice::Iter<'c, Self::Class>
where
'a: 'c;

fn style_scope(&self) -> Option<NonZeroUsize> {
self.style_scope
}

pub(crate) fn contain_scope(&self, scope: Option<NonZeroUsize>) -> bool {
scope.is_none()
|| self.style_scope == scope
|| self.extra_style_scope == scope
|| self.host_style_scope == scope
fn extra_style_scope(&self) -> Option<NonZeroUsize> {
self.extra_style_scope
}

fn host_style_scope(&self) -> Option<NonZeroUsize> {
self.host_style_scope
}

fn tag_name(&self) -> &str {
self.tag_name
}

fn id(&self) -> Option<&str> {
Some(self.id)
}

fn classes(&self) -> Self::ClassIter<'_> {
self.classes.iter()
}

fn attribute(&self, name: &str) -> Option<&str> {
None
}
}

impl<'b, 'a: 'b> StyleNode for &'b StyleQuery<'a> {
type Class = (String, Option<NonZeroUsize>);
type ClassIter<'c>
= core::slice::Iter<'c, Self::Class>
where
'b: 'c;

fn style_scope(&self) -> Option<NonZeroUsize> {
self.style_scope
}

fn extra_style_scope(&self) -> Option<NonZeroUsize> {
self.extra_style_scope
}

fn host_style_scope(&self) -> Option<NonZeroUsize> {
self.host_style_scope
}

fn tag_name(&self) -> &str {
self.tag_name
}

fn id(&self) -> Option<&str> {
Some(self.id)
}

fn classes(&self) -> Self::ClassIter<'_> {
self.classes.iter()
}

fn attribute(&self, name: &str) -> Option<&str> {
None
}
}

Expand Down
14 changes: 7 additions & 7 deletions float-pigment-css/src/sheet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,9 +365,9 @@ impl LinkedStyleSheet {
Err(rule)
}

pub(crate) fn for_each_matched_rule<L: LengthNum>(
pub(crate) fn for_each_matched_rule<L: LengthNum, T: StyleNode>(
&self,
query: &[StyleQuery],
query: &[T],
media_query_status: &MediaQueryStatus<L>,
sheet_index: u16,
mut f: impl FnMut(MatchedRuleRef),
Expand Down Expand Up @@ -552,9 +552,9 @@ impl StyleSheet {
}
}

fn for_each_matched_rule<L: LengthNum>(
fn for_each_matched_rule<L: LengthNum, T: StyleNode>(
&mut self,
query: &[StyleQuery],
query: &[T],
media_query_status: &MediaQueryStatus<L>,
sheet_style_scope: Option<NonZeroUsize>,
sheet_index: u16,
Expand Down Expand Up @@ -589,9 +589,9 @@ impl StyleSheet {
Some(x) => x,
None => return,
};
for (class, scope) in query_last.classes.iter() {
if sheet_style_scope.is_none() || sheet_style_scope == *scope {
if let Some(rules) = class_index.get(class) {
for class in query_last.classes() {
if sheet_style_scope.is_none() || sheet_style_scope == class.scope() {
if let Some(rules) = class_index.get(class.name()) {
for r in rules {
if let Some(selector_weight) =
r.match_query(query, media_query_status, sheet_style_scope)
Expand Down
4 changes: 2 additions & 2 deletions float-pigment-css/src/sheet/rule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -457,9 +457,9 @@ impl Rule {
self.properties.iter()
}

pub(crate) fn match_query<L: LengthNum>(
pub(crate) fn match_query<L: LengthNum, T: StyleNode>(
&self,
query: &[StyleQuery],
query: &[T],
media_query_status: &MediaQueryStatus<L>,
sheet_style_scope: Option<NonZeroUsize>,
) -> Option<u16> {
Expand Down
Loading

0 comments on commit 7643c11

Please sign in to comment.