Skip to main content

css_ast/rules/
counter_style.rs

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