Skip to main content

oxc_css_parser/parser/at_rule/
page.rs

1use super::Parser;
2use crate::{
3    Parse, arena_vec,
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<'a> Parse<'a> for PageSelector<'a> {
15    fn parse(input: &mut Parser<'a>) -> PResult<Self> {
16        let mut name = None;
17        let mut pseudo = arena_vec!(input);
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 { token: Token::Colon(..), span } if span.start == end => {
37                    let item = input.parse::<PseudoPage>()?;
38                    end = item.span.end;
39                    pseudo.push(item);
40                }
41                _ => break,
42            }
43        }
44
45        Ok(PageSelector { name, pseudo, span: Span { start, end } })
46    }
47}
48
49impl<'a> Parse<'a> for PageSelectorList<'a> {
50    fn parse(input: &mut Parser<'a>) -> PResult<Self> {
51        let first = input.parse::<PageSelector>()?;
52        let mut span = first.span.clone();
53
54        let mut selectors = arena_vec!(input; first);
55        let mut comma_spans = arena_vec!(input);
56        while let Some((_, comma_span)) = eat!(input, Comma) {
57            comma_spans.push(comma_span);
58            selectors.push(input.parse()?);
59        }
60
61        if let Some(last) = selectors.last() {
62            span.end = last.span.end;
63        }
64        Ok(PageSelectorList { selectors, comma_spans, span })
65    }
66}
67
68impl<'a> Parse<'a> for PseudoPage<'a> {
69    fn parse(input: &mut Parser<'a>) -> PResult<Self> {
70        let (_, colon_span) = expect!(input, Colon);
71        let name = input.parse::<InterpolableIdent>()?;
72
73        let name_span = name.span();
74        util::assert_no_ws_or_comment(&colon_span, name_span)?;
75
76        let span = Span { start: colon_span.start, end: name_span.end };
77        Ok(PseudoPage { name, span })
78    }
79}