tailwind_css_fixes/modules/effects/mask/mask_image/
mod.rs1use super::*;
2
3#[derive(Clone, Debug)]
7pub struct TailwindMaskImage {
8 kind: MaskImageKind,
10 value: Option<UnitValue>,
12 is_negative: bool,
14}
15
16#[derive(Clone, Debug, PartialEq)]
17enum MaskImageKind {
18 None,
19 Linear,
20 Radial,
21 Conic,
22 }
24
25impl Display for TailwindMaskImage {
26 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
27 if self.is_negative {
28 write!(f, "-")?;
29 }
30
31 match (&self.kind, &self.value) {
32 (MaskImageKind::None, _) => write!(f, "mask-none"),
33 (MaskImageKind::Linear, Some(val)) => write!(f, "mask-linear-{}", val),
34 (MaskImageKind::Radial, Some(val)) => write!(f, "mask-radial-{}", val),
35 (MaskImageKind::Conic, Some(val)) => write!(f, "mask-conic-{}", val),
36 (MaskImageKind::Linear, None) => write!(f, "mask-linear"),
37 (MaskImageKind::Radial, None) => write!(f, "mask-radial"),
38 (MaskImageKind::Conic, None) => write!(f, "mask-conic"),
39 _ => Ok(()),
40 }
41 }
42}
43
44impl TailwindInstance for TailwindMaskImage {
45 fn attributes(&self, _: &TailwindBuilder) -> CssAttributes {
46 let (prefix, property) = ("--tw-mask", "mask-image");
47
48 match &self.kind {
49 MaskImageKind::None => css_attributes! { property => "none" },
50 MaskImageKind::Linear | MaskImageKind::Radial | MaskImageKind::Conic => {
51 let gradient_type = match self.kind {
52 MaskImageKind::Linear => "linear-gradient",
53 MaskImageKind::Radial => "radial-gradient",
54 MaskImageKind::Conic => "conic-gradient",
55 _ => unreachable!(),
56 };
57
58 let direction_or_angle = match self.value.as_ref() {
59 None => "".to_string(), Some(UnitValue::Keyword(k)) if k.starts_with("to-") => {
61 k.replace("to-", "to ").replace("-", " ")
64 }
65 Some(value) => {
66 let inner_value = match value {
67 UnitValue::Arbitrary(a) => a.get_properties(),
68 _ => value.to_string(),
69 };
70 if self.is_negative {
71 format!("calc({} * -1)", inner_value)
72 } else {
73 inner_value
74 }
75 }
76 };
77
78 let image = format!("{}({})", gradient_type, format!("{}, var({}-stops))", direction_or_angle, prefix));
80
81 css_attributes! {
82 format!("{}-position", prefix) => direction_or_angle,
83 property => image
84 }
85 }
86 }
87 }
88}
89
90impl TailwindMaskImage {
91 pub fn parse(pattern: &[&str], arbitrary: &TailwindArbitrary, neg: Negative) -> Result<Self> {
93 let (kind, rest) = match pattern {
94 ["none"] => (MaskImageKind::None, &pattern[1..]),
95 ["linear", rest @ ..] => (MaskImageKind::Linear, rest),
96 ["radial", rest @ ..] => (MaskImageKind::Radial, rest),
97 ["conic", rest @ ..] => (MaskImageKind::Conic, rest),
98 [] if arbitrary.as_str().contains("gradient") => {
100 (MaskImageKind::Linear, pattern)
102 }
103 _ => return syntax_error!("Unknown mask-image pattern: {}", pattern.join("-")),
104 };
105
106 let value = match kind {
107 MaskImageKind::None => None,
108 _ => { if arbitrary.is_some() {
110 let grad_content = arbitrary.as_str()
112 .replace('_', " ")
113 .trim_start_matches("linear-gradient(")
114 .trim_start_matches("radial-gradient(")
115 .trim_start_matches("conic-gradient(")
116 .trim_end_matches(')')
117 .to_string();
118 Some(UnitValue::Keyword(grad_content))
119 } else if rest.is_empty() {
120 None } else {
122 Some(UnitValue::negative_parser("mask-image", |_| false, false, false, false)(rest, arbitrary, neg)?)
123 }
124 }
125 };
126
127 Ok(Self { kind, value, is_negative: neg.0 })
128 }
129}