1use super::prelude::*;
2use crate::{CalcableValue, Color, Length, NonNegative};
3
4type ShadowOffset<'a> = (
7 CalcableValue<'a, Length>,
8 CalcableValue<'a, Length>,
9 Option<CalcableValue<'a, NonNegative<Length>>>,
10 Option<CalcableValue<'a, Length>>,
11);
12#[node]
18#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
19#[parse(all_must_occur)]
20#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
21#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit)]
22#[derive(csskit_derives::NodeWithMetadata)]
23pub struct Shadow<'a> {
24 pub color: Option<Color<'a>>,
25 pub offset: ShadowOffset<'a>,
26 #[atom(CssAtomSet::Inset)]
27 pub inset: Option<T![Ident]>,
28}
29
30#[cfg(test)]
31mod tests {
32 use super::*;
33 use crate::CssAtomSet;
34 use css_parse::{assert_parse, assert_parse_error, assert_peek_false};
35
36 #[test]
37 fn test_writes() {
38 assert_parse!(CssAtomSet::ATOMS, Shadow, "10px 20px");
39 assert_parse!(CssAtomSet::ATOMS, Shadow, "10px 20px 5px");
40 assert_parse!(CssAtomSet::ATOMS, Shadow, "10px 20px 5px 3px");
41 assert_parse!(CssAtomSet::ATOMS, Shadow, "red 10px 20px");
42 assert_parse!(CssAtomSet::ATOMS, Shadow, "#ff0000 10px 20px 5px");
43 assert_parse!(CssAtomSet::ATOMS, Shadow, "rgba(255,0,0,0.5)10px 20px 5px 3px");
44 assert_parse!(CssAtomSet::ATOMS, Shadow, "10px 20px inset");
45 assert_parse!(CssAtomSet::ATOMS, Shadow, "10px 20px 5px inset");
46 assert_parse!(CssAtomSet::ATOMS, Shadow, "10px 20px 5px 3px inset");
47 assert_parse!(CssAtomSet::ATOMS, Shadow, "red 10px 20px inset");
48 assert_parse!(CssAtomSet::ATOMS, Shadow, "blue 10px 20px 5px 3px inset");
49 assert_parse!(CssAtomSet::ATOMS, Shadow, "-10px -20px");
50 assert_parse!(CssAtomSet::ATOMS, Shadow, "red -10px -20px 5px");
51 assert_parse!(CssAtomSet::ATOMS, Shadow, "0 0");
52 assert_parse!(CssAtomSet::ATOMS, Shadow, "0 0 0");
53 assert_parse!(CssAtomSet::ATOMS, Shadow, "0 0 0 0");
54 assert_parse!(CssAtomSet::ATOMS, Shadow, "1em 2em");
55 assert_parse!(CssAtomSet::ATOMS, Shadow, "1rem 2rem 0.5rem");
56 }
57
58 #[test]
59 fn test_substitution_offsets() {
60 assert_parse!(CssAtomSet::ATOMS, Shadow, "calc(1px + 2px) 20px");
61 assert_parse!(CssAtomSet::ATOMS, Shadow, "10px calc(2px * 3)");
62 assert_parse!(CssAtomSet::ATOMS, Shadow, "var(--x) var(--y)");
63 assert_parse!(CssAtomSet::ATOMS, Shadow, "red var(--x) 20px calc(5px) 3px");
64 assert_parse!(CssAtomSet::ATOMS, Shadow, "10px 20px max(1px, 2px) inset");
65 }
66
67 #[test]
68 fn test_inset_leading() {
69 assert_parse!(CssAtomSet::ATOMS, Shadow, "inset 10px 20px");
70 assert_parse!(CssAtomSet::ATOMS, Shadow, "inset 0 1px 1px");
71 assert_parse!(CssAtomSet::ATOMS, Shadow, "inset 0 1px 1px rgba(0,0,0,.075)");
72 assert_parse!(CssAtomSet::ATOMS, Shadow, "inset red 10px 20px");
73 assert_parse!(CssAtomSet::ATOMS, Shadow, "red inset 10px 20px");
74 }
75
76 #[test]
77 fn test_errors() {
78 assert_peek_false!(CssAtomSet::ATOMS, Shadow, "");
79 assert_peek_false!(CssAtomSet::ATOMS, Shadow, "10% 20%");
80 assert_parse_error!(CssAtomSet::ATOMS, Shadow, "10px");
81 assert_parse_error!(CssAtomSet::ATOMS, Shadow, "red");
82 assert_parse_error!(CssAtomSet::ATOMS, Shadow, "inset");
83 assert_parse_error!(CssAtomSet::ATOMS, Shadow, "10px 20px -5px");
84 assert_parse_error!(CssAtomSet::ATOMS, Shadow, "10px 20px 5px 3px 7px");
85 assert_parse_error!(CssAtomSet::ATOMS, Shadow, "10px 20px 5px inset 3px");
86 assert_parse_error!(CssAtomSet::ATOMS, Shadow, "10px 20px 5px 3px inset extra");
87 }
88
89 #[test]
90 #[cfg(feature = "visitable")]
91 fn test_visits() {
92 use crate::assert_visits;
93 assert_visits!("10px 20px", Shadow, Length, Length);
94 assert_visits!("red 10px 20px", Shadow, Color, Length, Length);
95 assert_visits!("10px 20px 5px", Shadow, Length, Length, Length);
96 assert_visits!("blue 10px 20px 5px 3px", Shadow, Color, Length, Length, Length, Length);
97 }
98}