1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use super::Parser;
use crate::{
    ast::*,
    bump,
    error::{Error, ErrorKind, PResult},
    expect, expect_without_ws_or_comments, peek,
    pos::{Span, Spanned},
    tokenizer::{Token, TokenWithSpan},
    Parse,
};

// https://www.w3.org/TR/css-cascade-5/#at-import
impl<'cmt, 's: 'cmt> Parse<'cmt, 's> for ImportPrelude<'s> {
    fn parse(input: &mut Parser<'cmt, 's>) -> PResult<Self> {
        let href = match &peek!(input).token {
            Token::Str(..) | Token::StrTemplate(..) => input.parse().map(ImportPreludeHref::Str)?,
            _ => input.parse().map(ImportPreludeHref::Url)?,
        };
        let mut span = href.span().clone();

        let layer = match &peek!(input).token {
            Token::Ident(ident) if ident.name().eq_ignore_ascii_case("layer") => {
                let ident = input.parse::<Ident>()?;
                let layer = match peek!(input) {
                    TokenWithSpan {
                        token: Token::LParen(..),
                        span,
                    } if span.start == ident.span.end => {
                        bump!(input);
                        let args = vec![input.parse().map(ComponentValue::LayerName)?];
                        let end = expect!(input, RParen).1.end;
                        let span = Span {
                            start: ident.span.start,
                            end,
                        };
                        ImportPreludeLayer::WithName(Function {
                            name: FunctionName::Ident(InterpolableIdent::Literal(ident)),
                            args,
                            span,
                        })
                    }
                    _ => ImportPreludeLayer::Empty(ident),
                };
                span.end = layer.span().end;
                Some(layer)
            }
            _ => None,
        };

        let supports = input.try_parse(|parser| {
            let (ident, span) = expect!(parser, Ident);
            if !ident.name().eq_ignore_ascii_case("supports") {
                return Err(Error {
                    kind: ErrorKind::TryParseError,
                    span,
                });
            }

            expect_without_ws_or_comments!(parser, LParen);

            let kind = if let Ok(supports_condition) = parser.try_parse(SupportsCondition::parse) {
                ImportPreludeSupportsKind::SupportsCondition(supports_condition)
            } else {
                parser.parse().map(ImportPreludeSupportsKind::Declaration)?
            };
            let (_, Span { end, .. }) = expect!(parser, RParen);
            Ok(ImportPreludeSupports {
                kind,
                span: Span {
                    start: span.start,
                    end,
                },
            })
        });
        if let Ok(supports) = &supports {
            span.end = supports.span().end;
        }

        let media = if matches!(peek!(input).token, Token::Semicolon(..)) {
            None
        } else {
            let media = input.parse::<MediaQueryList>()?;
            span.end = media.span.end;
            Some(media)
        };

        Ok(ImportPrelude {
            href,
            layer,
            supports: supports.ok(),
            media,
            span,
        })
    }
}