1use super::prelude::*;
2use crate::Computed;
3
4#[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}