oxc_css_parser/parser/at_rule/
import.rs1use super::Parser;
2use crate::{
3 Parse, Syntax,
4 ast::*,
5 bump,
6 error::{Error, ErrorKind, PResult},
7 expect, expect_without_ws_or_comments, peek,
8 pos::{Span, Spanned},
9 tokenizer::{Token, TokenWithSpan},
10};
11
12impl<'cmt, 's: 'cmt> Parse<'cmt, 's> for ImportPrelude<'s> {
14 fn parse(input: &mut Parser<'cmt, 's>) -> PResult<Self> {
15 let href = match &peek!(input).token {
16 Token::Str(..) | Token::StrTemplate(..) => input.parse().map(ImportPreludeHref::Str)?,
17 _ => match input.try_parse(Url::parse) {
18 Ok(url) => ImportPreludeHref::Url(url),
19 Err(error) if matches!(input.syntax, Syntax::Scss | Syntax::Sass) => {
23 let function_name: Ident = expect!(input, Ident).into();
24 if !function_name.name.eq_ignore_ascii_case("url") {
25 return Err(error);
26 }
27 input
28 .parse_function(InterpolableIdent::Literal(function_name))
29 .map(ImportPreludeHref::Function)
30 .map_err(|_| error)?
31 }
32 Err(error) => return Err(error),
33 },
34 };
35 let mut span = href.span().clone();
36
37 let layer = match &peek!(input).token {
38 Token::Ident(ident) if ident.name().eq_ignore_ascii_case("layer") => {
39 let ident = input.parse::<Ident>()?;
40 let layer = match peek!(input) {
41 TokenWithSpan {
42 token: Token::LParen(..),
43 span,
44 } if span.start == ident.span.end => {
45 bump!(input);
46 let args = vec![input.parse().map(ComponentValue::LayerName)?];
47 let end = expect!(input, RParen).1.end;
48 let span = Span {
49 start: ident.span.start,
50 end,
51 };
52 ImportPreludeLayer::WithName(Function {
53 name: FunctionName::Ident(InterpolableIdent::Literal(ident)),
54 args,
55 span,
56 })
57 }
58 _ => ImportPreludeLayer::Empty(ident),
59 };
60 span.end = layer.span().end;
61 Some(layer)
62 }
63 _ => None,
64 };
65
66 let supports = input.try_parse(|parser| {
67 let (ident, span) = expect!(parser, Ident);
68 if !ident.name().eq_ignore_ascii_case("supports") {
69 return Err(Error {
70 kind: ErrorKind::TryParseError,
71 span,
72 });
73 }
74
75 expect_without_ws_or_comments!(parser, LParen);
76
77 let kind = if let Ok(supports_condition) = parser.try_parse(SupportsCondition::parse) {
78 ImportPreludeSupportsKind::SupportsCondition(supports_condition)
79 } else {
80 parser.parse().map(ImportPreludeSupportsKind::Declaration)?
81 };
82 let (_, Span { end, .. }) = expect!(parser, RParen);
83 Ok(ImportPreludeSupports {
84 kind,
85 span: Span {
86 start: span.start,
87 end,
88 },
89 })
90 });
91 if let Ok(supports) = &supports {
92 span.end = supports.span().end;
93 }
94
95 let media = if matches!(peek!(input).token, Token::Semicolon(..)) {
96 None
97 } else {
98 let media = input.parse::<MediaQueryList>()?;
99 span.end = media.span.end;
100 Some(media)
101 };
102
103 Ok(ImportPrelude {
104 href,
105 layer,
106 supports: supports.ok(),
107 media,
108 span,
109 })
110 }
111}