Skip to main content

oxc_css_parser/parser/at_rule/
page.rs

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