css_ast/rules/
counter_style.rs

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/// <https://drafts.csswg.org/css-counter-styles-3/#the-counter-style-rule>
9#[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
174// #[syntax(" [ [ <integer> | infinite ]{2} ]# | auto ")]
175// #[derive(Peek, Parse, ToCursors, ToSpan, DeclarationMetadata, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
176// #[declaration_metadata(initial = "n/a", inherits = False, property_group = CounterStyle)]
177// #[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
178// #[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit)]
179// pub struct RangeStyleValue<'a>;
180pub 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::<RangeStyleValue>(), 1);
241		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}