Created
April 7, 2023 16:11
-
-
Save Leinnan/9c46bc762fc80773baedb43273fb4e8b to your computer and use it in GitHub Desktop.
0001-Add-parsing-pseudo-classes.patch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| From f1dcf7f96c37eb2b8f4215ca31ede61ce45bd192 Mon Sep 17 00:00:00 2001 | |
| From: Piotr Siuszko <siuszko@zoho.com> | |
| Date: Fri, 7 Apr 2023 18:10:16 +0200 | |
| Subject: [PATCH] Add parsing pseudo classes | |
| --- | |
| src/parser.rs | 23 ++++++++++++++--------- | |
| src/selector.rs | 27 +++++++++++++++++++++++---- | |
| src/system.rs | 4 ++++ | |
| 3 files changed, 41 insertions(+), 13 deletions(-) | |
| diff --git a/src/parser.rs b/src/parser.rs | |
| index 2d94699..0c93929 100644 | |
| --- a/src/parser.rs | |
| +++ b/src/parser.rs | |
| @@ -7,7 +7,7 @@ use smallvec::{smallvec, SmallVec}; | |
| use crate::{ | |
| property::PropertyValues, | |
| - selector::{Selector, SelectorElement}, | |
| + selector::{NextValueType, Selector, SelectorElement}, | |
| stylesheet::StyleRule, | |
| EcssError, | |
| }; | |
| @@ -72,18 +72,22 @@ impl<'i> QualifiedRuleParser<'i> for StyleSheetParser { | |
| ) -> Result<Self::Prelude, ParseError<'i, Self::Error>> { | |
| let mut elements = smallvec![]; | |
| - let mut next_is_class = false; | |
| + let mut next_value_type = NextValueType::default(); | |
| while let Ok(token) = input.next_including_whitespace() { | |
| use cssparser::Token::*; | |
| match token { | |
| Ident(v) => { | |
| - if next_is_class { | |
| - next_is_class = false; | |
| - elements.push(SelectorElement::Class(v.to_string())); | |
| - } else { | |
| - elements.push(SelectorElement::Component(v.to_string())); | |
| - } | |
| + match next_value_type { | |
| + NextValueType::Class => { | |
| + elements.push(SelectorElement::Class(v.to_string())); | |
| + } | |
| + NextValueType::PseudoClass => { | |
| + elements.push(SelectorElement::PseudoClass(v.to_string())); | |
| + } | |
| + _ => elements.push(SelectorElement::Component(v.to_string())), | |
| + }; | |
| + next_value_type = NextValueType::default(); | |
| } | |
| IDHash(v) => { | |
| if v.is_empty() { | |
| @@ -93,7 +97,8 @@ impl<'i> QualifiedRuleParser<'i> for StyleSheetParser { | |
| } | |
| } | |
| WhiteSpace(_) => elements.push(SelectorElement::Child), | |
| - Delim(c) if *c == '.' => next_is_class = true, | |
| + Delim(c) if *c == '.' => next_value_type = NextValueType::Class, | |
| + Colon => next_value_type = NextValueType::PseudoClass, | |
| _ => { | |
| let token = token.to_css_string(); | |
| return Err(input.new_custom_error(EcssError::UnexpectedToken(token))); | |
| diff --git a/src/selector.rs b/src/selector.rs | |
| index 67f2243..c2f4bcf 100644 | |
| --- a/src/selector.rs | |
| +++ b/src/selector.rs | |
| @@ -15,10 +15,19 @@ pub enum SelectorElement { | |
| Component(String), | |
| /// A class name component selector element, `.border` | |
| Class(String), | |
| + PseudoClass(String), | |
| /// Indicates a parent-child relation between previous elements and next elements, like `window .border` | |
| Child, | |
| } | |
| +#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)] | |
| +pub enum NextValueType { | |
| + #[default] | |
| + Unspecified, | |
| + Class, | |
| + PseudoClass, | |
| +} | |
| + | |
| /// A selector parsed from a `css` rule. Each selector has a internal hash used to differentiate between many rules in the same sheet. | |
| #[derive(Debug, Default, Clone)] | |
| pub struct Selector { | |
| @@ -76,6 +85,10 @@ impl std::fmt::Display for Selector { | |
| result.push('.'); | |
| result.push_str(c); | |
| } | |
| + SelectorElement::PseudoClass(c) => { | |
| + result.push(':'); | |
| + result.push_str(c); | |
| + } | |
| SelectorElement::Child => result.push(' '), | |
| } | |
| } | |
| @@ -117,23 +130,29 @@ impl Hash for Selector { | |
| impl<'i> From<Vec<CowRcStr<'i>>> for Selector { | |
| fn from(input: Vec<CowRcStr<'i>>) -> Self { | |
| let mut elements = smallvec![]; | |
| - let mut next_is_class = false; | |
| + let mut next_value_type = NextValueType::default(); | |
| for value in input.into_iter().filter(|v| !v.is_empty()) { | |
| if value.as_ref() == "." { | |
| - next_is_class = true; | |
| + next_value_type = NextValueType::Class; | |
| + continue; | |
| + } | |
| + if value.as_ref() == ":" { | |
| + next_value_type = NextValueType::PseudoClass; | |
| continue; | |
| } | |
| if let Some(value) = value.strip_prefix('#') { | |
| elements.push(SelectorElement::Name(value.to_string())); | |
| - } else if next_is_class { | |
| + } else if next_value_type == NextValueType::Class { | |
| elements.push(SelectorElement::Class(value.to_string())) | |
| + } else if next_value_type == NextValueType::PseudoClass { | |
| + elements.push(SelectorElement::PseudoClass(value.to_string())) | |
| } else { | |
| elements.push(SelectorElement::Component(value.to_string())) | |
| } | |
| - next_is_class = false; | |
| + next_value_type = NextValueType::default(); | |
| } | |
| Self::new(elements) | |
| diff --git a/src/system.rs b/src/system.rs | |
| index ab50251..d0152eb 100644 | |
| --- a/src/system.rs | |
| +++ b/src/system.rs | |
| @@ -167,6 +167,10 @@ fn select_entities_node( | |
| SelectorElement::Class(class) => { | |
| get_entities_with(class.as_str(), &css_query.classes, filter) | |
| } | |
| + SelectorElement::PseudoClass(_class) => { | |
| + // TODO how to handle that? | |
| + get_entities_with_component("interaction", world, registry, filter) | |
| + } | |
| SelectorElement::Component(component) => { | |
| get_entities_with_component(component.as_str(), world, registry, filter) | |
| } | |
| -- | |
| 2.40.0.windows.1 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment