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