1use crate::{CssAtomSet, CssDiagnostic};
2use bumpalo::collections::Vec;
3use css_lexer::Kind;
4use css_parse::{Cursor, Diagnostic, Parse, Parser, Peek, Result as ParserResult, T};
5use csskit_derives::{Parse, SemanticEq, ToCursors, ToSpan};
6
7use super::CompoundSelector;
8
9#[derive(ToSpan, ToCursors, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
11#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit)]
12#[derive(csskit_derives::NodeWithMetadata)]
13#[cfg_attr(feature = "css_feature_data", derive(::csskit_derives::ToCSSFeature), css_feature("css.selectors"))]
14pub enum FunctionalPseudoElement<'a> {
15 Highlight(HighlightPseudoElement),
17 Part(PartPseudoElement<'a>),
19 Picker(PickerPseudoElement),
21 Slotted(SlottedPseudoElement<'a>),
23 ViewTransitionGroup(ViewTransitionGroupPseudoElement<'a>),
26 ViewTransitionImagePair(ViewTransitionImagePairPseudoElement<'a>),
28 ViewTransitionNew(ViewTransitionNewPseudoElement<'a>),
30 ViewTransitionOld(ViewTransitionOldPseudoElement<'a>),
32}
33
34impl<'a> Peek<'a> for FunctionalPseudoElement<'a> {
35 fn peek<I>(p: &Parser<'a, I>, _: css_lexer::Cursor) -> bool
36 where
37 I: Iterator<Item = Cursor> + Clone,
38 {
39 p.peek::<T![::]>() && p.peek_n(3) == Kind::Function
40 }
41}
42
43impl<'a> Parse<'a> for FunctionalPseudoElement<'a> {
44 fn parse<I>(p: &mut Parser<'a, I>) -> ParserResult<Self>
45 where
46 I: Iterator<Item = Cursor> + Clone,
47 {
48 match p.to_atom::<CssAtomSet>(p.peek_n(3)) {
49 CssAtomSet::Highlight => p.parse::<HighlightPseudoElement>().map(Self::Highlight),
50 CssAtomSet::Part => p.parse::<PartPseudoElement>().map(Self::Part),
51 CssAtomSet::Picker => p.parse::<PickerPseudoElement>().map(Self::Picker),
52 CssAtomSet::Slotted => p.parse::<SlottedPseudoElement>().map(Self::Slotted),
53 CssAtomSet::ViewTransitionGroup => {
54 p.parse::<ViewTransitionGroupPseudoElement>().map(Self::ViewTransitionGroup)
55 }
56 CssAtomSet::ViewTransitionImagePair => {
57 p.parse::<ViewTransitionImagePairPseudoElement>().map(Self::ViewTransitionImagePair)
58 }
59 CssAtomSet::ViewTransitionNew => p.parse::<ViewTransitionNewPseudoElement>().map(Self::ViewTransitionNew),
60 CssAtomSet::ViewTransitionOld => p.parse::<ViewTransitionOldPseudoElement>().map(Self::ViewTransitionOld),
61 _ => Err(Diagnostic::new(p.next(), Diagnostic::unexpected_pseudo_element))?,
62 }
63 }
64}
65
66#[derive(Parse, ToSpan, ToCursors, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
67#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
68#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
69#[derive(csskit_derives::NodeWithMetadata)]
70pub struct HighlightPseudoElement {
71 pub colons: T![::],
72 #[atom(CssAtomSet::Highlight)]
73 pub function: T![Function],
74 pub value: T![Ident],
75 pub close: T![')'],
76}
77
78#[derive(Parse, ToSpan, ToCursors, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
79#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
80#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit)]
81#[derive(csskit_derives::NodeWithMetadata)]
82pub struct SlottedPseudoElement<'a> {
83 #[cfg_attr(feature = "visitable", visit(skip))]
84 pub colons: T![::],
85 #[cfg_attr(feature = "visitable", visit(skip))]
86 #[atom(CssAtomSet::Slotted)]
87 pub function: T![Function],
88 pub value: CompoundSelector<'a>,
89 #[cfg_attr(feature = "visitable", visit(skip))]
90 pub close: Option<T![')']>,
91}
92
93#[derive(Parse, ToSpan, ToCursors, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
94#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
95#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
96#[derive(csskit_derives::NodeWithMetadata)]
97pub struct PartPseudoElement<'a> {
98 pub colons: T![::],
99 #[atom(CssAtomSet::Part)]
100 pub function: T![Function],
101 pub value: Vec<'a, T![Ident]>,
102 pub close: Option<T![')']>,
103}
104
105#[derive(Parse, ToSpan, ToCursors, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
106#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
107#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
108#[derive(csskit_derives::NodeWithMetadata)]
109pub struct PickerPseudoElement {
110 pub colons: T![::],
111 #[atom(CssAtomSet::Picker)]
112 pub function: T![Function],
113 pub value: T![Ident],
114 pub close: Option<T![')']>,
115}
116
117#[derive(Parse, ToSpan, ToCursors, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
118#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
119#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
120#[derive(csskit_derives::NodeWithMetadata)]
121pub struct ViewTransitionGroupPseudoElement<'a> {
122 pub colons: T![::],
123 #[atom(CssAtomSet::ViewTransitionGroup)]
124 pub function: T![Function],
125 pub value: PtNameAndClassSelector<'a>,
126 pub close: Option<T![')']>,
127}
128
129#[derive(Parse, ToSpan, ToCursors, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
130#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
131#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
132#[derive(csskit_derives::NodeWithMetadata)]
133pub struct ViewTransitionImagePairPseudoElement<'a> {
134 pub colons: T![::],
135 #[atom(CssAtomSet::ViewTransitionImagePair)]
136 pub function: T![Function],
137 pub value: PtNameAndClassSelector<'a>,
138 pub close: Option<T![')']>,
139}
140
141#[derive(Parse, ToSpan, ToCursors, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
142#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
143#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
144#[derive(csskit_derives::NodeWithMetadata)]
145pub struct ViewTransitionNewPseudoElement<'a> {
146 pub colons: T![::],
147 #[atom(CssAtomSet::ViewTransitionNew)]
148 pub function: T![Function],
149 pub value: PtNameAndClassSelector<'a>,
150 pub close: Option<T![')']>,
151}
152
153#[derive(Parse, ToSpan, ToCursors, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
154#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
155#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
156#[derive(csskit_derives::NodeWithMetadata)]
157pub struct ViewTransitionOldPseudoElement<'a> {
158 pub colons: T![::],
159 #[atom(CssAtomSet::ViewTransitionOld)]
160 pub function: T![Function],
161 pub value: PtNameAndClassSelector<'a>,
162 pub close: Option<T![')']>,
163}
164
165#[derive(Parse, ToSpan, ToCursors, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
166#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
167#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
168#[derive(csskit_derives::NodeWithMetadata)]
169pub enum PtNameAndClassSelector<'a> {
170 Wildcard(T![*]),
171 Named(T![Ident], Vec<'a, (T![.], T![Ident])>),
172 Classes(Vec<'a, (T![.], T![Ident])>),
173}