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