css_ast/selector/
moz.rs

1use crate::{DirValue, diagnostics};
2use css_parse::{
3	Build, Cursor, Parse, Parser, Result as ParserResult, T, function_set, pseudo_class, pseudo_element,
4	syntax::CommaSeparated,
5};
6use csskit_derives::{ToCursors, Visitable};
7
8pseudo_element!(
9	/// https://developer.mozilla.org/en-US/docs/Web/CSS/Mozilla_Extensions#pseudo-elements_and_pseudo-classes
10	#[derive(Visitable)]
11	#[visit(self)]
12	pub enum MozPseudoElement {
13		AnonymousBlock: "-moz-anonymous-block",
14		AnonymousItem: "-moz-anonymous-item",
15		AnonymousPositionedBlock: "-moz-anonymous-positioned-block",
16		BlockInsideInlineWrapper: "-moz-block-inside-inline-wrapper",
17		BlockRubyContent: "-moz-block-ruby-content",
18		ButtonContent: "-moz-button-content",
19		Canvas: "-moz-canvas",
20		CellContent: "-moz-cell-content",
21		ColorSwatch: "-moz-color-swatch",
22		ColumnContent: "-moz-column-content",
23		ColumnSet: "-moz-column-set",
24		ColumnSpanWrapper: "-moz-column-span-wrapper",
25		DropdownList: "-moz-dropdown-list",
26		FieldsetContent: "-moz-fieldset-content",
27		FirstLetterContinuation: "-moz-first-letter-continuation",
28		FocusInner: "-moz-focus-inner",
29		FocusOuter: "-moz-focus-outer",
30		FramesetBlank: "-moz-frameset-blank",
31		HframesetBorder: "-moz-hframeset-border",
32		HtmlCanvasContent: "-moz-html-canvas-content",
33		InlineTable: "-moz-inline-table",
34		LineFrame: "-moz-line-frame",
35		ListBullet: "-moz-list-bullet",
36		ListNumber: "-moz-list-number",
37		MathmlAnonymousBlock: "-moz-mathml-anonymous-block",
38		NumberSpinBox: "-moz-number-spin-box",
39		NumberSpinDown: "-moz-number-spin-down",
40		NumberSpinUp: "-moz-number-spin-up",
41		OofPlaceholder: "-moz-oof-placeholder",
42		Page: "-moz-page",
43		PageBreak: "-moz-page-break",
44		PageContent: "-moz-page-content",
45		PageSequence: "-moz-page-sequence",
46		Pagebreak: "-moz-pagebreak",
47		Pagecontent: "-moz-pagecontent",
48		Placeholder: "-moz-placeholder",
49		PrintedSheet: "-moz-printed-sheet",
50		ProgressBar: "-moz-progress-bar",
51		RangeProgress: "-moz-range-progress",
52		RangeThumb: "-moz-range-thumb",
53		RangeTrack: "-moz-range-track",
54		Reveal: "-moz-reveal",
55		Ruby: "-moz-ruby",
56		RubyBase: "-moz-ruby-base",
57		RubyBaseContainer: "-moz-ruby-base-container",
58		RubyText: "-moz-ruby-text",
59		RubyTextContainer: "-moz-ruby-text-container",
60		ScrolledCanvas: "-moz-scrolled-canvas",
61		ScrolledContent: "-moz-scrolled-content",
62		ScrolledPageSequence: "-moz-scrolled-page-sequence",
63		SearchClearButton: "-moz-search-clear-button",
64		Selection: "-moz-selection",
65		SvgForeignContent: "-moz-svg-foreign-content",
66		SvgMarkerAnonChild: "-moz-svg-marker-anon-child",
67		SvgMarkerOuterSvgAnonChild: "-moz-svg-marker-outer-svg-anon-child",
68		SvgText: "-moz-svg-text",
69		Table: "-moz-table",
70		TableCell: "-moz-table-cell",
71		TableColumn: "-moz-table-column",
72		TableColumnGroup: "-moz-table-column-group",
73		TableOuter: "-moz-table-outer",
74		TableRow: "-moz-table-row",
75		TableRowGroup: "-moz-table-row-group",
76		TableWrapper: "-moz-table-wrapper",
77		TextControlEditingRoot: "-moz-text-control-editing-root",
78		TextControlPreview: "-moz-text-control-preview",
79		TreeCell: "-moz-tree-cell",
80		TreeCheckbox: "-moz-tree-checkbox",
81		TreeDropFeedback: "-moz-tree-drop-feedback",
82		TreeIndentation: "-moz-tree-indentation",
83		TreeSeparator: "-moz-tree-separator",
84		VframesetBorder: "-moz-vframeset-border",
85		Viewport: "-moz-viewport",
86		ViewportScroll: "-moz-viewport-scroll",
87	}
88);
89
90#[derive(ToCursors, Visitable, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
91#[cfg_attr(feature = "serde", derive(serde::Serialize), serde(rename_all = "kebab-case"))]
92#[visit(self)]
93pub enum MozFunctionalPseudoElement<'a> {
94	TreeCell(T![::], T![Function], CommaSeparated<'a, T![Ident]>, T![')']),
95	TreeCellText(T![::], T![Function], CommaSeparated<'a, T![Ident]>, T![')']),
96	TreeCheckbox(T![::], T![Function], CommaSeparated<'a, T![Ident]>, T![')']),
97	TreeColumn(T![::], T![Function], CommaSeparated<'a, T![Ident]>, T![')']),
98	TreeImage(T![::], T![Function], CommaSeparated<'a, T![Ident]>, T![')']),
99	TreeLine(T![::], T![Function], CommaSeparated<'a, T![Ident]>, T![')']),
100	TreeRow(T![::], T![Function], CommaSeparated<'a, T![Ident]>, T![')']),
101	TreeSeparator(T![::], T![Function], CommaSeparated<'a, T![Ident]>, T![')']),
102	TreeTwisty(T![::], T![Function], CommaSeparated<'a, T![Ident]>, T![')']),
103}
104
105function_set!(
106	pub enum MozFunctionalPseudoElementKeyword {
107		TreeCell: "-moz-tree-cell",
108		TreeCellText: "-moz-tree-cell-text",
109		TreeCheckbox: "-moz-tree-checkbox",
110		TreeColumn: "-moz-tree-column",
111		TreeImage: "-moz-tree-image",
112		TreeLine: "-moz-tree-line",
113		TreeRow: "-moz-tree-row",
114		TreeSeparator: "-moz-tree-separator",
115		TreeTwisty: "-moz-tree-twisty",
116	}
117);
118
119impl<'a> Parse<'a> for MozFunctionalPseudoElement<'a> {
120	fn parse(p: &mut Parser<'a>) -> ParserResult<Self> {
121		let colons = p.parse::<T![::]>()?;
122		let keyword = p.parse::<MozFunctionalPseudoElementKeyword>()?;
123		let function = <T![Function]>::build(p, keyword.into());
124		let items = p.parse::<CommaSeparated<'a, T![Ident]>>()?;
125		let close = p.parse::<T![')']>()?;
126		Ok(match keyword {
127			MozFunctionalPseudoElementKeyword::TreeCell(_) => Self::TreeCell(colons, function, items, close),
128			MozFunctionalPseudoElementKeyword::TreeCellText(_) => Self::TreeCellText(colons, function, items, close),
129			MozFunctionalPseudoElementKeyword::TreeCheckbox(_) => Self::TreeCheckbox(colons, function, items, close),
130			MozFunctionalPseudoElementKeyword::TreeColumn(_) => Self::TreeColumn(colons, function, items, close),
131			MozFunctionalPseudoElementKeyword::TreeImage(_) => Self::TreeImage(colons, function, items, close),
132			MozFunctionalPseudoElementKeyword::TreeLine(_) => Self::TreeLine(colons, function, items, close),
133			MozFunctionalPseudoElementKeyword::TreeRow(_) => Self::TreeRow(colons, function, items, close),
134			MozFunctionalPseudoElementKeyword::TreeSeparator(_) => Self::TreeSeparator(colons, function, items, close),
135			MozFunctionalPseudoElementKeyword::TreeTwisty(_) => Self::TreeTwisty(colons, function, items, close),
136		})
137	}
138}
139
140pseudo_class!(
141	/// <https://developer.mozilla.org/en-US/docs/Web/CSS/Mozilla_Extensions#pseudo-elements_and_pseudo-classes>
142	#[derive(Visitable)]
143	#[visit(self)]
144	pub enum MozPseudoClass {
145		Any: "-moz-any",
146		AnyLink: "-moz-any-link",
147		Broken: "-moz-broken",
148		DragOver: "-moz-drag-over",
149		FirstNode: "-moz-first-node",
150		FocusRing: "-moz-focusring",
151		FullScreen: "-moz-full-screen",
152		FullScreenAncestor: "-moz-full-screen-ancestor",
153		HandlerBlocked: "-moz-handler-blocked",
154		HandlerCrashed: "-moz-handler-crashed",
155		HandlerDisabled: "-moz-handler-disabled",
156		LastNode: "-moz-last-node",
157		Loading: "-moz-loading",
158		LwTheme: "-moz-lwtheme",
159		LwThemeBrighttext: "-moz-lwtheme-brighttext",
160		LwThemeDarktext: "-moz-lwtheme-darktext",
161		NativeAnonymous: "-moz-native-anonymous",
162		OnlyWhitespace: "-moz-only-whitespace",
163		PlaceholderShown: "-moz-placeholder-shown",
164		ReadOnly: "-moz-read-only",
165		ReadWrite: "-moz-read-write",
166		SubmitInvalid: "-moz-submit-invalid",
167		Suppressed: "-moz-suppressed",
168		UiInvalid: "-moz-ui-invalid",
169		UiValid: "-moz-ui-valid",
170		UserDisabled: "-moz-user-disabled",
171		WindowInactive: "-moz-window-inactive",
172	}
173);
174
175#[derive(ToCursors, Visitable, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
176#[cfg_attr(feature = "serde", derive(serde::Serialize), serde(rename_all = "kebab-case"))]
177#[visit]
178pub enum MozFunctionalPseudoClass {
179	LocaleDir(MozLocaleDirFunctionalPseudoClass),
180}
181
182impl<'a> Parse<'a> for MozFunctionalPseudoClass {
183	fn parse(p: &mut Parser<'a>) -> ParserResult<Self> {
184		let colon = p.parse::<T![:]>()?;
185		let function = p.parse::<T![Function]>()?;
186		let c: Cursor = function.into();
187		if p.eq_ignore_ascii_case(c, "-moz-locale-dir") {
188			let value = p.parse::<DirValue>()?;
189			let close = p.parse_if_peek::<T![')']>()?;
190			Ok(Self::LocaleDir(MozLocaleDirFunctionalPseudoClass { colon, function, value, close }))
191		} else {
192			Err(diagnostics::UnexpectedFunction(p.parse_str(c).into(), c))?
193		}
194	}
195}
196
197#[derive(ToCursors, Visitable, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
198#[cfg_attr(feature = "serde", derive(serde::Serialize), serde(rename_all = "kebab-case"))]
199#[visit(self)]
200pub struct MozLocaleDirFunctionalPseudoClass {
201	pub colon: T![:],
202	pub function: T![Function],
203	pub value: DirValue,
204	pub close: Option<T![')']>,
205}
206
207#[cfg(test)]
208mod tests {
209	use super::*;
210	use css_parse::assert_parse;
211
212	#[test]
213	fn size_test() {
214		assert_eq!(std::mem::size_of::<MozPseudoElement>(), 40);
215		assert_eq!(std::mem::size_of::<MozFunctionalPseudoElement>(), 88);
216		assert_eq!(std::mem::size_of::<MozPseudoClass>(), 28);
217		assert_eq!(std::mem::size_of::<MozFunctionalPseudoClass>(), 56);
218	}
219
220	#[test]
221	fn test_writes() {
222		assert_parse!(MozPseudoElement, "::-moz-anonymous-block");
223		assert_parse!(MozFunctionalPseudoElement, "::-moz-tree-twisty(selected,focus)");
224	}
225}