1use super::prelude::*;
2use crate::{CssAtomSet, types::CounterStyle};
3
4#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
5#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
6#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(skip))]
7#[derive(csskit_derives::NodeWithMetadata)]
8pub enum TextFunctionContent {
9 #[atom(CssAtomSet::Content)]
10 Content(T![Ident]),
11 #[atom(CssAtomSet::Before)]
12 Before(T![Ident]),
13 #[atom(CssAtomSet::After)]
14 After(T![Ident]),
15 #[atom(CssAtomSet::FirstLetter)]
16 FirstLetter(T![Ident]),
17}
18
19#[derive(Parse, Peek, ToCursors, IntoCursor, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
20#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
21pub enum TargetCounterKind {
22 String(T![String]),
23 Url(T![Url]),
24}
25
26#[derive(Parse, Peek, ToSpan, ToCursors, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
32#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
33#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit)]
34#[derive(csskit_derives::NodeWithMetadata)]
35pub enum Target<'a> {
36 TargetCounter(TargetCounterFunction<'a>),
39 TargetCounters(TargetCountersFunction<'a>),
42 TargetText(TargetTextFunction),
45}
46
47#[derive(Parse, Peek, ToSpan, ToCursors, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
48#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
49#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
50#[derive(csskit_derives::NodeWithMetadata)]
51pub struct TargetCounterFunction<'a> {
52 #[atom(CssAtomSet::TargetCounter)]
53 pub name: T![Function],
54 pub params: TargetCounterParams<'a>,
55 pub close: T![')'],
56}
57
58#[derive(Parse, Peek, ToSpan, ToCursors, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
59#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
60pub struct TargetCounterParams<'a>(
61 TargetCounterKind,
62 Option<T![,]>,
63 T![Ident],
64 Option<T![,]>,
65 Option<CounterStyle<'a>>,
66);
67
68#[derive(Parse, Peek, ToSpan, ToCursors, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
69#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
70#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
71#[derive(csskit_derives::NodeWithMetadata)]
72pub struct TargetCountersFunction<'a> {
73 #[atom(CssAtomSet::TargetCounters)]
74 pub name: T![Function],
75 pub params: TargetCountersParams<'a>,
76 pub close: T![')'],
77}
78
79#[derive(Parse, Peek, ToSpan, ToCursors, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
80#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
81pub struct TargetCountersParams<'a>(
82 TargetCounterKind,
83 Option<T![,]>,
84 T![Ident],
85 Option<T![,]>,
86 T![String],
87 Option<T![,]>,
88 Option<CounterStyle<'a>>,
89);
90
91#[derive(Parse, Peek, ToSpan, ToCursors, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
92#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
93#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
94#[derive(csskit_derives::NodeWithMetadata)]
95pub struct TargetTextFunction {
96 #[atom(CssAtomSet::TargetText)]
97 pub name: T![Function],
98 pub params: TargetTextParams,
99 pub close: T![')'],
100}
101
102#[derive(Parse, Peek, ToSpan, ToCursors, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
103#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
104pub struct TargetTextParams(TargetCounterKind, Option<T![,]>, Option<TextFunctionContent>);
105
106#[cfg(test)]
107mod tests {
108 use super::*;
109 use crate::CssAtomSet;
110 use css_parse::{assert_parse, assert_parse_error};
111
112 #[test]
113 fn size_test() {
114 assert_eq!(std::mem::size_of::<Target>(), 184);
115 }
116
117 #[test]
118 fn test_writes() {
119 assert_parse!(CssAtomSet::ATOMS, Target, "target-counter('foo',bar,lower-roman)");
120 assert_parse!(CssAtomSet::ATOMS, Target, "target-counters('foo',bar,'baz',lower-roman)");
121 assert_parse!(CssAtomSet::ATOMS, Target, "target-text('foo')");
122 assert_parse!(CssAtomSet::ATOMS, Target, "target-text('foo',before)");
123 }
124
125 #[test]
126 fn test_errors() {
127 assert_parse_error!(CssAtomSet::ATOMS, Target, "target-counter()");
128 assert_parse_error!(CssAtomSet::ATOMS, Target, "target-counter('foo')");
129 assert_parse_error!(CssAtomSet::ATOMS, Target, "target-counters()");
130 assert_parse_error!(CssAtomSet::ATOMS, Target, "target-counters('foo')");
131 assert_parse_error!(CssAtomSet::ATOMS, Target, "target-counters('foo',bar)");
132 assert_parse_error!(CssAtomSet::ATOMS, Target, "target-text()");
133 assert_parse_error!(CssAtomSet::ATOMS, Target, "target-text(123)");
134 }
135}