oxc_css_parser/parser/at_rule/
keyframes.rs1use super::Parser;
2use crate::{
3 Parse,
4 ast::*,
5 error::{Error, ErrorKind, PResult},
6 parser::state::ParserState,
7 pos::Span,
8 tokenizer::Token,
9 util,
10};
11
12impl<'a> Parse<'a> for KeyframeBlock<'a> {
14 fn parse(input: &mut Parser<'a>) -> PResult<Self> {
15 let first_selector = input.parse::<KeyframeSelector>()?;
16 let start = first_selector.span().start;
17
18 let mut selectors = input.vec_with_capacity(2);
19 selectors.push(first_selector);
20 let mut comma_spans = input.vec();
21 while let Some((_, comma_span)) = input.cursor.eat_comma()? {
22 comma_spans.push(comma_span);
23 selectors.push(input.parse()?);
24 }
25 debug_assert_eq!(comma_spans.len() + 1, selectors.len());
26
27 let block = input
28 .with_state(ParserState { in_keyframes_at_rule: false, ..input.state.clone() })
29 .parse::<SimpleBlock>()?;
30
31 let span = Span { start, end: block.span.end };
32 Ok(KeyframeBlock { selectors, comma_spans, block, span })
33 }
34}
35
36impl<'a> Parse<'a> for KeyframeSelector<'a> {
37 fn parse(input: &mut Parser<'a>) -> PResult<Self> {
38 match &input.cursor.peek()?.token {
39 Token::Percentage(..) => Ok(KeyframeSelector::Percentage(input.parse()?)),
40 _ => {
41 let ident = input.parse()?;
42 match &ident {
43 InterpolableIdent::Literal(ident)
44 if !ident.name.eq_ignore_ascii_case("from")
45 && !ident.name.eq_ignore_ascii_case("to") =>
46 {
47 input.recoverable_errors.push(Error {
48 kind: ErrorKind::UnknownKeyframeSelectorIdent,
49 span: ident.span.clone(),
50 });
51 }
52 _ => {}
53 }
54 Ok(KeyframeSelector::Ident(ident))
55 }
56 }
57 }
58}
59
60impl<'a> Parse<'a> for KeyframesName<'a> {
62 fn parse(input: &mut Parser<'a>) -> PResult<Self> {
63 match &input.cursor.peek()?.token {
64 Token::Ident(..) | Token::HashLBrace(..) | Token::AtLBraceVar(..) => {
65 let ident = input.parse()?;
66 match &ident {
67 InterpolableIdent::Literal(ident)
68 if util::is_css_wide_keyword(ident.name)
69 || ident.name.eq_ignore_ascii_case("default") =>
70 {
71 input.recoverable_errors.push(Error {
72 kind: ErrorKind::CSSWideKeywordDisallowed,
73 span: ident.span.clone(),
74 });
75 }
76 _ => {}
77 }
78 Ok(KeyframesName::Ident(ident))
79 }
80 Token::AtKeyword(..) => input.parse().map(KeyframesName::LessVariable),
81 Token::Tilde(..) => input.parse().map(KeyframesName::LessEscapedStr),
82 _ => input.parse().map(KeyframesName::Str),
83 }
84 }
85}