tailwind_css_fixes/modules/borders/divide/divide_width/
mod.rs

1use crate::NumericValue;
2
3use super::*;
4
5#[doc=include_str!("readme.md")]
6#[derive(Clone, Debug)]
7pub struct TailwindDivideWidth {
8    axis: AxisXY, // true for X, false for Y
9    kind: NumericValue,
10}
11
12impl Display for TailwindDivideWidth {
13    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
14        // Handle the default case (e.g., "divide-x") vs. explicit width ("divide-x-2")
15        self.axis.write_xy(f, "divide", &self.kind)
16    }
17}
18
19impl TailwindInstance for TailwindDivideWidth {
20    fn inlineable(&self) -> bool {
21        // This utility generates a nested rule (:where(& > :not(:last-child))) and cannot be inlined.
22        false
23    }
24
25    fn attributes(&self, _: &TailwindBuilder) -> CssAttributes {
26        let width = self.kind.get_properties(|f| format!("{}px", f));
27        
28        let inner_attrs = match self.axis {
29            AxisXY::X => {
30                let var_name = "--tw-divide-x-reverse";
31                css_attributes! {
32                    var_name => "0",
33                    "border-inline-style" => "var(--tw-border-style)",
34                    "border-inline-start-width" => format!("calc({} * var({}))", width, var_name),
35                    "border-inline-end-width" => format!("calc({} * calc(1 - var({})))", width, var_name)
36                }
37            },
38            AxisXY::Y => {
39                let var_name = "--tw-divide-y-reverse";
40                css_attributes! {
41                    var_name => "0",
42                    "border-top-style" => "var(--tw-border-style)",
43                    "border-bottom-style" => "var(--tw-border-style)",
44                    "border-top-width" => format!("calc({} * var({}))", width, var_name),
45                    "border-bottom-width" => format!("calc({} * calc(1 - var({})))", width, var_name)
46                }
47            },
48            AxisXY::N => unreachable!(),
49        };
50
51        // Create the top-level object to hold the nested rule
52        let mut top_level_attrs = CssAttributes::default();
53        let selector = ":where(& > :not(:last-child))".to_string();
54        top_level_attrs.insert_nested(selector, inner_attrs);
55
56        top_level_attrs
57    }
58}
59
60
61impl TailwindDivideWidth {
62    /// Parses divide-width utilities like `divide-x`, `divide-y-2`, `divide-x-[3rem]`.
63    /// https://tailwindcss.com/docs/divide-width
64    pub fn parse(width_pattern: &[&str], arbitrary: &TailwindArbitrary, axis_is_x: bool) -> Result<Self> {
65        // If the width pattern and arbitrary value are empty, it's a default width.
66        if width_pattern.is_empty() && arbitrary.is_none() {
67            Ok(Self {
68                axis: AxisXY::from(axis_is_x),
69                // Default width is 1px.
70                kind: NumericValue::Number { n: 1.0, negative: false, can_be_negative: false },
71            })
72        } else {
73            // Otherwise, parse the explicit width.
74            //  - checker for keywords is false bc there no keywords for divide-width
75            let kind = NumericValue::positive_parser("divide-width", |_| false)(width_pattern, arbitrary)?;
76            Ok(Self { axis: AxisXY::from(axis_is_x), kind })
77        }
78    
79    }
80}