Skip to main content

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::*;
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(
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
176// #[syntax(" [ [ <integer> | infinite ]{2} ]# | auto ")]
177// #[derive(Peek, Parse, ToCursors, ToSpan, DeclarationMetadata, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
178// #[declaration_metadata(initial = "n/a", inherits = False, property_group = CounterStyle)]
179// #[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
180// #[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit)]
181// pub struct RangeStyleValue<'a>;
182pub 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::<RangeStyleValue>(), 1);
243		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}