css_ast/rules/
property.rs

1use super::prelude::*;
2use crate::Computed;
3
4// https://drafts.csswg.org/cssom-1/#csspagerule
5// https://drafts.csswg.org/css-page-3/#at-page-rule
6#[derive(Parse, Peek, ToSpan, ToCursors, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
8#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit)]
9#[cfg_attr(feature = "css_feature_data", derive(::csskit_derives::ToCSSFeature), css_feature("css.at-rules.property"))]
10pub struct PropertyRule<'a> {
11	#[cfg_attr(feature = "visitable", visit(skip))]
12	#[atom(CssAtomSet::Property)]
13	pub name: T![AtKeyword],
14	pub prelude: PropertyPrelude,
15	pub block: PropertyRuleBlock<'a>,
16}
17
18impl<'a> NodeWithMetadata<CssMetadata> for PropertyRule<'a> {
19	fn metadata(&self) -> CssMetadata {
20		let mut meta = self.block.0.metadata();
21		meta.used_at_rules |= AtRuleId::Property;
22		meta
23	}
24}
25
26#[derive(Parse, Peek, ToSpan, ToCursors, 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))]
29pub struct PropertyPrelude(T![DashedIdent]);
30
31#[derive(Parse, Peek, ToSpan, ToCursors, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
32#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable))]
33#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
34pub struct PropertyRuleBlock<'a>(DeclarationList<'a, PropertyRuleValue<'a>, CssMetadata>);
35
36#[derive(ToSpan, ToCursors, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
37#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
38#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(children))]
39pub enum PropertyRuleValue<'a> {
40	InitialValue(ComponentValues<'a>),
41	Syntax(SyntaxValue),
42	Inherits(InheritsValue),
43	Unknown(ComponentValues<'a>),
44}
45
46#[derive(Parse, Peek, IntoCursor, ToCursors, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
47#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
48#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
49pub enum InheritsValue {
50	#[atom(CssAtomSet::True)]
51	True(T![Ident]),
52	#[atom(CssAtomSet::False)]
53	False(T![Ident]),
54}
55
56#[derive(Parse, Peek, ToCursors, IntoCursor, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
57#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
58#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
59pub struct SyntaxValue(T![String]);
60
61impl<'a, M: NodeMetadata> DeclarationValue<'a, M> for PropertyRuleValue<'a> {
62	type ComputedValue = Computed<'a>;
63
64	fn valid_declaration_name<I>(p: &Parser<'a, I>, c: Cursor) -> bool
65	where
66		I: Iterator<Item = Cursor> + Clone,
67	{
68		matches!(p.to_atom::<CssAtomSet>(c), CssAtomSet::InitialValue | CssAtomSet::Inherits | CssAtomSet::Syntax)
69	}
70
71	fn is_unknown(&self) -> bool {
72		matches!(self, Self::Unknown(_))
73	}
74
75	fn is_initial(&self) -> bool {
76		false
77	}
78
79	fn is_inherit(&self) -> bool {
80		false
81	}
82
83	fn is_unset(&self) -> bool {
84		false
85	}
86
87	fn is_revert(&self) -> bool {
88		false
89	}
90
91	fn is_revert_layer(&self) -> bool {
92		false
93	}
94
95	fn needs_computing(&self) -> bool {
96		matches!(self, Self::Unknown(_))
97	}
98
99	fn parse_declaration_value<I>(p: &mut Parser<'a, I>, c: Cursor) -> ParserResult<Self>
100	where
101		I: Iterator<Item = Cursor> + Clone,
102	{
103		Ok(match p.to_atom::<CssAtomSet>(c) {
104			CssAtomSet::InitialValue => Self::InitialValue(p.parse::<ComponentValues<'a>>()?),
105			CssAtomSet::Inherits => Self::Inherits(p.parse::<InheritsValue>()?),
106			CssAtomSet::Syntax => Self::Syntax(p.parse::<SyntaxValue>()?),
107			_ => Self::Unknown(p.parse::<ComponentValues<'a>>()?),
108		})
109	}
110}
111
112impl<'a, M: NodeMetadata> NodeWithMetadata<M> for PropertyRuleValue<'a> {
113	fn metadata(&self) -> M {
114		M::default()
115	}
116}
117
118#[cfg(test)]
119mod tests {
120	use super::*;
121	use crate::CssAtomSet;
122	use css_parse::assert_parse;
123
124	#[test]
125	fn size_test() {
126		assert_eq!(std::mem::size_of::<PropertyRule>(), 112);
127	}
128
129	#[test]
130	fn test_writes() {
131		assert_parse!(
132			CssAtomSet::ATOMS,
133			PropertyRule,
134			r#"@property --foo{initial-value:0;inherits:false;syntax:"<length>"}"#
135		);
136	}
137}