css_inline/
parser.rs

1pub(crate) struct CSSRuleListParser<'d, 'i>(&'d mut Vec<Declaration<'i>>);
2
3impl<'d, 'i> CSSRuleListParser<'d, 'i> {
4    #[inline]
5    pub(crate) fn new(declarations: &'d mut Vec<Declaration<'i>>) -> CSSRuleListParser<'d, 'i> {
6        CSSRuleListParser(declarations)
7    }
8}
9
10pub(crate) struct CSSDeclarationListParser;
11
12pub(crate) type Name<'i> = cssparser::CowRcStr<'i>;
13pub(crate) type Declaration<'i> = (Name<'i>, &'i str);
14pub(crate) type QualifiedRule<'i> = (&'i str, (usize, usize));
15
16fn exhaust<'i>(input: &mut cssparser::Parser<'i, '_>) -> &'i str {
17    let start = input.position();
18    while input.next().is_ok() {}
19    input.slice_from(start)
20}
21
22/// Parser for qualified rules - a prelude + a simple {} block.
23///
24/// Usually these rules are a selector + list of declarations: `p { color: blue; font-size: 2px }`
25impl<'i> cssparser::QualifiedRuleParser<'i> for CSSRuleListParser<'_, 'i> {
26    type Prelude = &'i str;
27    type QualifiedRule = QualifiedRule<'i>;
28    type Error = ();
29
30    fn parse_prelude<'t>(
31        &mut self,
32        input: &mut cssparser::Parser<'i, 't>,
33    ) -> Result<Self::Prelude, cssparser::ParseError<'i, Self::Error>> {
34        // Proceed with parsing until the end of the prelude.
35        Ok(exhaust(input))
36    }
37
38    fn parse_block<'t>(
39        &mut self,
40        prelude: Self::Prelude,
41        _: &cssparser::ParserState,
42        input: &mut cssparser::Parser<'i, 't>,
43    ) -> Result<Self::QualifiedRule, cssparser::ParseError<'i, Self::Error>> {
44        // Parse list of declarations
45        let mut parser = CSSDeclarationListParser;
46        let parser = cssparser::RuleBodyParser::new(input, &mut parser);
47        let start = self.0.len();
48        for item in parser.flatten() {
49            self.0.push(item);
50        }
51        Ok((prelude, (start, self.0.len())))
52    }
53}
54
55/// Parse a declaration within {} block: `color: blue`
56impl<'i> cssparser::DeclarationParser<'i> for CSSDeclarationListParser {
57    type Declaration = Declaration<'i>;
58    type Error = ();
59
60    fn parse_value<'t>(
61        &mut self,
62        name: Name<'i>,
63        input: &mut cssparser::Parser<'i, 't>,
64    ) -> Result<Self::Declaration, cssparser::ParseError<'i, Self::Error>> {
65        Ok((name, exhaust(input)))
66    }
67}
68
69impl<'i> cssparser::AtRuleParser<'i> for CSSRuleListParser<'_, 'i> {
70    type Prelude = &'i str;
71    type AtRule = QualifiedRule<'i>;
72    type Error = ();
73}
74
75/// Parsing for at-rules, e.g: `@charset "utf-8";`
76/// Since they are can not be inlined we use the default implementation, that rejects all at-rules.
77impl<'i> cssparser::AtRuleParser<'i> for CSSDeclarationListParser {
78    type Prelude = String;
79    type AtRule = Declaration<'i>;
80    type Error = ();
81}
82
83impl<'i> cssparser::RuleBodyItemParser<'i, Declaration<'i>, ()> for CSSDeclarationListParser {
84    fn parse_declarations(&self) -> bool {
85        true
86    }
87
88    fn parse_qualified(&self) -> bool {
89        true
90    }
91}
92
93impl<'i> cssparser::QualifiedRuleParser<'i> for CSSDeclarationListParser {
94    type Prelude = String;
95    type QualifiedRule = Declaration<'i>;
96    type Error = ();
97}