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