1use super::shadow::ShadowList;
3
4const LENGTH_UNITS: [&str; 16] = [
5 "cm", "mm", "Q", "in", "pc", "pt", "px", "em", "ex", "ch", "rem", "lh", "vw", "vh", "vmin",
6 "vmax",
7];
8const LINE_WIDTHS: [&str; 3] = ["thin", "medium", "thick"];
9const LINE_STYLES: [&str; 10] = [
10 "solid", "dashed", "dotted", "double", "groove", "ridge", "inset", "outset", "hidden", "none",
11];
12const ANGLES: [&str; 4] = ["deg", "grad", "rad", "turn"];
13const GRADIENT_TYPES: [&str; 5] = [
14 "linear-gradient",
15 "radial-gradient",
16 "repeating-linear-gradient",
17 "repeating-radial-gradient",
18 "conic-gradient",
19];
20const VALID_POSITIONS: [&str; 5] = ["center", "top", "right", "bottom", "left"];
21const ABSOLUTE_SIZES: [&str; 8] = [
22 "xx-small",
23 "x-small",
24 "small",
25 "medium",
26 "large",
27 "x-large",
28 "xx-large",
29 "xxx-large",
30];
31const RELATIVE_SIZES: [&str; 2] = ["larger", "smaller"];
32const NAMED_COLORS: [&str; 150] = [
33 "transparent",
34 "currentColor",
35 "antiquewhite",
36 "aliceblue",
37 "aqua",
38 "aquamarine",
39 "azure",
40 "beige",
41 "bisque",
42 "black",
43 "blanchedalmond",
44 "blue",
45 "blueviolet",
46 "brown",
47 "burlywood",
48 "cadetblue",
49 "chartreuse",
50 "chocolate",
51 "coral",
52 "cornflowerblue",
53 "cornsilk",
54 "crimson",
55 "cyan",
56 "darkblue",
57 "darkcyan",
58 "darkgoldenrod",
59 "darkgray",
60 "darkgreen",
61 "darkgrey",
62 "darkkhaki",
63 "darkmagenta",
64 "darkolivegreen",
65 "darkorange",
66 "darkorchid",
67 "darkred",
68 "darksalmon",
69 "darkseagreen",
70 "darkslateblue",
71 "darkslategray",
72 "darkslategrey",
73 "darkturquoise",
74 "darkviolet",
75 "deeppink",
76 "deepskyblue",
77 "dimgray",
78 "dimgrey",
79 "dodgerblue",
80 "firebrick",
81 "floralwhite",
82 "forestgreen",
83 "fuchsia",
84 "gainsboro",
85 "ghostwhite",
86 "gold",
87 "goldenrod",
88 "gray",
89 "green",
90 "greenyellow",
91 "grey",
92 "honeydew",
93 "hotpink",
94 "indianred",
95 "indigo",
96 "ivory",
97 "khaki",
98 "lavender",
99 "lavenderblush",
100 "lawngreen",
101 "lemonchiffon",
102 "lightblue",
103 "lightcoral",
104 "lightcyan",
105 "lightgoldenrodyellow",
106 "lightgray",
107 "lightgreen",
108 "lightgrey",
109 "lightpink",
110 "lightsalmon",
111 "lightseagreen",
112 "lightskyblue",
113 "lightslategray",
114 "lightslategrey",
115 "lightsteelblue",
116 "lightyellow",
117 "lime",
118 "limegreen",
119 "linen",
120 "magenta",
121 "maroon",
122 "mediumaquamarine",
123 "mediumblue",
124 "mediumorchid",
125 "mediumpurple",
126 "mediumseagreen",
127 "mediumslateblue",
128 "mediumspringgreen",
129 "mediumturquoise",
130 "mediumvioletred",
131 "midnightblue",
132 "mintcream",
133 "mistyrose",
134 "moccasin",
135 "navajowhite",
136 "navy",
137 "oldlace",
138 "olive",
139 "olivedrab",
140 "orange",
141 "orangered",
142 "orchid",
143 "palegoldenrod",
144 "palegreen",
145 "paleturquoise",
146 "palevioletred",
147 "papayawhip",
148 "peachpuff",
149 "peru",
150 "pink",
151 "plum",
152 "powderblue",
153 "purple",
154 "rebeccapurple",
155 "red",
156 "rosybrown",
157 "royalblue",
158 "saddlebrown",
159 "salmon",
160 "sandybrown",
161 "seagreen",
162 "seashell",
163 "sienna",
164 "silver",
165 "skyblue",
166 "slateblue",
167 "slategray",
168 "slategrey",
169 "snow",
170 "springgreen",
171 "steelblue",
172 "tan",
173 "teal",
174 "thistle",
175 "tomato",
176 "turquoise",
177 "violet",
178 "wheat",
179 "white",
180 "whitesmoke",
181 "yellow",
182 "yellowgreen",
183];
184
185fn is_matching_base(value: &str) -> bool {
186 is_matching_var(value)
187 || [
188 "inherit",
189 "initial",
190 "revert",
191 "revert-layer",
192 "unset",
193 "fill",
194 "max-content",
195 "min-content",
196 "fit-content",
197 ]
198 .contains(&value)
199}
200
201pub fn is_matching_all(_value: &str) -> bool {
203 true
204}
205
206pub fn is_matching_url(value: &str) -> bool {
215 value.starts_with("url(")
216}
217
218pub fn is_matching_var(value: &str) -> bool {
227 value.starts_with("var(")
228}
229
230pub fn is_matching_shadow(value: &str) -> bool {
239 ShadowList::parse(value).is_some()
240}
241
242pub fn is_matching_absolute_size(value: &str) -> bool {
251 ABSOLUTE_SIZES.contains(&value)
252}
253
254pub fn is_matching_relative_size(value: &str) -> bool {
263 RELATIVE_SIZES.contains(&value)
264}
265
266pub fn is_matching_line_width(value: &str) -> bool {
275 LINE_WIDTHS.contains(&value)
276}
277
278pub fn is_matching_line_style(value: &str) -> bool {
287 LINE_STYLES.contains(&value)
288}
289
290pub fn is_matching_computational_css_function(value: &str) -> bool {
304 value.starts_with("min(")
305 || value.starts_with("max(")
306 || value.starts_with("clamp(")
307 || value.starts_with("calc(")
308}
309
310pub fn is_matching_color(value: &str) -> bool {
320 (value.starts_with('#') && (value.len() == 4 || value.len() == 7))
321 || ["rgb(", "rgba(", "hsl(", "hsla(", "hwb(", "lch(", "lab("]
322 .iter()
323 .any(|e| value.starts_with(e))
324 || NAMED_COLORS.iter().any(|c| &value == c)
325 || is_matching_base(value)
326}
327
328pub fn is_matching_length(value: &str) -> bool {
337 value.split(' ').all(|v| {
338 v == "0"
339 || LENGTH_UNITS.iter().any(|u| v.ends_with(u))
340 || is_matching_computational_css_function(value)
341 }) || is_matching_base(value)
342}
343
344pub fn is_matching_number(value: &str) -> bool {
353 value.parse::<f32>().is_ok()
354 || is_matching_computational_css_function(value)
355 || is_matching_base(value)
356}
357
358pub fn is_matching_percentage(value: &str) -> bool {
367 value.ends_with('%') || is_matching_computational_css_function(value) || is_matching_base(value)
368}
369
370pub fn is_matching_time(value: &str) -> bool {
380 value.ends_with('s')
381 || value.ends_with("ms")
382 || is_matching_computational_css_function(value)
383 || is_matching_base(value)
384}
385
386pub fn is_matching_gradient(value: &str) -> bool {
395 GRADIENT_TYPES.iter().any(|t| value.starts_with(t)) || is_matching_base(value)
396}
397
398pub fn is_matching_position(value: &str) -> bool {
409 value
410 .split(' ')
411 .all(|v| VALID_POSITIONS.contains(&v) || is_matching_length(v) || is_matching_percentage(v))
412 || is_matching_base(value)
413}
414
415pub fn is_matching_angle(value: &str) -> bool {
424 ANGLES.iter().any(|a| value.ends_with(a))
425 || is_matching_computational_css_function(value)
426 || is_matching_base(value)
427}
428
429pub fn is_matching_image(value: &str) -> bool {
438 is_matching_url(value)
439 || is_matching_gradient(value)
440 || ["element(", "image(", "cross-fade(", "image-set("]
441 .iter()
442 .any(|e| value.starts_with(e))
443 || is_matching_base(value)
444}
445
446#[cfg(test)]
447mod tests {
448 use super::*;
449
450 #[test]
451 fn is_matching_color_test() {
452 assert!(is_matching_color("blue"));
453 assert!(is_matching_color("#333"));
454 assert!(is_matching_color("#121212"));
455 assert!(is_matching_color("rgb(12.12,12,12)"));
456 assert!(is_matching_color("rgb(12 12 12)"));
457 assert!(is_matching_color("rgb(12 12 12/0.1)"));
458 assert!(is_matching_color("rgb(12 12 12 / 0.1)"));
459 assert!(is_matching_color("rgb(var(--blue),12,12)"));
460 assert!(is_matching_color("rgb(12 12 12 / var(--opacity))"));
461 assert!(is_matching_color("rgba(12,12,12,0.12)"));
462 assert!(is_matching_color("hsl(360,100%,50%)"));
463 assert!(is_matching_color("hsl(3.14rad,100%,50%)"));
464 assert!(is_matching_color("hsl(3.14rad 100% 50%/0.42)"));
465 assert!(is_matching_color("hsl(var(--hue) 12% 42%/var(--opacity))"));
466 assert!(is_matching_color("hsla(360,100%,50%,0.12)"));
467 }
468
469 #[test]
470 fn is_matching_length_test() {
471 assert!(is_matching_length("300px"));
472 assert!(!is_matching_length("50%"));
473 assert!(is_matching_length("30vw"));
474 assert!(is_matching_length("min(10%,10px)"));
475 assert!(is_matching_length("0"));
476 }
477
478 #[test]
479 fn is_matching_shadow_with_functions_test() {
480 assert!(is_matching_shadow("10px 10px min(1px,2px) 10px rgb(1,1,1)"));
481 assert!(is_matching_shadow("inset 0 -3em 3em rgba(0,0,0,0.1),0 0 0 2px rgb(255,255,255),0.3em 0.3em 1em rgba(0,0,0,0.3)"));
482 assert!(is_matching_shadow(
483 "var(--a, 0 0 1px rgb(0, 0, 0)), 0 0 1px rgb(0, 0, 0)"
484 ));
485 }
486}