Handle uppercase I
in attribute selectors
This commit is contained in:
parent
3e45f05d97
commit
65030eb7ea
35
src/lexer.rs
35
src/lexer.rs
@ -4,7 +4,7 @@ use std::str::Chars;
|
|||||||
|
|
||||||
use crate::atrule::AtRuleKind;
|
use crate::atrule::AtRuleKind;
|
||||||
use crate::common::{Keyword, Op, Pos, Symbol};
|
use crate::common::{Keyword, Op, Pos, Symbol};
|
||||||
use crate::selector::{Attribute, AttributeKind};
|
use crate::selector::{Attribute, AttributeKind, CaseKind};
|
||||||
use crate::{Token, TokenKind, Whitespace};
|
use crate::{Token, TokenKind, Whitespace};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -243,7 +243,7 @@ impl<'a> Lexer<'a> {
|
|||||||
kind: AttributeKind::Any,
|
kind: AttributeKind::Any,
|
||||||
attr,
|
attr,
|
||||||
value: String::new(),
|
value: String::new(),
|
||||||
case_sensitive: true,
|
case_sensitive: CaseKind::Sensitive,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
'i' => {
|
'i' => {
|
||||||
@ -253,7 +253,17 @@ impl<'a> Lexer<'a> {
|
|||||||
kind: AttributeKind::Any,
|
kind: AttributeKind::Any,
|
||||||
attr,
|
attr,
|
||||||
value: String::new(),
|
value: String::new(),
|
||||||
case_sensitive: false,
|
case_sensitive: CaseKind::InsensitiveLowercase,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
'I' => {
|
||||||
|
self.devour_whitespace();
|
||||||
|
assert!(self.buf.next() == Some(']'));
|
||||||
|
return TokenKind::Attribute(Attribute {
|
||||||
|
kind: AttributeKind::Any,
|
||||||
|
attr,
|
||||||
|
value: String::new(),
|
||||||
|
case_sensitive: CaseKind::InsensitiveCapital,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
'=' => AttributeKind::Equals,
|
'=' => AttributeKind::Equals,
|
||||||
@ -272,14 +282,19 @@ impl<'a> Lexer<'a> {
|
|||||||
self.devour_whitespace();
|
self.devour_whitespace();
|
||||||
|
|
||||||
let mut value = String::with_capacity(99);
|
let mut value = String::with_capacity(99);
|
||||||
let mut case_sensitive = true;
|
let mut case_sensitive = CaseKind::Sensitive;
|
||||||
|
|
||||||
while let Some(c) = self.buf.peek() {
|
while let Some(c) = self.buf.peek() {
|
||||||
if !c.is_alphabetic() && c != &'-' && c != &'_' && c != &'"' && c != &'\'' {
|
if !c.is_alphabetic() && c != &'-' && c != &'_' && c != &'"' && c != &'\'' {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if c == &'i' {
|
if c == &'i' || c == &'I' {
|
||||||
|
if c == &'i' {
|
||||||
|
case_sensitive = CaseKind::InsensitiveLowercase;
|
||||||
|
} else if c == &'I' {
|
||||||
|
case_sensitive = CaseKind::InsensitiveCapital;
|
||||||
|
}
|
||||||
let tok = self
|
let tok = self
|
||||||
.buf
|
.buf
|
||||||
.next()
|
.next()
|
||||||
@ -287,7 +302,14 @@ impl<'a> Lexer<'a> {
|
|||||||
self.pos.next_char();
|
self.pos.next_char();
|
||||||
self.devour_whitespace();
|
self.devour_whitespace();
|
||||||
match self.buf.next() {
|
match self.buf.next() {
|
||||||
Some(']') => case_sensitive = false,
|
Some(']') => {
|
||||||
|
return TokenKind::Attribute(Attribute {
|
||||||
|
kind,
|
||||||
|
attr,
|
||||||
|
value,
|
||||||
|
case_sensitive,
|
||||||
|
})
|
||||||
|
}
|
||||||
Some(val) => {
|
Some(val) => {
|
||||||
self.pos.next_char();
|
self.pos.next_char();
|
||||||
value.push(tok);
|
value.push(tok);
|
||||||
@ -304,6 +326,7 @@ impl<'a> Lexer<'a> {
|
|||||||
.expect("this is impossible because we have already peeked");
|
.expect("this is impossible because we have already peeked");
|
||||||
self.pos.next_char();
|
self.pos.next_char();
|
||||||
value.push(tok);
|
value.push(tok);
|
||||||
|
self.devour_whitespace();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.devour_whitespace();
|
self.devour_whitespace();
|
||||||
|
@ -329,38 +329,51 @@ impl Selector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct Attribute {
|
pub(crate) struct Attribute {
|
||||||
pub attr: String,
|
pub attr: String,
|
||||||
pub value: String,
|
pub value: String,
|
||||||
pub case_sensitive: bool,
|
pub case_sensitive: CaseKind,
|
||||||
pub kind: AttributeKind,
|
pub kind: AttributeKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub(crate) enum CaseKind {
|
||||||
|
InsensitiveCapital,
|
||||||
|
InsensitiveLowercase,
|
||||||
|
Sensitive,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for CaseKind {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::InsensitiveCapital => write!(f, " I"),
|
||||||
|
Self::InsensitiveLowercase => write!(f, " i"),
|
||||||
|
Self::Sensitive => write!(f, ""),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for Attribute {
|
impl Display for Attribute {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
if self.case_sensitive {
|
match self.kind {
|
||||||
match self.kind {
|
AttributeKind::Any => write!(f, "[{}{}]", self.attr, self.case_sensitive),
|
||||||
AttributeKind::Any => write!(f, "[{}]", self.attr),
|
AttributeKind::Equals => {
|
||||||
AttributeKind::Equals => write!(f, "[{}={}]", self.attr, self.value),
|
write!(f, "[{}={}{}]", self.attr, self.value, self.case_sensitive)
|
||||||
AttributeKind::InList => write!(f, "[{}~={}]", self.attr, self.value),
|
|
||||||
AttributeKind::BeginsWithHyphenOrExact => {
|
|
||||||
write!(f, "[{}|={}]", self.attr, self.value)
|
|
||||||
}
|
|
||||||
AttributeKind::StartsWith => write!(f, "[{}^={}]", self.attr, self.value),
|
|
||||||
AttributeKind::EndsWith => write!(f, "[{}$={}]", self.attr, self.value),
|
|
||||||
AttributeKind::Contains => write!(f, "[{}*={}]", self.attr, self.value),
|
|
||||||
}
|
}
|
||||||
} else {
|
AttributeKind::InList => {
|
||||||
match self.kind {
|
write!(f, "[{}~={}{}]", self.attr, self.value, self.case_sensitive)
|
||||||
AttributeKind::Any => write!(f, "[{} i]", self.attr),
|
}
|
||||||
AttributeKind::Equals => write!(f, "[{}={} i]", self.attr, self.value),
|
AttributeKind::BeginsWithHyphenOrExact => {
|
||||||
AttributeKind::InList => write!(f, "[{}~={} i]", self.attr, self.value),
|
write!(f, "[{}|={}{}]", self.attr, self.value, self.case_sensitive)
|
||||||
AttributeKind::BeginsWithHyphenOrExact => {
|
}
|
||||||
write!(f, "[{}|={} i]", self.attr, self.value)
|
AttributeKind::StartsWith => {
|
||||||
}
|
write!(f, "[{}^={}{}]", self.attr, self.value, self.case_sensitive)
|
||||||
AttributeKind::StartsWith => write!(f, "[{}^={} i]", self.attr, self.value),
|
}
|
||||||
AttributeKind::EndsWith => write!(f, "[{}$={} i]", self.attr, self.value),
|
AttributeKind::EndsWith => {
|
||||||
AttributeKind::Contains => write!(f, "[{}*={} i]", self.attr, self.value),
|
write!(f, "[{}$={}{}]", self.attr, self.value, self.case_sensitive)
|
||||||
|
}
|
||||||
|
AttributeKind::Contains => {
|
||||||
|
write!(f, "[{}*={}{}]", self.attr, self.value, self.case_sensitive)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,6 +127,14 @@ mod test_selectors {
|
|||||||
);
|
);
|
||||||
|
|
||||||
test!(selector_attribute_any, "[attr] {\n color: red;\n}\n");
|
test!(selector_attribute_any, "[attr] {\n color: red;\n}\n");
|
||||||
|
test!(
|
||||||
|
selector_attribute_any_lower_case_insensitive,
|
||||||
|
"[attr i] {\n color: red;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
selector_attribute_any_upper_case_insensitive,
|
||||||
|
"[attr I] {\n color: red;\n}\n"
|
||||||
|
);
|
||||||
test!(
|
test!(
|
||||||
selector_attribute_equals,
|
selector_attribute_equals,
|
||||||
"[attr=val] {\n color: red;\n}\n"
|
"[attr=val] {\n color: red;\n}\n"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user