css_ast/functions/
transform_functions.rs

1use super::prelude::*;
2use crate::{AngleOrZero, Length, LengthPercentage, NoneOr, NumberOrPercentage};
3
4// https://drafts.csswg.org/css-transforms-1/#two-d-transform-functions
5#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
6#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
7#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit)]
8#[allow(clippy::large_enum_variant)] // TODO: matrix3d should probably be boxed
9pub enum TransformFunction {
10	Matrix(MatrixFunction),
11	Matrix3d(Matrix3dFunction),
12	Translate(TranslateFunction),
13	Translate3d(Translate3dFunction),
14	TranslateX(TranslatexFunction),
15	TranslateY(TranslateyFunction),
16	TranslateZ(TranslatezFunction),
17	Scale(ScaleFunction),
18	Scale3d(Scale3dFunction),
19	ScaleX(ScalexFunction),
20	ScaleY(ScaleyFunction),
21	ScaleZ(ScalezFunction),
22	Rotate(RotateFunction),
23	Rotate3d(Rotate3dFunction),
24	RotateX(RotatexFunction),
25	RotateY(RotateyFunction),
26	RotateZ(RotatezFunction),
27	Skew(SkewFunction),
28	SkewX(SkewxFunction),
29	SkewY(SkewyFunction),
30	Perspective(PerspectiveFunction),
31}
32
33/// <https://drafts.csswg.org/css-transforms-1/#funcdef-transform-matrix>
34///
35/// ```text,ignore
36/// matrix() = matrix( <number>#{6} )
37/// ```
38#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
39#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
40#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
41pub struct MatrixFunction {
42	#[atom(CssAtomSet::Matrix)]
43	pub name: T![Function],
44	pub params: MatrixFunctionParams,
45	pub close: T![')'],
46}
47
48#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
49#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
50pub struct MatrixFunctionParams(
51	pub T![Number],
52	pub Option<T![,]>,
53	pub T![Number],
54	pub Option<T![,]>,
55	pub T![Number],
56	pub Option<T![,]>,
57	pub T![Number],
58	pub Option<T![,]>,
59	pub T![Number],
60	pub Option<T![,]>,
61	pub T![Number],
62);
63
64/// <https://drafts.csswg.org/css-transforms-2/#funcdef-matrix3d>
65///
66/// ```text,ignore
67/// matrix3d() = matrix3d( <number>#{16} )
68/// ```
69#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
70#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
71#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
72pub struct Matrix3dFunction {
73	#[atom(CssAtomSet::Matrix3d)]
74	pub name: T![Function],
75	pub params: Matrix3dFunctionParams,
76	pub close: T![')'],
77}
78
79#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
80#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
81#[allow(clippy::type_complexity)] // TODO: simplify types
82pub struct Matrix3dFunctionParams(
83	pub T![Number],
84	pub Option<T![,]>,
85	pub T![Number],
86	pub Option<T![,]>,
87	pub T![Number],
88	pub Option<T![,]>,
89	pub T![Number],
90	pub Option<T![,]>,
91	pub T![Number],
92	pub Option<T![,]>,
93	pub T![Number],
94	pub Option<T![,]>,
95	pub T![Number],
96	pub Option<T![,]>,
97	pub T![Number],
98	pub Option<T![,]>,
99	pub T![Number],
100	pub Option<T![,]>,
101	pub T![Number],
102	pub Option<T![,]>,
103	pub T![Number],
104	pub Option<T![,]>,
105	pub T![Number],
106	pub Option<T![,]>,
107	pub T![Number],
108	pub Option<T![,]>,
109	pub T![Number],
110	pub Option<T![,]>,
111	pub T![Number],
112	pub Option<T![,]>,
113	pub T![Number],
114);
115
116/// <https://drafts.csswg.org/css-transforms-1/#funcdef-transform-translate>
117///
118/// ```text,ignore
119/// translate() = translate( <length-percentage> , <length-percentage>? )
120/// ```
121#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
122#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
123#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
124pub struct TranslateFunction {
125	#[atom(CssAtomSet::Translate)]
126	pub name: T![Function],
127	pub x: LengthPercentage,
128	pub comma: Option<T![,]>,
129	pub y: Option<LengthPercentage>,
130	pub close: T![')'],
131}
132
133/// <https://drafts.csswg.org/css-transforms-2/#funcdef-translate3d>
134///
135/// ```text,ignore
136/// translate3d() = translate3d( <length-percentage> , <length-percentage> , <length> )
137/// ```
138#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
139#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
140#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
141pub struct Translate3dFunction {
142	#[atom(CssAtomSet::Translate3d)]
143	pub name: T![Function],
144	pub params: Translate3dFunctionParams,
145	pub close: T![')'],
146}
147
148#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
149#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
150pub struct Translate3dFunctionParams(
151	pub LengthPercentage,
152	pub Option<T![,]>,
153	pub LengthPercentage,
154	pub Option<T![,]>,
155	pub Length,
156);
157
158/// <https://drafts.csswg.org/css-transforms-1/#funcdef-transform-translatex>
159///
160/// ```text,ignore
161/// translateX() = translateX( <length-percentage> )
162/// ```
163#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
164#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
165#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
166pub struct TranslatexFunction {
167	#[atom(CssAtomSet::Translatex)]
168	pub name: T![Function],
169	pub params: LengthPercentage,
170	pub close: T![')'],
171}
172
173/// <https://drafts.csswg.org/css-transforms-1/#funcdef-transform-translatey>
174///
175/// ```text,ignore
176/// translateY() = translateY( <length-percentage> )
177/// ```
178#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
179#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
180#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
181pub struct TranslateyFunction {
182	#[atom(CssAtomSet::Translatey)]
183	pub name: T![Function],
184	pub params: LengthPercentage,
185	pub close: T![')'],
186}
187
188/// <https://drafts.csswg.org/css-transforms-2/#funcdef-translatez>
189///
190/// ```text,ignore
191/// translateZ() = translateZ( <length> )
192/// ```
193#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
194#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
195#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
196pub struct TranslatezFunction {
197	#[atom(CssAtomSet::Translatez)]
198	pub name: T![Function],
199	pub params: Length,
200	pub close: T![')'],
201}
202
203/// <https://drafts.csswg.org/css-transforms-2/#funcdef-scale>
204///
205/// ```text,ignore
206/// scale() = scale( [ <number> | <percentage> ]#{1,2} )
207/// ```
208#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
209#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
210#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
211pub struct ScaleFunction {
212	#[atom(CssAtomSet::Scale)]
213	pub name: T![Function],
214	pub params: (NumberOrPercentage, Option<T![,]>, Option<NumberOrPercentage>),
215	pub close: T![')'],
216}
217
218/// <https://drafts.csswg.org/css-transforms-2/#funcdef-scale3d>
219///
220/// ```text,ignore
221/// scale3d() = scale3d( [ <number> | <percentage> ]#{3} )
222/// ```
223#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
224#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
225#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
226pub struct Scale3dFunction {
227	#[atom(CssAtomSet::Scale3d)]
228	pub name: T![Function],
229	pub params: Scale3dFunctionParams,
230	pub close: T![')'],
231}
232
233#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
234#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
235pub struct Scale3dFunctionParams(
236	pub NumberOrPercentage,
237	pub Option<T![,]>,
238	pub NumberOrPercentage,
239	pub Option<T![,]>,
240	pub NumberOrPercentage,
241);
242
243/// <https://drafts.csswg.org/css-transforms-2/#funcdef-scalex>
244///
245/// ```text,ignore
246/// scaleX() = scaleX( <number> | <percentage> )
247/// ````
248#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
249#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
250#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
251pub struct ScalexFunction {
252	#[atom(CssAtomSet::Scalex)]
253	pub name: T![Function],
254	pub params: NumberOrPercentage,
255	pub close: T![')'],
256}
257
258/// <https://drafts.csswg.org/css-transforms-2/#funcdef-scaley>
259///
260/// ```text,ignore
261/// scaleY() = scaleY( <number> | <percentage> )
262/// ````
263#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
264#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
265#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
266pub struct ScaleyFunction {
267	#[atom(CssAtomSet::Scaley)]
268	pub name: T![Function],
269	pub params: NumberOrPercentage,
270	pub close: T![')'],
271}
272
273/// <https://drafts.csswg.org/css-transforms-2/#funcdef-scalez>
274///
275/// ```text,ignore
276/// scaleZ() = scaleZ( <number> | <percentage> )
277/// ````
278#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
279#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
280#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
281pub struct ScalezFunction {
282	#[atom(CssAtomSet::Scalez)]
283	pub name: T![Function],
284	pub params: NumberOrPercentage,
285	pub close: T![')'],
286}
287
288/// <https://drafts.csswg.org/css-transforms-1/#funcdef-transform-rotate>
289///
290/// ```text,ignore
291/// rotate() = rotate( [ <angle> | <zero> ] )
292/// ```
293#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
294#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
295#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
296pub struct RotateFunction {
297	#[atom(CssAtomSet::Rotate)]
298	pub name: T![Function],
299	pub params: AngleOrZero,
300	pub close: T![')'],
301}
302
303/// <https://drafts.csswg.org/css-transforms-2/#funcdef-rotate3d>
304///
305/// ```text,ignore
306/// rotate3d() = rotate3d( <number> , <number> , <number> , [ <angle> | <zero> ] )
307/// ```
308#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
309#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
310#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
311pub struct Rotate3dFunction {
312	#[atom(CssAtomSet::Rotate3d)]
313	pub name: T![Function],
314	pub params: Rotate3dFunctionParams,
315	pub close: T![')'],
316}
317
318#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
319#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
320pub struct Rotate3dFunctionParams(
321	pub T![Number],
322	pub Option<T![,]>,
323	pub T![Number],
324	pub Option<T![,]>,
325	pub T![Number],
326	pub Option<T![,]>,
327	pub AngleOrZero,
328);
329
330/// <https://drafts.csswg.org/css-transforms-2/#funcdef-rotatex>
331///
332/// ```text,ignore
333/// rotateX() = rotateX( [ <angle> | <zero> ] )
334/// ```
335#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
336#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
337#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
338pub struct RotatexFunction {
339	#[atom(CssAtomSet::Rotatex)]
340	pub name: T![Function],
341	pub params: AngleOrZero,
342	pub close: T![')'],
343}
344
345/// <https://drafts.csswg.org/css-transforms-2/#funcdef-rotatey>
346///
347/// ```text,ignore
348/// rotateY() = rotateY( [ <angle> | <zero> ] )
349/// ```
350#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
351#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
352#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
353pub struct RotateyFunction {
354	#[atom(CssAtomSet::Rotatey)]
355	pub name: T![Function],
356	pub params: AngleOrZero,
357	pub close: T![')'],
358}
359
360/// <https://drafts.csswg.org/css-transforms-2/#funcdef-rotatez>
361///
362/// ```text,ignore
363/// rotateZ() = rotateZ( [ <angle> | <zero> ] )
364/// ```
365#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
366#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
367#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
368pub struct RotatezFunction {
369	#[atom(CssAtomSet::Rotatez)]
370	pub name: T![Function],
371	pub params: AngleOrZero,
372	pub close: T![')'],
373}
374
375/// <https://drafts.csswg.org/css-transforms-1/#funcdef-transform-skew>
376///
377/// ```text,ignore
378/// skew() = skew( [ <angle> | <zero> ] , [ <angle> | <zero> ]? )
379/// ```
380#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
381#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
382#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
383pub struct SkewFunction {
384	#[atom(CssAtomSet::Skew)]
385	pub name: T![Function],
386	pub params: (AngleOrZero, Option<T![,]>, Option<AngleOrZero>),
387	pub close: T![')'],
388}
389
390/// <https://drafts.csswg.org/css-transforms-1/#funcdef-transform-skewx>
391///
392/// ```text,ignore
393/// skewX() = skewX( [ <angle> | <zero> ] )
394/// ```
395#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
396#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
397#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
398pub struct SkewxFunction {
399	#[atom(CssAtomSet::Skewx)]
400	pub name: T![Function],
401	pub params: AngleOrZero,
402	pub close: T![')'],
403}
404
405/// <https://drafts.csswg.org/css-transforms-1/#funcdef-transform-skewy>
406///
407/// ```text,ignore
408/// skewY() = skewY( [ <angle> | <zero> ] )
409/// ```
410#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
411#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
412#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
413pub struct SkewyFunction {
414	#[atom(CssAtomSet::Skewy)]
415	pub name: T![Function],
416	pub params: AngleOrZero,
417	pub close: T![')'],
418}
419
420/// <https://drafts.csswg.org/css-transforms-2/#funcdef-perspective>
421///
422/// ```text,ignore
423/// perspective() = perspective( [ <length [0,∞]> | none ] )
424/// ```
425#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
426#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
427#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
428pub struct PerspectiveFunction {
429	#[atom(CssAtomSet::Perspective)]
430	pub name: T![Function],
431	pub params: NoneOr<Length>,
432	pub close: T![')'],
433}
434
435#[cfg(test)]
436mod tests {
437	use super::*;
438	use crate::CssAtomSet;
439	use css_parse::{assert_parse, assert_parse_error, assert_parse_span};
440
441	#[test]
442	fn size_test() {
443		assert_eq!(std::mem::size_of::<TransformFunction>(), 456);
444	}
445
446	#[test]
447	fn test_writes() {
448		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "matrix(1,2,3,4,5,6)");
449		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "matrix(1 2 3 4 5 6)");
450		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "matrix(0,0,0,0,0,0)");
451		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "matrix(-1,-2,-3,-4,-5,-6)");
452		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "matrix(1.5,2.5,3.5,4.5,5.5,6.5)");
453
454		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "translate(10px)");
455		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "translate(10px,20px)");
456		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "translate(45%)");
457		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "translate(2rem)");
458		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "translateX(1rem)");
459		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "translateY(1rem)");
460
461		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "scale(1,2)");
462		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "scale(0,0)");
463		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "scale(1)");
464		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "scale(1.5,2.5)");
465		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "scaleX(2)");
466		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "scaleY(2)");
467
468		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "rotate(45deg)");
469		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "rotate(0)");
470		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "rotate(2turn)");
471		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "rotate(20rad)");
472
473		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "skew(1deg,2deg)");
474		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "skew(0,0)");
475		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "skew(1deg)");
476		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "skewX(1deg)");
477		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "skewX(0)");
478		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "skewY(1deg)");
479		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "skewY(0)");
480
481		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "scale3d(10%,10%,10%)");
482		assert_parse!(CssAtomSet::ATOMS, TransformFunction, "rotate3d(1,2,3,10deg)");
483	}
484
485	#[test]
486	fn test_span() {
487		assert_parse_span!(
488			CssAtomSet::ATOMS,
489			TransformFunction,
490			r#"
491				matrix(1,2,3,4,5,6) translate(0)
492				^^^^^^^^^^^^^^^^^^^
493		"#
494		);
495		assert_parse_span!(
496			CssAtomSet::ATOMS,
497			TransformFunction,
498			r#"
499				translate(0) foo
500				^^^^^^^^^^^^
501		"#
502		);
503		assert_parse_span!(
504			CssAtomSet::ATOMS,
505			TranslateFunction,
506			r#"
507				translate(0) bar
508				^^^^^^^^^^^^
509		"#
510		);
511	}
512
513	#[test]
514	fn test_errors() {
515		assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "matrix()");
516		assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "matrix(1)");
517		assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "matrix(1,2)");
518		assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "matrix(one,two,three,four,five,size)");
519
520		assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "translate()");
521		assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "translate(foo)");
522		assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "translateX()");
523		assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "translateX(foo)");
524		assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "translateY()");
525		assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "translateY(foo)");
526
527		assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "scale()");
528		assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "scale(foo)");
529		assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "scaleX()");
530		assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "scaleX(foo)");
531		assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "scaleY()");
532		assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "scaleY(foo)");
533
534		assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "rotate()");
535		assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "rotate(45px)");
536		assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "rotate(all the way around)");
537
538		assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "skew()");
539		assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "skew(foo)");
540		assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "skewX()");
541		assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "skewX(foo)");
542		assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "skewY()");
543		assert_parse_error!(CssAtomSet::ATOMS, TransformFunction, "skewY(foo)");
544	}
545}