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(
20 Parse, Peek, ToCursors, IntoCursor, ToSpan, SemanticEq, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
21)]
22#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
23pub enum TargetCounterKind {
24 String(T![String]),
25 Url(T![Url]),
26}
27
28#[derive(Parse, Peek, ToSpan, ToCursors, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
34#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
35#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit)]
36#[derive(csskit_derives::NodeWithMetadata)]
37pub enum Target<'a> {
38 TargetCounter(TargetCounterFunction<'a>),
44 TargetCounters(TargetCountersFunction<'a>),
50 TargetText(TargetTextFunction),
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())]
60#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
61#[derive(csskit_derives::NodeWithMetadata)]
62pub struct TargetCounterFunction<'a> {
63 #[atom(CssAtomSet::TargetCounter)]
64 pub name: T![Function],
65 pub params: TargetCounterParams<'a>,
66 pub close: T![')'],
67}
68
69#[derive(Parse, Peek, ToSpan, ToCursors, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
70#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
71pub struct TargetCounterParams<'a>(
72 TargetCounterKind,
73 Option<T![,]>,
74 T![Ident],
75 Option<T![,]>,
76 Option<CounterStyle<'a>>,
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())]
81#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
82#[derive(csskit_derives::NodeWithMetadata)]
83pub struct TargetCountersFunction<'a> {
84 #[atom(CssAtomSet::TargetCounters)]
85 pub name: T![Function],
86 pub params: TargetCountersParams<'a>,
87 pub close: T![')'],
88}
89
90#[derive(Parse, Peek, ToSpan, ToCursors, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
91#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
92pub struct TargetCountersParams<'a>(
93 TargetCounterKind,
94 Option<T![,]>,
95 T![Ident],
96 Option<T![,]>,
97 T![String],
98 Option<T![,]>,
99 Option<CounterStyle<'a>>,
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())]
104#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
105#[derive(csskit_derives::NodeWithMetadata)]
106pub struct TargetTextFunction {
107 #[atom(CssAtomSet::TargetText)]
108 pub name: T![Function],
109 pub params: TargetTextParams,
110 pub close: T![')'],
111}
112
113#[derive(Parse, Peek, ToSpan, ToCursors, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
114#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
115pub struct TargetTextParams(TargetCounterKind, Option<T![,]>, Option<TextFunctionContent>);
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120 use crate::CssAtomSet;
121 use css_parse::{assert_parse, assert_parse_error};
122
123 #[test]
124 fn size_test() {
125 assert_eq!(std::mem::size_of::<Target>(), 184);
126 }
127
128 #[test]
129 fn test_writes() {
130 assert_parse!(CssAtomSet::ATOMS, Target, "target-counter('foo',bar,lower-roman)");
131 assert_parse!(CssAtomSet::ATOMS, Target, "target-counters('foo',bar,'baz',lower-roman)");
132 assert_parse!(CssAtomSet::ATOMS, Target, "target-text('foo')");
133 assert_parse!(CssAtomSet::ATOMS, Target, "target-text('foo',before)");
134 }
135
136 #[test]
137 fn test_errors() {
138 assert_parse_error!(CssAtomSet::ATOMS, Target, "target-counter()");
139 assert_parse_error!(CssAtomSet::ATOMS, Target, "target-counter('foo')");
140 assert_parse_error!(CssAtomSet::ATOMS, Target, "target-counters()");
141 assert_parse_error!(CssAtomSet::ATOMS, Target, "target-counters('foo')");
142 assert_parse_error!(CssAtomSet::ATOMS, Target, "target-counters('foo',bar)");
143 assert_parse_error!(CssAtomSet::ATOMS, Target, "target-text()");
144 assert_parse_error!(CssAtomSet::ATOMS, Target, "target-text(123)");
145 }
146}