css_ast/types/
repeat_style.rs1use crate::diagnostics;
2use css_parse::{Build, Cursor, Parse, Parser, Peek, Result as ParserResult, T, keyword_set};
3use csskit_derives::{ToCursors, ToSpan, Visitable};
4
5#[derive(ToCursors, ToSpan, Visitable, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
11#[cfg_attr(feature = "serde", derive(serde::Serialize), serde(rename_all = "kebab-case"))]
12#[visit(self)]
13pub enum RepeatStyle {
14 RepeatX(T![Ident]),
15 RepeatY(T![Ident]),
16 Repetition(Repetition, Option<Repetition>),
17}
18
19impl<'a> Peek<'a> for RepeatStyle {
20 fn peek(p: &Parser<'a>, c: Cursor) -> bool {
21 <Repetition>::peek(p, c) || (<T![Ident]>::peek(p, c) && matches!(p.parse_str_lower(c), "repeat-x" | "repeat-y"))
22 }
23}
24
25impl<'a> Parse<'a> for RepeatStyle {
26 fn parse(p: &mut Parser<'a>) -> ParserResult<Self> {
27 let ident = p.parse::<T![Ident]>()?;
28 let c: Cursor = ident.into();
29 match p.parse_str_lower(c) {
30 "repeat-x" => Ok(Self::RepeatX(<T![Ident]>::build(p, c))),
31 "repeat-y" => Ok(Self::RepeatY(<T![Ident]>::build(p, c))),
32 _ if <Repetition>::peek(p, c) => {
33 let first = Repetition::build(p, c);
34 let second = p.parse_if_peek::<Repetition>()?;
35 Ok(Self::Repetition(first, second))
36 }
37 _ => {
38 let source_cursor = p.to_source_cursor(c);
39 Err(diagnostics::UnexpectedIdent(source_cursor.to_string(), c))?
40 }
41 }
42 }
43}
44
45keyword_set!(
46 #[derive(Visitable)]
52 #[visit(skip)]
53 pub enum Repetition {
54 Repeat: "repeat",
55 Space: "space",
56 Round: "round",
57 NoRepeat: "no-repeat"
58 }
59);