Skip to main content

css_ast/functions/
ray_function.rs

1use super::prelude::*;
2use crate::{AtPosition, CalcableValue};
3
4/// <https://drafts.csswg.org/motion-1/#funcdef-ray>
5///
6/// ```text,ignore
7/// ray() = ray( <angle> && <ray-size>? && contain? && [at <position>]? )
8/// ```
9#[node]
10#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
11#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
12#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
13#[derive(csskit_derives::NodeWithMetadata)]
14pub struct RayFunction<'a> {
15	#[atom(CssAtomSet::Ray)]
16	pub name: T![Function],
17	pub params: RayFunctionParams<'a>,
18	#[semantic_eq(skip)]
19	pub close: T![')'],
20}
21
22/// The arguments of [`RayFunction`], which may appear in any order.
23///
24/// ```text,ignore
25/// <angle> && <ray-size>? && contain? && [at <position>]?
26/// ```
27#[node]
28#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
29#[parse(all_must_occur)]
30#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
31#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
32#[derive(csskit_derives::NodeWithMetadata)]
33pub struct RayFunctionParams<'a> {
34	pub angle: CalcableValue<'a, Angle>,
35	pub size: Option<RaySize>,
36	#[atom(CssAtomSet::Contain)]
37	pub contain: Option<T![Ident]>,
38	pub at: Option<AtPosition<'a>>,
39}
40
41/// <https://drafts.csswg.org/motion-1/#typedef-ray-size>
42///
43/// ```text,ignore
44/// <ray-size> = closest-side | closest-corner | farthest-side | farthest-corner | sides
45/// ```
46#[node]
47#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
48#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
49#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(skip))]
50#[derive(csskit_derives::NodeWithMetadata)]
51pub enum RaySize {
52	#[atom(CssAtomSet::ClosestSide)]
53	ClosestSide(T![Ident]),
54	#[atom(CssAtomSet::ClosestCorner)]
55	ClosestCorner(T![Ident]),
56	#[atom(CssAtomSet::FarthestSide)]
57	FarthestSide(T![Ident]),
58	#[atom(CssAtomSet::FarthestCorner)]
59	FarthestCorner(T![Ident]),
60	#[atom(CssAtomSet::Sides)]
61	Sides(T![Ident]),
62}
63
64#[cfg(test)]
65mod tests {
66	use super::*;
67	use crate::CssAtomSet;
68	use css_parse::{assert_parse, assert_parse_error, assert_peek_false};
69
70	#[test]
71	fn test_parses() {
72		assert_parse!(CssAtomSet::ATOMS, RayFunction, "ray(45deg)");
73		assert_parse!(CssAtomSet::ATOMS, RayFunction, "ray(45deg closest-side)");
74		assert_parse!(CssAtomSet::ATOMS, RayFunction, "ray(contain 45deg)");
75		assert_parse!(CssAtomSet::ATOMS, RayFunction, "ray(45deg sides contain)");
76		assert_parse!(CssAtomSet::ATOMS, RayFunction, "ray(farthest-corner 45deg contain at center)");
77		assert_parse!(CssAtomSet::ATOMS, RayFunction, "ray(at 50% 50% 0.25turn)");
78		assert_parse!(CssAtomSet::ATOMS, RayFunction, "ray(calc(45deg + 1rad))");
79		assert_parse!(CssAtomSet::ATOMS, RayFunction, "ray(var(--angle))");
80	}
81
82	#[test]
83	fn test_errors() {
84		assert_peek_false!(CssAtomSet::ATOMS, RayFunction, "circle(45deg)");
85		assert_parse_error!(CssAtomSet::ATOMS, RayFunction, "ray()");
86		assert_parse_error!(CssAtomSet::ATOMS, RayFunction, "ray(contain)");
87		assert_parse_error!(CssAtomSet::ATOMS, RayFunction, "ray(45deg 45deg)");
88		assert_parse_error!(CssAtomSet::ATOMS, RayFunction, "ray(45deg sides sides)");
89	}
90}