css_ast/rules/
layer.rs

1use super::prelude::*;
2
3// https://drafts.csswg.org/css-cascade-5/#layering
4#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
5#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
6#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit)]
7#[cfg_attr(feature = "css_feature_data", derive(::csskit_derives::ToCSSFeature), css_feature("css.at-rules.layer"))]
8#[derive(csskit_derives::NodeWithMetadata)]
9#[metadata(node_kinds = AtRule, used_at_rules = Layer)]
10pub struct LayerRule<'a> {
11	#[cfg_attr(feature = "visitable", visit(skip))]
12	#[atom(CssAtomSet::Layer)]
13	pub name: T![AtKeyword],
14	pub prelude: LayerNameList<'a>,
15	#[metadata(delegate)]
16	pub block: Option<LayerRuleBlock<'a>>,
17	#[cfg_attr(feature = "visitable", visit(skip))]
18	pub semicolon: Option<T![;]>,
19}
20
21#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
22#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable))]
23#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
24pub struct LayerNameList<'a>(pub CommaSeparated<'a, LayerName<'a>>);
25
26#[derive(Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
27#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
28#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
29#[derive(csskit_derives::NodeWithMetadata)]
30pub struct LayerName<'a>(T![Ident], Vec<'a, (T![.], T![Ident])>);
31
32impl<'a> Parse<'a> for LayerName<'a> {
33	fn parse<I>(p: &mut Parser<'a, I>) -> ParserResult<Self>
34	where
35		I: Iterator<Item = Cursor> + Clone,
36	{
37		let mut parts = Vec::new_in(p.bump());
38		let first = p.parse::<T![Ident]>()?;
39		loop {
40			if p.peek::<T![.]>() {
41				let dot = p.parse::<T![.]>()?;
42				let ident = p.parse::<T![Ident]>()?;
43				parts.push((dot, ident));
44			} else {
45				return Ok(Self(first, parts));
46			}
47		}
48	}
49}
50
51#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
52#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable))]
53#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
54#[derive(csskit_derives::NodeWithMetadata)]
55pub struct LayerRuleBlock<'a>(#[metadata(delegate)] pub RuleList<'a, Rule<'a>, CssMetadata>);
56
57#[cfg(test)]
58mod tests {
59	use super::*;
60	use crate::CssAtomSet;
61	use css_parse::assert_parse;
62
63	#[test]
64	fn size_test() {
65		assert_eq!(std::mem::size_of::<LayerRule>(), 160);
66		assert_eq!(std::mem::size_of::<LayerNameList>(), 32);
67		assert_eq!(std::mem::size_of::<LayerName>(), 48);
68		assert_eq!(std::mem::size_of::<LayerRuleBlock>(), 96);
69	}
70
71	#[test]
72	fn test_writes() {
73		assert_parse!(CssAtomSet::ATOMS, LayerRule, "@layer foo{}");
74		assert_parse!(CssAtomSet::ATOMS, LayerRule, "@layer foo;");
75		assert_parse!(CssAtomSet::ATOMS, LayerRule, "@layer foo,bar;");
76		assert_parse!(CssAtomSet::ATOMS, LayerRule, "@layer foo.bar,baz.bing.baz;");
77		assert_parse!(CssAtomSet::ATOMS, LayerRule, "@layer foo.bar{body{color:black}}");
78	}
79}