tailwind_css_fixes/modules/background/image/
mod.rs1use super::*;
2
3#[doc=include_str!("readme.md")]
4#[derive(Clone, Debug)]
5pub struct TailwindBackgroundImage {
6 kind: BgImageKind,
8 value: Option<UnitValue>,
10 is_negative: bool,
12}
13
14#[derive(Clone, Debug, PartialEq)]
15enum BgImageKind {
16 None,
17 Url,
18 Linear,
19 Radial,
20 Conic,
21 RepeatingLinear,
22 RepeatingRadial,
23 RepeatingConic,
24}
25
26impl Display for TailwindBackgroundImage {
27 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
28 if self.is_negative {
29 write!(f, "-")?;
30 }
31
32 match (&self.kind, &self.value) {
33 (BgImageKind::None, _) => write!(f, "bg-none"),
34 (BgImageKind::Url, Some(val)) => write!(f, "bg-[url({})]", val),
35 (BgImageKind::Linear, Some(val)) => write!(f, "bg-linear-{}", val),
36 (BgImageKind::Radial, Some(val)) => write!(f, "bg-radial-{}", val),
37 (BgImageKind::Conic, Some(val)) => write!(f, "bg-conic-{}", val),
38 (BgImageKind::Linear, None) => write!(f, "bg-linear"),
39 (BgImageKind::Radial, None) => write!(f, "bg-radial"),
40 (BgImageKind::Conic, None) => write!(f, "bg-conic"),
41 (BgImageKind::RepeatingLinear, Some(val)) => write!(f, "bg-[repeating-linear-gradient({})]", val),
42 (BgImageKind::RepeatingRadial, Some(val)) => write!(f, "bg-[repeating-radial-gradient({})]", val),
43 (BgImageKind::RepeatingConic, Some(val)) => write!(f, "bg-[repeating-conic-gradient({})]", val),
44 _ => Ok(()), }
46 }
47}
48
49impl TailwindInstance for TailwindBackgroundImage {
50 fn attributes(&self, _: &TailwindBuilder) -> CssAttributes {
51 match &self.kind {
52 BgImageKind::None => css_attributes! { "background-image" => "none" },
53 BgImageKind::Url => {
54 let url_value = self.value.as_ref().unwrap().to_string();
55 css_attributes! { "background-image" => format!("url({})", url_value) }
56 }
57 BgImageKind::RepeatingLinear | BgImageKind::RepeatingRadial | BgImageKind::RepeatingConic => {
58 let arbitrary_gradient_val = self.value.as_ref().unwrap().to_string().replace('_', " ");
59
60 let gradient_type = match self.kind {
61 BgImageKind::RepeatingLinear => "repeating-linear-gradient",
62 BgImageKind::RepeatingRadial => "repeating-radial-gradient",
63 BgImageKind::RepeatingConic => "repeating-conic-gradient",
64 _ => unreachable!(),
65 };
66 css_attributes! { "background-image" => format!("{}({})", gradient_type, arbitrary_gradient_val) }
67 }
68 BgImageKind::Linear | BgImageKind::Radial | BgImageKind::Conic => {
69 let gradient_type = match self.kind {
70 BgImageKind::Linear => "linear-gradient",
71 BgImageKind::Radial => "radial-gradient",
72 BgImageKind::Conic => "conic-gradient",
73 _ => unreachable!(),
74 };
75
76 let direction_or_angle = match self.value.as_ref() {
77 None => "in oklab".to_string(),
79 Some(UnitValue::Keyword(k)) if k.starts_with("to-") => {
81 let direction = k.strip_prefix("to-").unwrap_or(k);
82 let mut full_direction = String::new();
83 if direction.contains('t') { full_direction.push_str("top "); }
84 if direction.contains('b') { full_direction.push_str("bottom "); }
85 if direction.contains('l') { full_direction.push_str("left "); }
86 if direction.contains('r') { full_direction.push_str("right "); }
87 format!("to {} in oklab", full_direction.trim())
88 }
89 Some(value) => {
91 let inner_value = match value {
93 UnitValue::Arbitrary(a) => a.get_properties(),
94 _ => value.to_string()
95 };
96
97 if self.is_negative {
98 format!("calc({} * -1)", inner_value)
99 } else {
100 format!("{} in oklab", inner_value)
101 }
102 }
103 };
104
105 let image = match self.value.as_ref() {
107 Some(UnitValue::Arbitrary(_)) | Some(UnitValue::Number {..}) | Some(UnitValue::Length(_)) => {
108 format!("{}(var(--tw-gradient-stops, {}))", gradient_type, direction_or_angle)
109 },
110 _ => format!("{}(var(--tw-gradient-stops))", gradient_type)
111 };
112
113 css_attributes! {
114 "--tw-gradient-position" => direction_or_angle,
115 "background-image" => image
116 }
117 }
118 }
119 }
120}
121
122impl TailwindBackgroundImage {
123 pub fn parse(pattern: &[&str], arbitrary: &TailwindArbitrary, neg: Negative) -> Result<Self> {
125 let (kind, rest) = match pattern {
126 ["none"] => (BgImageKind::None, &pattern[1..]),
127 ["gradient", rest @ ..] | ["linear", rest @ ..] => (BgImageKind::Linear, rest),
128 ["radial", rest @ ..] => (BgImageKind::Radial, rest),
129 ["conic", rest @ ..] => (BgImageKind::Conic, rest),
130 [] if arbitrary.as_str().starts_with("url(") => (BgImageKind::Url, pattern),
131 [] if arbitrary.as_str().starts_with("repeating-linear-gradient(") => (BgImageKind::RepeatingLinear, pattern),
132 [] if arbitrary.as_str().starts_with("repeating-radial-gradient(") => (BgImageKind::RepeatingRadial, pattern),
133 [] if arbitrary.as_str().starts_with("repeating-conic-gradient(") => (BgImageKind::RepeatingConic, pattern),
134 _ => return syntax_error!("Unknown background-image pattern: {}", pattern.join("-")),
135 };
136
137 let value = match kind {
138 BgImageKind::None => None,
139 BgImageKind::Url => {
140 let url = arbitrary.as_str().strip_prefix("url(").and_then(|s| s.strip_suffix(')')).unwrap_or("");
141 Some(UnitValue::Keyword(url.to_string()))
142 }
143 BgImageKind::RepeatingLinear | BgImageKind::RepeatingRadial | BgImageKind::RepeatingConic => {
144 let prefix = match kind {
145 BgImageKind::RepeatingLinear => "repeating-linear-gradient(",
146 BgImageKind::RepeatingRadial => "repeating-radial-gradient(",
147 BgImageKind::RepeatingConic => "repeating-conic-gradient(",
148 _ => unreachable!(),
149 };
150 let content = arbitrary.as_str().strip_prefix(prefix).and_then(|s| s.strip_suffix(')')).unwrap_or("");
151 Some(UnitValue::Keyword(content.to_string()))
152 }
153 BgImageKind::Linear
154 | BgImageKind::Radial
155 | BgImageKind::Conic => {
156 if rest.is_empty() && arbitrary.is_none() {
157 None
159 } else {
160 let joined = rest.join("-");
161 if joined.starts_with("to-") {
162 Some(UnitValue::Keyword(joined.replace("-b-r", "-br").replace("-b-l", "-bl").replace("-t-r", "-tr").replace("-t-l", "-tl")))
164 } else {
165 Some(UnitValue::negative_parser("bg-image", |_| false, false, false, false)(rest, arbitrary, neg)?)
168 }
169 }
170 }
171 };
172
173 Ok(Self { kind, value, is_negative: neg.0 })
174 }
175}