css_ast/rules/
layer.rs

1use bumpalo::collections::Vec;
2use css_parse::{AtRule, Parse, Parser, Result as ParserResult, RuleList, T, atkeyword_set, syntax::CommaSeparated};
3use csskit_derives::{Parse, Peek, ToCursors, ToSpan, Visitable};
4
5use crate::stylesheet::Rule;
6
7atkeyword_set!(pub struct AtLayerKeyword "layer");
8
9// https://drafts.csswg.org/css-cascade-5/#layering
10#[derive(Parse, Peek, ToCursors, ToSpan, Visitable, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
11#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
12#[cfg_attr(feature = "css_feature_data", derive(::csskit_derives::ToCSSFeature), css_feature("css.at-rules.layer"))]
13#[visit]
14pub struct LayerRule<'a>(pub AtRule<AtLayerKeyword, LayerNameList<'a>, Option<LayerRuleBlock<'a>>>);
15
16#[derive(Parse, Peek, ToCursors, ToSpan, Visitable, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
17#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
18pub struct LayerNameList<'a>(pub CommaSeparated<'a, LayerName<'a>>);
19
20#[derive(Peek, ToCursors, ToSpan, Visitable, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
21#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
22#[visit(self)]
23pub struct LayerName<'a>(T![Ident], Vec<'a, (T![.], T![Ident])>);
24
25impl<'a> Parse<'a> for LayerName<'a> {
26	fn parse(p: &mut Parser<'a>) -> ParserResult<Self> {
27		let mut parts = Vec::new_in(p.bump());
28		let first = p.parse::<T![Ident]>()?;
29		loop {
30			if p.peek::<T![.]>() {
31				let dot = p.parse::<T![.]>()?;
32				let ident = p.parse::<T![Ident]>()?;
33				parts.push((dot, ident));
34			} else {
35				return Ok(Self(first, parts));
36			}
37		}
38	}
39}
40
41#[derive(Parse, Peek, ToCursors, ToSpan, Visitable, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
42#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
43pub struct LayerRuleBlock<'a>(RuleList<'a, Rule<'a>>);
44
45#[cfg(test)]
46mod tests {
47	use super::*;
48	use css_parse::assert_parse;
49
50	#[test]
51	fn size_test() {
52		assert_eq!(std::mem::size_of::<LayerRule>(), 128);
53		assert_eq!(std::mem::size_of::<LayerNameList>(), 32);
54		assert_eq!(std::mem::size_of::<LayerName>(), 48);
55		assert_eq!(std::mem::size_of::<LayerRuleBlock>(), 64);
56	}
57
58	#[test]
59	fn test_writes() {
60		assert_parse!(LayerRule, "@layer foo{}");
61		assert_parse!(LayerRule, "@layer foo;");
62		assert_parse!(LayerRule, "@layer foo,bar;");
63		assert_parse!(LayerRule, "@layer foo.bar,baz.bing.baz;");
64		assert_parse!(LayerRule, "@layer foo.bar{body{color:black}}");
65	}
66}