Skip to main content

oxc_css_parser/parser/at_rule/
page.rs

1use super::Parser;
2use crate::{
3    Parse,
4    ast::*,
5    eat,
6    error::PResult,
7    expect, peek,
8    pos::{Span, Spanned},
9    tokenizer::{Token, TokenWithSpan},
10    util,
11};
12
13// https://www.w3.org/TR/css-page-3/#syntax-page-selector
14impl<'cmt, 's: 'cmt> Parse<'cmt, 's> for PageSelector<'s> {
15    fn parse(input: &mut Parser<'cmt, 's>) -> PResult<Self> {
16        let mut name = None;
17        let mut pseudo = vec![];
18        let start;
19        let mut end;
20
21        if let Token::Colon(..) = &peek!(input).token {
22            let first = input.parse::<PseudoPage>()?;
23            start = first.span.start;
24            end = first.span.end;
25            pseudo.push(first);
26        } else {
27            let ident = input.parse::<InterpolableIdent>()?;
28            let ident_span = ident.span();
29            start = ident_span.start;
30            end = ident_span.end;
31            name = Some(ident)
32        }
33
34        loop {
35            match peek!(input) {
36                TokenWithSpan {
37                    token: Token::Colon(..),
38                    span,
39                } if span.start == end => {
40                    let item = input.parse::<PseudoPage>()?;
41                    end = item.span.end;
42                    pseudo.push(item);
43                }
44                _ => break,
45            }
46        }
47
48        Ok(PageSelector {
49            name,
50            pseudo,
51            span: Span { start, end },
52        })
53    }
54}
55
56impl<'cmt, 's: 'cmt> Parse<'cmt, 's> for PageSelectorList<'s> {
57    fn parse(input: &mut Parser<'cmt, 's>) -> PResult<Self> {
58        let first = input.parse::<PageSelector>()?;
59        let mut span = first.span.clone();
60
61        let mut selectors = vec![first];
62        let mut comma_spans = vec![];
63        while let Some((_, comma_span)) = eat!(input, Comma) {
64            comma_spans.push(comma_span);
65            selectors.push(input.parse()?);
66        }
67
68        if let Some(last) = selectors.last() {
69            span.end = last.span.end;
70        }
71        Ok(PageSelectorList {
72            selectors,
73            comma_spans,
74            span,
75        })
76    }
77}
78
79impl<'cmt, 's: 'cmt> Parse<'cmt, 's> for PseudoPage<'s> {
80    fn parse(input: &mut Parser<'cmt, 's>) -> PResult<Self> {
81        let (_, colon_span) = expect!(input, Colon);
82        let name = input.parse::<InterpolableIdent>()?;
83
84        let name_span = name.span();
85        util::assert_no_ws_or_comment(&colon_span, name_span)?;
86
87        let span = Span {
88            start: colon_span.start,
89            end: name_span.end,
90        };
91        Ok(PseudoPage { name, span })
92    }
93}