Skip to main content

oxc_css_parser/parser/at_rule/
layer.rs

1use super::Parser;
2use crate::{
3    Parse,
4    ast::*,
5    bump, eat,
6    error::{Error, PResult},
7    peek,
8    pos::{Span, Spanned},
9    tokenizer::{Token, TokenWithSpan},
10    util,
11};
12
13// https://drafts.csswg.org/css-cascade-5/#layering
14impl<'cmt, 's: 'cmt> Parse<'cmt, 's> for LayerNames<'s> {
15    fn parse(input: &mut Parser<'cmt, 's>) -> PResult<Self> {
16        let first = input.parse::<LayerName>()?;
17        let mut span = first.span.clone();
18
19        let mut names = vec![first];
20        let mut comma_spans = vec![];
21        while let Some((_, comma_span)) = eat!(input, Comma) {
22            comma_spans.push(comma_span);
23            names.push(input.parse()?);
24        }
25
26        if let Some(last) = names.last() {
27            span.end = last.span.end;
28        }
29        Ok(LayerNames {
30            names,
31            comma_spans,
32            span,
33        })
34    }
35}
36
37// https://drafts.csswg.org/css-cascade-5/#layer-names
38impl<'cmt, 's: 'cmt> Parse<'cmt, 's> for LayerName<'s> {
39    fn parse(input: &mut Parser<'cmt, 's>) -> PResult<Self> {
40        let first = input.parse::<InterpolableIdent>()?;
41        let start = first.span().start;
42        let mut end = first.span().end;
43
44        let mut idents = vec![first];
45        while let TokenWithSpan {
46            token: Token::Dot(..),
47            span,
48        } = peek!(input)
49        {
50            if span.start == end {
51                let span = bump!(input).span;
52                let ident = input.parse::<InterpolableIdent>()?;
53                util::assert_no_ws_or_comment(&span, ident.span())?;
54                end = ident.span().end;
55                idents.push(ident);
56            } else {
57                break;
58            }
59        }
60
61        let invalid_ident = idents.iter().find(|ident| match &ident {
62            InterpolableIdent::Literal(ident) => util::is_css_wide_keyword(&ident.name),
63            _ => false,
64        });
65        if let Some(invalid_ident) = invalid_ident {
66            input.recoverable_errors.push(Error {
67                kind: crate::error::ErrorKind::CSSWideKeywordDisallowed,
68                span: invalid_ident.span().clone(),
69            });
70        }
71
72        let span = Span { start, end };
73        Ok(LayerName { idents, span })
74    }
75}