1use css_parse::{
2 AtRule, Build, Cursor, DeclarationList, DeclarationValue, Parser, Peek, Result as ParserResult, T, atkeyword_set,
3 keyword_set, syntax::ComponentValues,
4};
5use csskit_derives::{IntoCursor, Parse, Peek, ToCursors, ToSpan, Visitable};
6
7use crate::Computed;
8
9atkeyword_set!(pub struct AtPropertyKeyword "property");
10
11#[derive(Parse, Peek, ToSpan, ToCursors, Visitable, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
14#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
15#[cfg_attr(feature = "css_feature_data", derive(::csskit_derives::ToCSSFeature), css_feature("css.at-rules.property"))]
16#[visit]
17pub struct PropertyRule<'a>(pub AtRule<AtPropertyKeyword, PropertyPrelude, PropertyRuleBlock<'a>>);
18
19#[derive(Parse, Peek, ToSpan, ToCursors, Visitable, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
20#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
21#[visit(self)]
22pub struct PropertyPrelude(T![DashedIdent]);
23
24#[derive(Parse, Peek, ToSpan, ToCursors, Visitable, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
25#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
26pub struct PropertyRuleBlock<'a>(DeclarationList<'a, PropertyRuleValue<'a>>);
27
28keyword_set!(pub enum PropertyRulePropertyId { InitialValue: "initial-value", Inherits: "inherits", Syntax: "syntax" });
29
30#[derive(ToSpan, ToCursors, Visitable, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
31#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
32#[visit(children)]
33pub enum PropertyRuleValue<'a> {
34 InitialValue(ComponentValues<'a>),
35 Syntax(SyntaxValue),
36 Inherits(InheritsValue),
37 Unknown(ComponentValues<'a>),
38}
39
40keyword_set!(
41 #[derive(Visitable)]
42 #[visit(self)]
43 pub enum InheritsValue {
44 True: "true",
45 False: "false"
46 }
47);
48
49#[derive(Parse, Peek, ToCursors, IntoCursor, Visitable, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
50#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
51#[visit(self)]
52pub struct SyntaxValue(T![String]);
53
54impl<'a> DeclarationValue<'a> for PropertyRuleValue<'a> {
55 type ComputedValue = Computed<'a>;
56
57 fn valid_declaration_name(p: &Parser<'a>, c: Cursor) -> bool {
58 PropertyRulePropertyId::peek(p, c)
59 }
60
61 fn is_unknown(&self) -> bool {
62 matches!(self, Self::Unknown(_))
63 }
64
65 fn is_initial(&self) -> bool {
66 false
67 }
68
69 fn is_inherit(&self) -> bool {
70 false
71 }
72
73 fn is_unset(&self) -> bool {
74 false
75 }
76
77 fn is_revert(&self) -> bool {
78 false
79 }
80
81 fn is_revert_layer(&self) -> bool {
82 false
83 }
84
85 fn needs_computing(&self) -> bool {
86 matches!(self, Self::Unknown(_))
87 }
88
89 fn parse_declaration_value(p: &mut Parser<'a>, c: Cursor) -> ParserResult<Self> {
90 if !PropertyRulePropertyId::peek(p, c) {
91 Ok(Self::Unknown(p.parse::<ComponentValues<'a>>()?))
92 } else {
93 Ok(match PropertyRulePropertyId::build(p, c) {
94 PropertyRulePropertyId::InitialValue(_) => Self::InitialValue(p.parse::<ComponentValues<'a>>()?),
95 PropertyRulePropertyId::Inherits(_) => Self::Inherits(p.parse::<InheritsValue>()?),
96 PropertyRulePropertyId::Syntax(_) => Self::Syntax(p.parse::<SyntaxValue>()?),
97 })
98 }
99 }
100}
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105 use css_parse::assert_parse;
106
107 #[test]
108 fn size_test() {
109 assert_eq!(std::mem::size_of::<PropertyRule>(), 104);
110 }
111
112 #[test]
113 fn test_writes() {
114 assert_parse!(PropertyRule, r#"@property --foo{initial-value:0;inherits:false;syntax:"<length>"}"#);
115 }
116}