more robustly parse !optional
in selectors
This commit is contained in:
parent
36a55e582c
commit
38a37a3997
@ -7,7 +7,7 @@ use crate::{
|
|||||||
use super::Parser;
|
use super::Parser;
|
||||||
|
|
||||||
impl<'a> Parser<'a> {
|
impl<'a> Parser<'a> {
|
||||||
pub fn scan_identifier(&mut self, ident: &str) -> SassResult<bool> {
|
pub fn scan_identifier(&mut self, ident: &'static str) -> SassResult<bool> {
|
||||||
let peeked_identifier =
|
let peeked_identifier =
|
||||||
match peek_ident_no_interpolation(self.toks, false, self.span_before) {
|
match peek_ident_no_interpolation(self.toks, false, self.span_before) {
|
||||||
Ok(v) => v.node,
|
Ok(v) => v.node,
|
||||||
|
@ -17,10 +17,7 @@ use crate::{
|
|||||||
ComplexSelectorComponent, ExtendRule, ExtendedSelector, Extender, Selector, SelectorParser,
|
ComplexSelectorComponent, ExtendRule, ExtendedSelector, Extender, Selector, SelectorParser,
|
||||||
},
|
},
|
||||||
style::Style,
|
style::Style,
|
||||||
utils::{
|
utils::{read_until_closing_curly_brace, read_until_semicolon_or_closing_curly_brace},
|
||||||
peek_ident_no_interpolation, read_until_closing_curly_brace,
|
|
||||||
read_until_semicolon_or_closing_curly_brace,
|
|
||||||
},
|
|
||||||
value::Value,
|
value::Value,
|
||||||
Options, {Cow, Token},
|
Options, {Cow, Token},
|
||||||
};
|
};
|
||||||
@ -134,6 +131,16 @@ impl<'a> Parser<'a> {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn expect_identifier(&mut self, ident: &'static str) -> SassResult<()> {
|
||||||
|
let this_ident = self.parse_identifier_no_interpolation(false)?;
|
||||||
|
self.span_before = this_ident.span;
|
||||||
|
if this_ident.node == ident {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
Err((format!("Expected \"{}\".", ident), self.span_before).into())
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_stmt(&mut self) -> SassResult<Vec<Stmt>> {
|
fn parse_stmt(&mut self) -> SassResult<Vec<Stmt>> {
|
||||||
let mut stmts = Vec::new();
|
let mut stmts = Vec::new();
|
||||||
while let Some(Token { kind, pos }) = self.toks.peek() {
|
while let Some(Token { kind, pos }) = self.toks.peek() {
|
||||||
@ -420,13 +427,11 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
'!' => {
|
'!' => {
|
||||||
if peek_ident_no_interpolation(self.toks, false, self.span_before)?.node
|
if from_fn {
|
||||||
== "optional"
|
self.expect_identifier("optional")?;
|
||||||
{
|
|
||||||
self.toks.truncate_iterator_to_cursor();
|
|
||||||
optional = true;
|
optional = true;
|
||||||
} else {
|
} else {
|
||||||
string.push('!');
|
return Err(("expected \"{\".", tok.pos).into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c => string.push(c),
|
c => string.push(c),
|
||||||
|
@ -1882,6 +1882,13 @@ test!(
|
|||||||
}",
|
}",
|
||||||
":has(a >) b, :has(a >) :has(a >) :has(a >) b, :has(a >) :has(a >) :has(a >) b {\n color: red;\n}\n"
|
":has(a >) b, :has(a >) :has(a >) :has(a >) b, :has(a >) :has(a >) :has(a >) b {\n color: red;\n}\n"
|
||||||
);
|
);
|
||||||
|
error!(
|
||||||
|
extend_optional_keyword_not_complete,
|
||||||
|
"a {
|
||||||
|
@extend a !opt;
|
||||||
|
}",
|
||||||
|
"Error: Expected \"optional\"."
|
||||||
|
);
|
||||||
|
|
||||||
// todo: extend_loop (massive test)
|
// todo: extend_loop (massive test)
|
||||||
// todo: extend tests in folders
|
// todo: extend tests in folders
|
||||||
|
@ -712,3 +712,7 @@ error!(
|
|||||||
toplevel_parent_selector_after_element,
|
toplevel_parent_selector_after_element,
|
||||||
"a&{}", "Error: \"&\" may only used at the beginning of a compound selector."
|
"a&{}", "Error: \"&\" may only used at the beginning of a compound selector."
|
||||||
);
|
);
|
||||||
|
error!(
|
||||||
|
denies_optional_in_selector,
|
||||||
|
"a !optional {}", "Error: expected \"{\"."
|
||||||
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user