1use super::prelude::*;
2#[cfg(feature = "visitable")]
3use crate::visit::{NodeId, QueryableNode};
4use crate::{Computed, Inherits, PropertyGroup, Todo};
5use csskit_derives::*;
6use csskit_proc_macro::syntax;
7
8#[derive(Parse, Peek, ToSpan, ToCursors, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
10#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit, queryable(skip))]
11#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
12#[derive(csskit_derives::NodeWithMetadata)]
13#[metadata(node_kinds = AtRule, used_at_rules = CounterStyle, property_kinds = Name)]
14pub struct CounterStyleRule<'a> {
15 #[cfg_attr(feature = "visitable", visit(skip))]
16 #[atom(CssAtomSet::CounterStyle)]
17 pub name: T![AtKeyword],
18 pub prelude: CounterStyleName,
19 #[metadata(delegate)]
20 pub block: CounterStyleRuleBlock<'a>,
21}
22
23#[cfg(feature = "visitable")]
24impl<'a> QueryableNode for CounterStyleRule<'a> {
25 const NODE_ID: NodeId = NodeId::CounterStyleRule;
26
27 fn get_property(&self, kind: PropertyKind) -> Option<Cursor> {
28 match kind {
29 PropertyKind::Name => Some(self.prelude.into()),
30 _ => None,
31 }
32 }
33}
34
35#[derive(
36 Parse, Peek, IntoCursor, ToSpan, SemanticEq, ToCursors, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
37)]
38#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable))]
39#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
40pub struct CounterStyleName(T![Ident]);
41
42#[derive(Parse, Peek, ToSpan, ToCursors, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
43#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable))]
44#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
45#[derive(csskit_derives::NodeWithMetadata)]
46pub struct CounterStyleRuleBlock<'a>(
47 #[metadata(delegate)] DeclarationList<'a, CounterStyleRuleStyleValue<'a>, CssMetadata>,
48);
49
50#[derive(ToSpan, ToCursors, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
51#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
52#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit)]
53#[derive(csskit_derives::NodeWithMetadata)]
54#[metadata(node_kinds = Declaration, property_kinds = Name)]
55pub enum CounterStyleRuleStyleValue<'a> {
56 Unknown(ComponentValues<'a>),
57 System(SystemStyleValue),
58 Symbols(SymbolsStyleValue<'a>),
59 AdditiveSymbols(AdditiveSymbolsStyleValue<'a>),
60 Negative(NegativeStyleValue<'a>),
61 Prefix(PrefixStyleValue<'a>),
62 Suffix(SuffixStyleValue<'a>),
63 Range(RangeStyleValue),
64 Pad(PadStyleValue<'a>),
65 SpeakAs(SpeakAsStyleValue),
66 Fallback(FallbackStyleValue),
67}
68
69impl<'a> DeclarationValue<'a, CssMetadata> for CounterStyleRuleStyleValue<'a> {
70 type ComputedValue = Computed<'a>;
71
72 fn valid_declaration_name<I>(p: &Parser<'a, I>, c: Cursor) -> bool
73 where
74 I: Iterator<Item = Cursor> + Clone,
75 {
76 matches!(p.to_atom::<CssAtomSet>(c), CssAtomSet::InitialValue | CssAtomSet::Inherits | CssAtomSet::Syntax)
77 }
78
79 fn is_unknown(&self) -> bool {
80 matches!(self, Self::Unknown(_))
81 }
82
83 fn is_initial(&self) -> bool {
84 false
85 }
86
87 fn is_inherit(&self) -> bool {
88 false
89 }
90
91 fn is_unset(&self) -> bool {
92 false
93 }
94
95 fn is_revert(&self) -> bool {
96 false
97 }
98
99 fn is_revert_layer(&self) -> bool {
100 false
101 }
102
103 fn needs_computing(&self) -> bool {
104 matches!(self, Self::Unknown(_))
105 }
106
107 fn parse_declaration_value<I>(p: &mut Parser<'a, I>, c: Cursor) -> ParserResult<Self>
108 where
109 I: Iterator<Item = Cursor> + Clone,
110 {
111 Ok(match p.to_atom::<CssAtomSet>(c) {
112 CssAtomSet::System => Self::System(p.parse::<SystemStyleValue>()?),
113 CssAtomSet::Symbols => Self::Symbols(p.parse::<SymbolsStyleValue<'a>>()?),
114 CssAtomSet::AdditiveSymbols => Self::AdditiveSymbols(p.parse::<AdditiveSymbolsStyleValue<'a>>()?),
115 CssAtomSet::Negative => Self::Negative(p.parse::<NegativeStyleValue<'a>>()?),
116 CssAtomSet::Prefix => Self::Prefix(p.parse::<PrefixStyleValue<'a>>()?),
117 CssAtomSet::Suffix => Self::Suffix(p.parse::<SuffixStyleValue<'a>>()?),
118 CssAtomSet::Range => Self::Range(p.parse::<RangeStyleValue>()?),
119 CssAtomSet::Pad => Self::Pad(p.parse::<PadStyleValue<'a>>()?),
120 CssAtomSet::SpeakAs => Self::SpeakAs(p.parse::<SpeakAsStyleValue>()?),
121 CssAtomSet::Fallback => Self::Fallback(p.parse::<FallbackStyleValue>()?),
122 _ => Self::Unknown(p.parse::<ComponentValues<'a>>()?),
123 })
124 }
125}
126
127#[syntax(" [ <integer [0,∞]> && <symbol> ]# ")]
128#[derive(
129 Peek, Parse, ToCursors, ToSpan, DeclarationMetadata, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
130)]
131#[declaration_metadata(initial = "n/a", inherits = False, property_group = CounterStyle)]
132#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
133#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit)]
134#[derive(csskit_derives::NodeWithMetadata)]
135pub struct AdditiveSymbolsStyleValue<'a>;
136
137#[derive(
138 Peek, Parse, ToCursors, ToSpan, DeclarationMetadata, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
139)]
140#[declaration_metadata(initial = "n/a", inherits = False, property_group = CounterStyle)]
141#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
142#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit)]
143#[derive(csskit_derives::NodeWithMetadata)]
144pub struct FallbackStyleValue(CounterStyleName);
145
146#[syntax(" <symbol> <symbol>? ")]
147#[derive(
148 Peek, Parse, ToCursors, ToSpan, DeclarationMetadata, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
149)]
150#[declaration_metadata(initial = "n/a", inherits = False, property_group = CounterStyle)]
151#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
152#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit)]
153#[derive(csskit_derives::NodeWithMetadata)]
154pub struct NegativeStyleValue<'a>;
155
156#[syntax(" <integer [0,∞]> && <symbol> ")]
157#[derive(
158 Peek, Parse, ToCursors, ToSpan, DeclarationMetadata, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
159)]
160#[declaration_metadata(initial = "n/a", inherits = False, property_group = CounterStyle)]
161#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
162#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit)]
163#[derive(csskit_derives::NodeWithMetadata)]
164pub struct PadStyleValue<'a>;
165
166#[syntax(" <symbol> ")]
167#[derive(
168 Peek, Parse, ToCursors, ToSpan, DeclarationMetadata, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
169)]
170#[declaration_metadata(initial = "n/a", inherits = False, property_group = CounterStyle)]
171#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
172#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit)]
173#[derive(csskit_derives::NodeWithMetadata)]
174pub struct PrefixStyleValue<'a>;
175
176pub type RangeStyleValue = Todo;
183
184#[syntax(" auto | bullets | numbers | words | spell-out | <counter-style-name> ")]
185#[derive(
186 Peek, Parse, ToCursors, ToSpan, DeclarationMetadata, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
187)]
188#[declaration_metadata(initial = "n/a", inherits = False, property_group = CounterStyle)]
189#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
190#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit)]
191#[derive(csskit_derives::NodeWithMetadata)]
192pub enum SpeakAsStyleValue {}
193
194#[syntax(" <symbol> ")]
195#[derive(
196 Peek, Parse, ToCursors, ToSpan, DeclarationMetadata, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
197)]
198#[declaration_metadata(initial = "n/a", inherits = False, property_group = CounterStyle)]
199#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
200#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit)]
201#[derive(csskit_derives::NodeWithMetadata)]
202pub struct SuffixStyleValue<'a>;
203
204#[syntax(" <symbol>+ ")]
205#[derive(
206 Peek, Parse, ToCursors, ToSpan, DeclarationMetadata, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
207)]
208#[declaration_metadata(initial = "n/a", inherits = False, property_group = CounterStyle)]
209#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
210#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit)]
211#[derive(csskit_derives::NodeWithMetadata)]
212pub struct SymbolsStyleValue<'a>;
213
214#[syntax(
215 " cyclic | numeric | alphabetic | symbolic | additive | [fixed <integer>?] | [ extends <counter-style-name> ] "
216)]
217#[derive(
218 Peek, Parse, ToCursors, ToSpan, DeclarationMetadata, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
219)]
220#[declaration_metadata(initial = "n/a", inherits = False, property_group = CounterStyle)]
221#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
222#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit)]
223#[derive(csskit_derives::NodeWithMetadata)]
224pub enum SystemStyleValue {}
225
226#[cfg(test)]
227mod tests {
228 use super::*;
229 use css_parse::assert_parse;
230
231 #[test]
232 fn size_test() {
233 assert_eq!(std::mem::size_of::<CounterStyleRule>(), 128);
234 assert_eq!(std::mem::size_of::<CounterStyleName>(), 12);
235 assert_eq!(std::mem::size_of::<CounterStyleRuleBlock>(), 96);
236 assert_eq!(std::mem::size_of::<CounterStyleRuleStyleValue>(), 80);
237 assert_eq!(std::mem::size_of::<AdditiveSymbolsStyleValue>(), 32);
238 assert_eq!(std::mem::size_of::<FallbackStyleValue>(), 12);
239 assert_eq!(std::mem::size_of::<NegativeStyleValue>(), 80);
240 assert_eq!(std::mem::size_of::<PadStyleValue>(), 56);
241 assert_eq!(std::mem::size_of::<PrefixStyleValue>(), 40);
242 assert_eq!(std::mem::size_of::<SpeakAsStyleValue>(), 16);
244 assert_eq!(std::mem::size_of::<SuffixStyleValue>(), 40);
245 assert_eq!(std::mem::size_of::<SymbolsStyleValue>(), 32);
246 assert_eq!(std::mem::size_of::<SystemStyleValue>(), 28);
247 }
248
249 #[test]
250 fn test_writes() {
251 assert_parse!(CssAtomSet::ATOMS, CounterStyleRule, "@counter-style thumbs {}");
252 }
253}