mirror of
https://github.com/swc-project/swc.git
synced 2024-12-25 22:56:11 +03:00
fix(css/parser): Fix a bug with scope in block (#6402)
This commit is contained in:
parent
fafc6257c8
commit
3d7545d89b
@ -565,7 +565,7 @@ where
|
|||||||
| js_word!("-o-keyframes")
|
| js_word!("-o-keyframes")
|
||||||
| js_word!("-ms-keyframes") => {
|
| js_word!("-ms-keyframes") => {
|
||||||
let ctx = Ctx {
|
let ctx = Ctx {
|
||||||
block_contents_grammar: BlockContentsGrammar::DeclarationList,
|
block_contents_grammar: BlockContentsGrammar::RuleList,
|
||||||
is_top_level: false,
|
is_top_level: false,
|
||||||
in_keyframes_at_rule: true,
|
in_keyframes_at_rule: true,
|
||||||
..self.ctx
|
..self.ctx
|
||||||
|
@ -134,24 +134,18 @@ where
|
|||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let (normalized_at_rule_name, name) = if at_keyword_name.0.starts_with("--") {
|
let name = if at_keyword_name.0.starts_with("--") {
|
||||||
(
|
|
||||||
at_keyword_name.0.to_ascii_lowercase(),
|
|
||||||
AtRuleName::DashedIdent(DashedIdent {
|
AtRuleName::DashedIdent(DashedIdent {
|
||||||
span: Span::new(span.lo + BytePos(1), span.hi, Default::default()),
|
span: Span::new(span.lo + BytePos(1), span.hi, Default::default()),
|
||||||
value: at_keyword_name.0,
|
value: at_keyword_name.0,
|
||||||
raw: Some(at_keyword_name.1),
|
raw: Some(at_keyword_name.1),
|
||||||
}),
|
})
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
(
|
|
||||||
at_keyword_name.0.to_ascii_lowercase(),
|
|
||||||
AtRuleName::Ident(Ident {
|
AtRuleName::Ident(Ident {
|
||||||
span: Span::new(span.lo + BytePos(1), span.hi, Default::default()),
|
span: Span::new(span.lo + BytePos(1), span.hi, Default::default()),
|
||||||
value: at_keyword_name.0,
|
value: at_keyword_name.0,
|
||||||
raw: Some(at_keyword_name.1),
|
raw: Some(at_keyword_name.1),
|
||||||
}),
|
})
|
||||||
)
|
|
||||||
};
|
};
|
||||||
let mut prelude = vec![];
|
let mut prelude = vec![];
|
||||||
let mut at_rule = AtRule {
|
let mut at_rule = AtRule {
|
||||||
@ -181,103 +175,31 @@ where
|
|||||||
tok!(";") => {
|
tok!(";") => {
|
||||||
self.input.bump();
|
self.input.bump();
|
||||||
|
|
||||||
let list_of_component_values = self.create_locv(prelude);
|
at_rule.prelude = Some(Box::new(AtRulePrelude::ListOfComponentValues(
|
||||||
|
self.create_locv(prelude),
|
||||||
at_rule.prelude = match self
|
)));
|
||||||
.parse_according_to_grammar(&list_of_component_values, |parser| {
|
|
||||||
parser.parse_at_rule_prelude(&normalized_at_rule_name)
|
|
||||||
}) {
|
|
||||||
Ok(at_rule_prelude) => match at_rule_prelude {
|
|
||||||
None if normalized_at_rule_name == js_word!("layer") => {
|
|
||||||
self.errors.push(Error::new(
|
|
||||||
span,
|
|
||||||
ErrorKind::Expected("at least one name"),
|
|
||||||
));
|
|
||||||
|
|
||||||
Some(Box::new(AtRulePrelude::ListOfComponentValues(
|
|
||||||
list_of_component_values,
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
_ => at_rule_prelude.map(Box::new),
|
|
||||||
},
|
|
||||||
Err(err) => {
|
|
||||||
if *err.kind() != ErrorKind::Ignore {
|
|
||||||
self.errors.push(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !list_of_component_values.children.is_empty() {
|
|
||||||
Some(Box::new(AtRulePrelude::ListOfComponentValues(
|
|
||||||
list_of_component_values,
|
|
||||||
)))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
at_rule.span = span!(self, span.lo);
|
at_rule.span = span!(self, span.lo);
|
||||||
|
|
||||||
|
// Canonicalization against a grammar
|
||||||
|
at_rule = self.canonicalize_at_rule_prelude(at_rule)?;
|
||||||
|
|
||||||
return Ok(at_rule);
|
return Ok(at_rule);
|
||||||
}
|
}
|
||||||
// <{-token>
|
// <{-token>
|
||||||
// Consume a simple block and assign it to the at-rule’s block. Return the at-rule.
|
// Consume a simple block and assign it to the at-rule’s block. Return the at-rule.
|
||||||
tok!("{") => {
|
tok!("{") => {
|
||||||
let mut block = self.parse_as::<SimpleBlock>()?;
|
let block = self.parse_as::<SimpleBlock>()?;
|
||||||
|
|
||||||
let list_of_component_values = self.create_locv(prelude);
|
at_rule.prelude = Some(Box::new(AtRulePrelude::ListOfComponentValues(
|
||||||
|
self.create_locv(prelude),
|
||||||
at_rule.prelude = match self
|
)));
|
||||||
.parse_according_to_grammar(&list_of_component_values, |parser| {
|
at_rule.block = Some(block);
|
||||||
parser.parse_at_rule_prelude(&normalized_at_rule_name)
|
|
||||||
}) {
|
|
||||||
Ok(at_rule_prelude) => match at_rule_prelude {
|
|
||||||
Some(AtRulePrelude::LayerPrelude(LayerPrelude::NameList(
|
|
||||||
name_list,
|
|
||||||
))) if name_list.name_list.len() > 1 => {
|
|
||||||
self.errors.push(Error::new(
|
|
||||||
name_list.span,
|
|
||||||
ErrorKind::Expected("only one name"),
|
|
||||||
));
|
|
||||||
|
|
||||||
Some(Box::new(AtRulePrelude::ListOfComponentValues(
|
|
||||||
list_of_component_values,
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
_ => at_rule_prelude.map(Box::new),
|
|
||||||
},
|
|
||||||
Err(err) => {
|
|
||||||
if *err.kind() != ErrorKind::Ignore {
|
|
||||||
self.errors.push(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !list_of_component_values.children.is_empty() {
|
|
||||||
Some(Box::new(AtRulePrelude::ListOfComponentValues(
|
|
||||||
list_of_component_values,
|
|
||||||
)))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
at_rule.block = match self.parse_according_to_grammar(
|
|
||||||
&self.create_locv(block.value.clone()),
|
|
||||||
|parser| parser.parse_at_rule_block(&normalized_at_rule_name),
|
|
||||||
) {
|
|
||||||
Ok(block_contents) => {
|
|
||||||
block.value = block_contents;
|
|
||||||
|
|
||||||
Some(block)
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
if *err.kind() != ErrorKind::Ignore {
|
|
||||||
self.errors.push(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(block)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
at_rule.span = span!(self, span.lo);
|
at_rule.span = span!(self, span.lo);
|
||||||
|
|
||||||
|
// Canonicalization against a grammar
|
||||||
|
at_rule = self.canonicalize_at_rule_prelude(at_rule)?;
|
||||||
|
at_rule = self.canonicalize_at_rule_block(at_rule)?;
|
||||||
|
|
||||||
return Ok(at_rule);
|
return Ok(at_rule);
|
||||||
}
|
}
|
||||||
// anything else
|
// anything else
|
||||||
@ -299,50 +221,10 @@ where
|
|||||||
{
|
{
|
||||||
fn parse(&mut self) -> PResult<QualifiedRule> {
|
fn parse(&mut self) -> PResult<QualifiedRule> {
|
||||||
// To consume a qualified rule:
|
// To consume a qualified rule:
|
||||||
let create_prelude =
|
|
||||||
|p: &mut Parser<I>, list: Vec<ComponentValue>| -> PResult<QualifiedRulePrelude> {
|
|
||||||
let list_of_component_values = p.create_locv(list);
|
|
||||||
|
|
||||||
if p.ctx.in_keyframes_at_rule {
|
|
||||||
Ok(QualifiedRulePrelude::ListOfComponentValues(
|
|
||||||
list_of_component_values,
|
|
||||||
))
|
|
||||||
} else if p.ctx.mixed_with_declarations {
|
|
||||||
match p.parse_according_to_grammar::<RelativeSelectorList>(
|
|
||||||
&list_of_component_values,
|
|
||||||
|parser| parser.parse(),
|
|
||||||
) {
|
|
||||||
Ok(relative_selector_list) => Ok(
|
|
||||||
QualifiedRulePrelude::RelativeSelectorList(relative_selector_list),
|
|
||||||
),
|
|
||||||
Err(err) => {
|
|
||||||
p.errors.push(err);
|
|
||||||
|
|
||||||
Ok(QualifiedRulePrelude::ListOfComponentValues(
|
|
||||||
list_of_component_values,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
match p.parse_according_to_grammar::<SelectorList>(
|
|
||||||
&list_of_component_values,
|
|
||||||
|parser| parser.parse(),
|
|
||||||
) {
|
|
||||||
Ok(selector_list) => Ok(QualifiedRulePrelude::SelectorList(selector_list)),
|
|
||||||
Err(err) => {
|
|
||||||
p.errors.push(err);
|
|
||||||
|
|
||||||
Ok(QualifiedRulePrelude::ListOfComponentValues(
|
|
||||||
list_of_component_values,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let span = self.input.cur_span();
|
|
||||||
// Create a new qualified rule with its prelude initially set to an empty list,
|
// Create a new qualified rule with its prelude initially set to an empty list,
|
||||||
// and its value initially set to nothing.
|
// and its value initially set to nothing.
|
||||||
|
let span = self.input.cur_span();
|
||||||
let mut prelude = vec![];
|
let mut prelude = vec![];
|
||||||
|
|
||||||
// Repeatedly consume the next input token:
|
// Repeatedly consume the next input token:
|
||||||
@ -375,30 +257,20 @@ where
|
|||||||
// Consume a simple block and assign it to the qualified rule’s block. Return the
|
// Consume a simple block and assign it to the qualified rule’s block. Return the
|
||||||
// qualified rule.
|
// qualified rule.
|
||||||
tok!("{") => {
|
tok!("{") => {
|
||||||
let mut block = self.parse_as::<SimpleBlock>()?;
|
let block = self.parse_as::<SimpleBlock>()?;
|
||||||
|
let mut qualified_rule = QualifiedRule {
|
||||||
block.value = match self.ctx.block_contents_grammar {
|
span: span!(self, span.lo),
|
||||||
BlockContentsGrammar::DeclarationList => self
|
prelude: QualifiedRulePrelude::ListOfComponentValues(
|
||||||
.parse_according_to_grammar(&self.create_locv(block.value), |parser| {
|
self.create_locv(prelude),
|
||||||
parser.parse_as::<Vec<DeclarationOrAtRule>>()
|
),
|
||||||
})?
|
block,
|
||||||
.into_iter()
|
|
||||||
.map(ComponentValue::DeclarationOrAtRule)
|
|
||||||
.collect(),
|
|
||||||
_ => self
|
|
||||||
.parse_according_to_grammar(&self.create_locv(block.value), |parser| {
|
|
||||||
parser.parse_as::<Vec<StyleBlock>>()
|
|
||||||
})?
|
|
||||||
.into_iter()
|
|
||||||
.map(ComponentValue::StyleBlock)
|
|
||||||
.collect(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return Ok(QualifiedRule {
|
// Canonicalization against a grammar
|
||||||
span: span!(self, span.lo),
|
qualified_rule = self.canonicalize_qualified_rule_prelude(qualified_rule)?;
|
||||||
prelude: create_prelude(self, prelude)?,
|
qualified_rule = self.canonicalize_qualified_rule_block(qualified_rule)?;
|
||||||
block,
|
|
||||||
});
|
return Ok(qualified_rule);
|
||||||
}
|
}
|
||||||
// Reconsume the current input token. Consume a component value. Append the returned
|
// Reconsume the current input token. Consume a component value. Append the returned
|
||||||
// value to the qualified rule’s prelude.
|
// value to the qualified rule’s prelude.
|
||||||
@ -458,12 +330,7 @@ where
|
|||||||
// Reconsume the current input token. Consume an at-rule, and append the result to
|
// Reconsume the current input token. Consume an at-rule, and append the result to
|
||||||
// rules.
|
// rules.
|
||||||
tok!("@") => {
|
tok!("@") => {
|
||||||
let at_rule = self
|
let at_rule = self.parse()?;
|
||||||
.with_ctx(Ctx {
|
|
||||||
block_contents_grammar: BlockContentsGrammar::StyleBlock,
|
|
||||||
..self.ctx
|
|
||||||
})
|
|
||||||
.parse_as::<AtRule>()?;
|
|
||||||
|
|
||||||
rules.push(StyleBlock::AtRule(Box::new(at_rule)));
|
rules.push(StyleBlock::AtRule(Box::new(at_rule)));
|
||||||
}
|
}
|
||||||
@ -880,32 +747,8 @@ where
|
|||||||
return Ok(declaration);
|
return Ok(declaration);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grammar parsing
|
// Canonicalization against a grammar
|
||||||
let list_of_component_values = self.create_locv(declaration.value);
|
declaration = self.canonicalize_declaration_value(declaration)?;
|
||||||
|
|
||||||
declaration.value =
|
|
||||||
match self.parse_according_to_grammar(&list_of_component_values, |parser| {
|
|
||||||
let mut values = vec![];
|
|
||||||
|
|
||||||
loop {
|
|
||||||
if is!(parser, EOF) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
values.push(parser.parse_generic_value()?);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(values)
|
|
||||||
}) {
|
|
||||||
Ok(values) => values,
|
|
||||||
Err(err) => {
|
|
||||||
if *err.kind() != ErrorKind::Ignore {
|
|
||||||
self.errors.push(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
list_of_component_values.children
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 8. Return the declaration.
|
// 8. Return the declaration.
|
||||||
Ok(declaration)
|
Ok(declaration)
|
||||||
@ -1055,9 +898,8 @@ where
|
|||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let function_name = &*ident.0.to_ascii_lowercase();
|
|
||||||
let name = Ident {
|
let name = Ident {
|
||||||
span: swc_common::Span::new(span.lo, span.hi - BytePos(1), Default::default()),
|
span: Span::new(span.lo, span.hi - BytePos(1), Default::default()),
|
||||||
value: ident.0,
|
value: ident.0,
|
||||||
raw: Some(ident.1),
|
raw: Some(ident.1),
|
||||||
};
|
};
|
||||||
@ -1101,26 +943,8 @@ where
|
|||||||
|
|
||||||
function.span = span!(self, span.lo);
|
function.span = span!(self, span.lo);
|
||||||
|
|
||||||
// Grammar parsing
|
// Canonicalization against a grammar
|
||||||
match self.ctx.block_contents_grammar {
|
function = self.canonicalize_function_value(function)?;
|
||||||
BlockContentsGrammar::DeclarationList => {}
|
|
||||||
_ => {
|
|
||||||
let locv = self.create_locv(function.value);
|
|
||||||
|
|
||||||
function.value = match self.parse_according_to_grammar(&locv, |parser| {
|
|
||||||
parser.parse_function_values(function_name)
|
|
||||||
}) {
|
|
||||||
Ok(values) => values,
|
|
||||||
Err(err) => {
|
|
||||||
if *err.kind() != ErrorKind::Ignore {
|
|
||||||
self.errors.push(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
locv.children
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(function);
|
return Ok(function);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
|
use swc_atoms::js_word;
|
||||||
use swc_common::{Span, Spanned, SyntaxContext, DUMMY_SP};
|
use swc_common::{Span, Spanned, SyntaxContext, DUMMY_SP};
|
||||||
use swc_css_ast::*;
|
use swc_css_ast::*;
|
||||||
|
|
||||||
@ -7,7 +8,7 @@ use super::{
|
|||||||
input::{Input, InputType, ParserInput},
|
input::{Input, InputType, ParserInput},
|
||||||
Ctx, Error, PResult, Parse, Parser,
|
Ctx, Error, PResult, Parse, Parser,
|
||||||
};
|
};
|
||||||
use crate::parser::BlockContentsGrammar;
|
use crate::{error::ErrorKind, parser::BlockContentsGrammar};
|
||||||
|
|
||||||
impl<I> Parser<I>
|
impl<I> Parser<I>
|
||||||
where
|
where
|
||||||
@ -74,6 +75,255 @@ where
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn canonicalize_at_rule_prelude(&mut self, mut at_rule: AtRule) -> PResult<AtRule> {
|
||||||
|
let normalized_at_rule_name = match &at_rule.name {
|
||||||
|
AtRuleName::Ident(Ident { value, .. }) => value.to_ascii_lowercase(),
|
||||||
|
AtRuleName::DashedIdent(_) => return Ok(at_rule),
|
||||||
|
};
|
||||||
|
|
||||||
|
let list_of_component_values = match at_rule.prelude {
|
||||||
|
Some(at_rule_prelude) => match *at_rule_prelude {
|
||||||
|
AtRulePrelude::ListOfComponentValues(list_of_component_values) => {
|
||||||
|
list_of_component_values
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
at_rule.prelude = match self
|
||||||
|
.parse_according_to_grammar(&list_of_component_values, |parser| {
|
||||||
|
parser.parse_at_rule_prelude(&normalized_at_rule_name)
|
||||||
|
}) {
|
||||||
|
Ok(at_rule_prelude) => match at_rule_prelude {
|
||||||
|
Some(AtRulePrelude::LayerPrelude(LayerPrelude::NameList(name_list)))
|
||||||
|
if name_list.name_list.len() > 1 && at_rule.block.is_some() =>
|
||||||
|
{
|
||||||
|
self.errors.push(Error::new(
|
||||||
|
name_list.span,
|
||||||
|
ErrorKind::Expected("only one name"),
|
||||||
|
));
|
||||||
|
|
||||||
|
Some(Box::new(AtRulePrelude::ListOfComponentValues(
|
||||||
|
list_of_component_values,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
None if *normalized_at_rule_name == js_word!("layer")
|
||||||
|
&& at_rule.block.is_none() =>
|
||||||
|
{
|
||||||
|
self.errors.push(Error::new(
|
||||||
|
at_rule.span,
|
||||||
|
ErrorKind::Expected("at least one name"),
|
||||||
|
));
|
||||||
|
|
||||||
|
Some(Box::new(AtRulePrelude::ListOfComponentValues(
|
||||||
|
list_of_component_values,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
_ => at_rule_prelude.map(Box::new),
|
||||||
|
},
|
||||||
|
Err(err) => {
|
||||||
|
if *err.kind() != ErrorKind::Ignore {
|
||||||
|
self.errors.push(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !list_of_component_values.children.is_empty() {
|
||||||
|
Some(Box::new(AtRulePrelude::ListOfComponentValues(
|
||||||
|
list_of_component_values,
|
||||||
|
)))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(at_rule)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn canonicalize_at_rule_block(&mut self, mut at_rule: AtRule) -> PResult<AtRule> {
|
||||||
|
let normalized_at_rule_name = match &at_rule.name {
|
||||||
|
AtRuleName::Ident(Ident { value, .. }) => value.to_ascii_lowercase(),
|
||||||
|
AtRuleName::DashedIdent(_) => return Ok(at_rule),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut block = match at_rule.block {
|
||||||
|
Some(simple_block) => simple_block,
|
||||||
|
_ => {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let list_of_component_values = self.create_locv(block.value);
|
||||||
|
|
||||||
|
block.value = match self.parse_according_to_grammar(&list_of_component_values, |parser| {
|
||||||
|
parser.parse_at_rule_block(&normalized_at_rule_name)
|
||||||
|
}) {
|
||||||
|
Ok(block_contents) => block_contents,
|
||||||
|
Err(err) => {
|
||||||
|
if *err.kind() != ErrorKind::Ignore {
|
||||||
|
self.errors.push(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
list_of_component_values.children
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
at_rule.block = Some(block);
|
||||||
|
|
||||||
|
Ok(at_rule)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn canonicalize_qualified_rule_prelude(
|
||||||
|
&mut self,
|
||||||
|
mut qualified_rule: QualifiedRule,
|
||||||
|
) -> PResult<QualifiedRule> {
|
||||||
|
let list_of_component_values = match qualified_rule.prelude {
|
||||||
|
QualifiedRulePrelude::ListOfComponentValues(list_of_component_values) => {
|
||||||
|
list_of_component_values
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
qualified_rule.prelude = if self.ctx.in_keyframes_at_rule {
|
||||||
|
QualifiedRulePrelude::ListOfComponentValues(list_of_component_values)
|
||||||
|
} else if self.ctx.mixed_with_declarations {
|
||||||
|
match self.parse_according_to_grammar::<RelativeSelectorList>(
|
||||||
|
&list_of_component_values,
|
||||||
|
|parser| parser.parse(),
|
||||||
|
) {
|
||||||
|
Ok(relative_selector_list) => {
|
||||||
|
QualifiedRulePrelude::RelativeSelectorList(relative_selector_list)
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
self.errors.push(err);
|
||||||
|
|
||||||
|
QualifiedRulePrelude::ListOfComponentValues(list_of_component_values)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match self
|
||||||
|
.parse_according_to_grammar::<SelectorList>(&list_of_component_values, |parser| {
|
||||||
|
parser.parse()
|
||||||
|
}) {
|
||||||
|
Ok(selector_list) => QualifiedRulePrelude::SelectorList(selector_list),
|
||||||
|
Err(err) => {
|
||||||
|
self.errors.push(err);
|
||||||
|
|
||||||
|
QualifiedRulePrelude::ListOfComponentValues(list_of_component_values)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(qualified_rule)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn canonicalize_qualified_rule_block(
|
||||||
|
&mut self,
|
||||||
|
mut qualified_rule: QualifiedRule,
|
||||||
|
) -> PResult<QualifiedRule> {
|
||||||
|
qualified_rule.block.value = match self.ctx.block_contents_grammar {
|
||||||
|
BlockContentsGrammar::RuleList if self.ctx.in_keyframes_at_rule => self
|
||||||
|
.parse_according_to_grammar(
|
||||||
|
&self.create_locv(qualified_rule.block.value),
|
||||||
|
|parser| {
|
||||||
|
parser
|
||||||
|
.with_ctx(Ctx {
|
||||||
|
block_contents_grammar: BlockContentsGrammar::DeclarationList,
|
||||||
|
..parser.ctx
|
||||||
|
})
|
||||||
|
.parse_as::<Vec<DeclarationOrAtRule>>()
|
||||||
|
},
|
||||||
|
)?
|
||||||
|
.into_iter()
|
||||||
|
.map(ComponentValue::DeclarationOrAtRule)
|
||||||
|
.collect(),
|
||||||
|
_ => self
|
||||||
|
.parse_according_to_grammar(
|
||||||
|
&self.create_locv(qualified_rule.block.value),
|
||||||
|
|parser| {
|
||||||
|
parser
|
||||||
|
.with_ctx(Ctx {
|
||||||
|
block_contents_grammar: BlockContentsGrammar::StyleBlock,
|
||||||
|
..parser.ctx
|
||||||
|
})
|
||||||
|
.parse_as::<Vec<StyleBlock>>()
|
||||||
|
},
|
||||||
|
)?
|
||||||
|
.into_iter()
|
||||||
|
.map(ComponentValue::StyleBlock)
|
||||||
|
.collect(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(qualified_rule)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn canonicalize_function_value(
|
||||||
|
&mut self,
|
||||||
|
mut function: Function,
|
||||||
|
) -> PResult<Function> {
|
||||||
|
match self.ctx.block_contents_grammar {
|
||||||
|
BlockContentsGrammar::DeclarationList => {}
|
||||||
|
_ => {
|
||||||
|
let function_name = function.name.value.to_ascii_lowercase();
|
||||||
|
|
||||||
|
let locv = self.create_locv(function.value);
|
||||||
|
|
||||||
|
function.value = match self.parse_according_to_grammar(&locv, |parser| {
|
||||||
|
parser.parse_function_values(&function_name)
|
||||||
|
}) {
|
||||||
|
Ok(values) => values,
|
||||||
|
Err(err) => {
|
||||||
|
if *err.kind() != ErrorKind::Ignore {
|
||||||
|
self.errors.push(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
locv.children
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(function)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn canonicalize_declaration_value(
|
||||||
|
&mut self,
|
||||||
|
mut declaration: Declaration,
|
||||||
|
) -> PResult<Declaration> {
|
||||||
|
let locv = self.create_locv(declaration.value);
|
||||||
|
|
||||||
|
declaration.value = match self.parse_according_to_grammar(&locv, |parser| {
|
||||||
|
let mut values = vec![];
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if is!(parser, EOF) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
values.push(parser.parse_generic_value()?);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(values)
|
||||||
|
}) {
|
||||||
|
Ok(values) => values,
|
||||||
|
Err(err) => {
|
||||||
|
if *err.kind() != ErrorKind::Ignore {
|
||||||
|
self.errors.push(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
locv.children
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(declaration)
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn try_to_parse_legacy_nesting(&mut self) -> Option<QualifiedRule> {
|
pub(super) fn try_to_parse_legacy_nesting(&mut self) -> Option<QualifiedRule> {
|
||||||
let state = self.input.state();
|
let state = self.input.state();
|
||||||
let qualified_rule = self
|
let qualified_rule = self
|
||||||
|
@ -266,6 +266,7 @@ where
|
|||||||
Ok(tokens)
|
Ok(tokens)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO use `JsWord`
|
||||||
pub fn parse_function_values(&mut self, function_name: &str) -> PResult<Vec<ComponentValue>> {
|
pub fn parse_function_values(&mut self, function_name: &str) -> PResult<Vec<ComponentValue>> {
|
||||||
let mut values = vec![];
|
let mut values = vec![];
|
||||||
|
|
||||||
|
@ -2,5 +2,5 @@
|
|||||||
x Expected at least one name
|
x Expected at least one name
|
||||||
,-[$DIR/tests/recovery/at-rule/layer/empty/input.css:1:1]
|
,-[$DIR/tests/recovery/at-rule/layer/empty/input.css:1:1]
|
||||||
1 | @layer ;
|
1 | @layer ;
|
||||||
: ^^^^^^
|
: ^^^^^^^^
|
||||||
`----
|
`----
|
||||||
|
Loading…
Reference in New Issue
Block a user