lazily compute normalized name of psuedo selector
This commit is contained in:
parent
1ae9cdbb23
commit
4379e1e3b7
@ -600,7 +600,7 @@ fn first_if_root(queue: &mut VecDeque<ComplexSelectorComponent>) -> Option<Compo
|
|||||||
fn has_root(compound: &CompoundSelector) -> bool {
|
fn has_root(compound: &CompoundSelector) -> bool {
|
||||||
compound.components.iter().any(|simple| {
|
compound.components.iter().any(|simple| {
|
||||||
if let SimpleSelector::Pseudo(pseudo) = simple {
|
if let SimpleSelector::Pseudo(pseudo) = simple {
|
||||||
pseudo.is_class && &*pseudo.normalized_name == "root"
|
pseudo.is_class && pseudo.normalized_name() == "root"
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -598,7 +598,7 @@ impl Extender {
|
|||||||
// writing. We can keep them if either the original selector had a complex
|
// writing. We can keep them if either the original selector had a complex
|
||||||
// selector, or the result of extending has only complex selectors, because
|
// selector, or the result of extending has only complex selectors, because
|
||||||
// either way we aren't breaking anything that isn't already broken.
|
// either way we aren't breaking anything that isn't already broken.
|
||||||
let mut complexes = if &*pseudo.normalized_name == "not"
|
let mut complexes = if pseudo.normalized_name() == "not"
|
||||||
&& !pseudo
|
&& !pseudo
|
||||||
.selector
|
.selector
|
||||||
.clone()
|
.clone()
|
||||||
@ -644,7 +644,7 @@ impl Extender {
|
|||||||
return vec![complex];
|
return vec![complex];
|
||||||
}
|
}
|
||||||
|
|
||||||
match &*pseudo.normalized_name {
|
match pseudo.normalized_name() {
|
||||||
"not" => {
|
"not" => {
|
||||||
// In theory, if there's a `:not` nested within another `:not`, the
|
// In theory, if there's a `:not` nested within another `:not`, the
|
||||||
// inner `:not`'s contents should be unified with the return value.
|
// inner `:not`'s contents should be unified with the return value.
|
||||||
@ -652,7 +652,7 @@ impl Extender {
|
|||||||
// become `.foo:not(.bar)`. However, this is a narrow edge case and
|
// become `.foo:not(.bar)`. However, this is a narrow edge case and
|
||||||
// supporting it properly would make this code and the code calling it
|
// supporting it properly would make this code and the code calling it
|
||||||
// a lot more complicated, so it's not supported for now.
|
// a lot more complicated, so it's not supported for now.
|
||||||
if &*inner_pseudo.normalized_name == "matches" {
|
if inner_pseudo.normalized_name() == "matches" {
|
||||||
inner_pseudo.selector.clone().unwrap().components
|
inner_pseudo.selector.clone().unwrap().components
|
||||||
} else {
|
} else {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
@ -684,7 +684,7 @@ impl Extender {
|
|||||||
// Older browsers support `:not`, but only with a single complex selector.
|
// Older browsers support `:not`, but only with a single complex selector.
|
||||||
// In order to support those browsers, we break up the contents of a `:not`
|
// In order to support those browsers, we break up the contents of a `:not`
|
||||||
// unless it originally contained a selector list.
|
// unless it originally contained a selector list.
|
||||||
if &*pseudo.normalized_name == "not"
|
if pseudo.normalized_name() == "not"
|
||||||
&& pseudo.selector.clone().unwrap().components.len() == 1
|
&& pseudo.selector.clone().unwrap().components.len() == 1
|
||||||
{
|
{
|
||||||
let result = complexes
|
let result = complexes
|
||||||
|
@ -295,8 +295,6 @@ impl<'a, 'b> SelectorParser<'a, 'b> {
|
|||||||
Some(Token { kind: '(', .. }) => self.parser.toks.next(),
|
Some(Token { kind: '(', .. }) => self.parser.toks.next(),
|
||||||
_ => {
|
_ => {
|
||||||
return Ok(SimpleSelector::Pseudo(Pseudo {
|
return Ok(SimpleSelector::Pseudo(Pseudo {
|
||||||
// todo: we can store the reference to this
|
|
||||||
normalized_name: unvendor(&name.node).to_string().into_boxed_str(),
|
|
||||||
is_class: !element && !is_fake_pseudo_element(&name),
|
is_class: !element && !is_fake_pseudo_element(&name),
|
||||||
name: name.node,
|
name: name.node,
|
||||||
selector: None,
|
selector: None,
|
||||||
@ -353,7 +351,6 @@ impl<'a, 'b> SelectorParser<'a, 'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ok(SimpleSelector::Pseudo(Pseudo {
|
Ok(SimpleSelector::Pseudo(Pseudo {
|
||||||
normalized_name: unvendor(&name.node).to_string().into_boxed_str(),
|
|
||||||
is_class: !element && !is_fake_pseudo_element(&name),
|
is_class: !element && !is_fake_pseudo_element(&name),
|
||||||
name: name.node,
|
name: name.node,
|
||||||
selector,
|
selector,
|
||||||
|
@ -5,7 +5,7 @@ use std::{
|
|||||||
|
|
||||||
use codemap::Span;
|
use codemap::Span;
|
||||||
|
|
||||||
use crate::error::SassResult;
|
use crate::{common::unvendor, error::SassResult};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
Attribute, ComplexSelector, ComplexSelectorComponent, CompoundSelector, Namespace,
|
Attribute, ComplexSelector, ComplexSelectorComponent, CompoundSelector, Namespace,
|
||||||
@ -353,11 +353,11 @@ impl SimpleSelector {
|
|||||||
}
|
}
|
||||||
if let SimpleSelector::Pseudo(Pseudo {
|
if let SimpleSelector::Pseudo(Pseudo {
|
||||||
selector: Some(sel),
|
selector: Some(sel),
|
||||||
normalized_name,
|
name,
|
||||||
..
|
..
|
||||||
}) = their_simple
|
}) = their_simple
|
||||||
{
|
{
|
||||||
if SUBSELECTOR_PSEUDOS.contains(&&**normalized_name) {
|
if SUBSELECTOR_PSEUDOS.contains(&unvendor(&name)) {
|
||||||
return sel.components.iter().all(|complex| {
|
return sel.components.iter().all(|complex| {
|
||||||
if complex.components.len() != 1 {
|
if complex.components.len() != 1 {
|
||||||
return false;
|
return false;
|
||||||
@ -384,9 +384,6 @@ pub(crate) struct Pseudo {
|
|||||||
/// The name of this selector.
|
/// The name of this selector.
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
||||||
/// Like `name`, but without any vendor prefixes.
|
|
||||||
pub normalized_name: Box<str>,
|
|
||||||
|
|
||||||
/// Whether this is a pseudo-class selector.
|
/// Whether this is a pseudo-class selector.
|
||||||
///
|
///
|
||||||
/// If this is false, this is a pseudo-element selector
|
/// If this is false, this is a pseudo-element selector
|
||||||
@ -489,7 +486,7 @@ impl Pseudo {
|
|||||||
parents: Option<Vec<ComplexSelectorComponent>>,
|
parents: Option<Vec<ComplexSelectorComponent>>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
debug_assert!(self.selector.is_some());
|
debug_assert!(self.selector.is_some());
|
||||||
match &*self.normalized_name {
|
match self.normalized_name() {
|
||||||
"matches" | "any" => {
|
"matches" | "any" => {
|
||||||
let pseudos = selector_pseudos_named(compound.clone(), &self.name, true);
|
let pseudos = selector_pseudos_named(compound.clone(), &self.name, true);
|
||||||
pseudos.iter().any(move |pseudo2| {
|
pseudos.iter().any(move |pseudo2| {
|
||||||
@ -647,6 +644,11 @@ impl Pseudo {
|
|||||||
Specificity { min, max }
|
Specificity { min, max }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Like `name`, but without any vendor prefixes.
|
||||||
|
pub fn normalized_name(&self) -> &str {
|
||||||
|
unvendor(&self.name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns all pseudo selectors in `compound` that have a selector argument,
|
/// Returns all pseudo selectors in `compound` that have a selector argument,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user