Skip to main content

azul_css/props/style/
lists.rs

1//! CSS list styling properties (`list-style-type` and `list-style-position`)
2
3use alloc::string::{String, ToString};
4use core::fmt;
5use crate::corety::AzString;
6
7use crate::{codegen::format::FormatAsRustCode, props::formatter::PrintAsCssValue};
8
9// --- list-style-type ---
10
11/// CSS `list-style-type` property — controls the marker style for list items.
12#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
13#[repr(C)]
14#[derive(Default)]
15pub enum StyleListStyleType {
16    None,
17    #[default]
18    Disc,
19    Circle,
20    Square,
21    Decimal,
22    DecimalLeadingZero,
23    LowerRoman,
24    UpperRoman,
25    LowerGreek,
26    UpperGreek,
27    LowerAlpha,
28    UpperAlpha,
29}
30
31
32impl PrintAsCssValue for StyleListStyleType {
33    fn print_as_css_value(&self) -> String {
34        use StyleListStyleType::{None, Disc, Circle, Square, Decimal, DecimalLeadingZero, LowerRoman, UpperRoman, LowerGreek, UpperGreek, LowerAlpha, UpperAlpha};
35        String::from(match self {
36            None => "none",
37            Disc => "disc",
38            Circle => "circle",
39            Square => "square",
40            Decimal => "decimal",
41            DecimalLeadingZero => "decimal-leading-zero",
42            LowerRoman => "lower-roman",
43            UpperRoman => "upper-roman",
44            LowerGreek => "lower-greek",
45            UpperGreek => "upper-greek",
46            LowerAlpha => "lower-alpha",
47            UpperAlpha => "upper-alpha",
48        })
49    }
50}
51
52impl FormatAsRustCode for StyleListStyleType {
53    fn format_as_rust_code(&self, _tabs: usize) -> String {
54        use StyleListStyleType::{None, Disc, Circle, Square, Decimal, DecimalLeadingZero, LowerRoman, UpperRoman, LowerGreek, UpperGreek, LowerAlpha, UpperAlpha};
55        format!(
56            "StyleListStyleType::{}",
57            match self {
58                None => "None",
59                Disc => "Disc",
60                Circle => "Circle",
61                Square => "Square",
62                Decimal => "Decimal",
63                DecimalLeadingZero => "DecimalLeadingZero",
64                LowerRoman => "LowerRoman",
65                UpperRoman => "UpperRoman",
66                LowerGreek => "LowerGreek",
67                UpperGreek => "UpperGreek",
68                LowerAlpha => "LowerAlpha",
69                UpperAlpha => "UpperAlpha",
70            }
71        )
72    }
73}
74
75impl fmt::Display for StyleListStyleType {
76    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77        write!(f, "{}", self.print_as_css_value())
78    }
79}
80
81// --- list-style-position ---
82
83/// CSS `list-style-position` property — controls whether the marker is inside or outside the list item box.
84#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
85#[repr(C)]
86#[derive(Default)]
87pub enum StyleListStylePosition {
88    Inside,
89    #[default]
90    Outside,
91}
92
93
94impl PrintAsCssValue for StyleListStylePosition {
95    fn print_as_css_value(&self) -> String {
96        use StyleListStylePosition::{Inside, Outside};
97        String::from(match self {
98            Inside => "inside",
99            Outside => "outside",
100        })
101    }
102}
103
104impl FormatAsRustCode for StyleListStylePosition {
105    fn format_as_rust_code(&self, _tabs: usize) -> String {
106        use StyleListStylePosition::{Inside, Outside};
107        format!(
108            "StyleListStylePosition::{}",
109            match self {
110                Inside => "Inside",
111                Outside => "Outside",
112            }
113        )
114    }
115}
116
117impl fmt::Display for StyleListStylePosition {
118    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119        write!(f, "{}", self.print_as_css_value())
120    }
121}
122
123// --- Parsing Logic ---
124
125#[cfg(feature = "parser")]
126#[derive(Clone, PartialEq, Eq)]
127pub enum StyleListStyleTypeParseError<'a> {
128    InvalidValue(&'a str),
129}
130
131#[cfg(feature = "parser")]
132impl_debug_as_display!(StyleListStyleTypeParseError<'a>);
133
134#[cfg(feature = "parser")]
135impl_display! { StyleListStyleTypeParseError<'a>, {
136    InvalidValue(val) => format!("Invalid list-style-type value: \"{}\"", val),
137}}
138
139#[cfg(feature = "parser")]
140#[derive(Debug, Clone, PartialEq, Eq)]
141#[repr(C, u8)]
142pub enum StyleListStyleTypeParseErrorOwned {
143    InvalidValue(AzString),
144}
145
146#[cfg(feature = "parser")]
147impl StyleListStyleTypeParseError<'_> {
148    #[must_use] pub fn to_contained(&self) -> StyleListStyleTypeParseErrorOwned {
149        match self {
150            Self::InvalidValue(s) => StyleListStyleTypeParseErrorOwned::InvalidValue((*s).to_string().into()),
151        }
152    }
153}
154
155#[cfg(feature = "parser")]
156impl StyleListStyleTypeParseErrorOwned {
157    #[must_use] pub fn to_shared(&self) -> StyleListStyleTypeParseError<'_> {
158        match self {
159            Self::InvalidValue(s) => StyleListStyleTypeParseError::InvalidValue(s.as_str()),
160        }
161    }
162}
163
164/// Parses a CSS `list-style-type` value from a string.
165#[cfg(feature = "parser")]
166/// # Errors
167///
168/// Returns an error if `input` is not a valid CSS `list-style-type` value.
169pub fn parse_style_list_style_type(
170    input: &str,
171) -> Result<StyleListStyleType, StyleListStyleTypeParseError<'_>> {
172    let input = input.trim();
173    match input {
174        "none" => Ok(StyleListStyleType::None),
175        "disc" => Ok(StyleListStyleType::Disc),
176        "circle" => Ok(StyleListStyleType::Circle),
177        "square" => Ok(StyleListStyleType::Square),
178        "decimal" => Ok(StyleListStyleType::Decimal),
179        "decimal-leading-zero" => Ok(StyleListStyleType::DecimalLeadingZero),
180        "lower-roman" => Ok(StyleListStyleType::LowerRoman),
181        "upper-roman" => Ok(StyleListStyleType::UpperRoman),
182        "lower-greek" => Ok(StyleListStyleType::LowerGreek),
183        "upper-greek" => Ok(StyleListStyleType::UpperGreek),
184        "lower-alpha" | "lower-latin" => Ok(StyleListStyleType::LowerAlpha),
185        "upper-alpha" | "upper-latin" => Ok(StyleListStyleType::UpperAlpha),
186        _ => Err(StyleListStyleTypeParseError::InvalidValue(input)),
187    }
188}
189
190#[cfg(feature = "parser")]
191#[derive(Clone, PartialEq, Eq)]
192pub enum StyleListStylePositionParseError<'a> {
193    InvalidValue(&'a str),
194}
195
196#[cfg(feature = "parser")]
197impl_debug_as_display!(StyleListStylePositionParseError<'a>);
198
199#[cfg(feature = "parser")]
200impl_display! { StyleListStylePositionParseError<'a>, {
201    InvalidValue(val) => format!("Invalid list-style-position value: \"{}\"", val),
202}}
203
204#[cfg(feature = "parser")]
205#[derive(Debug, Clone, PartialEq, Eq)]
206#[repr(C, u8)]
207pub enum StyleListStylePositionParseErrorOwned {
208    InvalidValue(AzString),
209}
210
211#[cfg(feature = "parser")]
212impl StyleListStylePositionParseError<'_> {
213    #[must_use] pub fn to_contained(&self) -> StyleListStylePositionParseErrorOwned {
214        match self {
215            Self::InvalidValue(s) => {
216                StyleListStylePositionParseErrorOwned::InvalidValue((*s).to_string().into())
217            }
218        }
219    }
220}
221
222#[cfg(feature = "parser")]
223impl StyleListStylePositionParseErrorOwned {
224    #[must_use] pub fn to_shared(&self) -> StyleListStylePositionParseError<'_> {
225        match self {
226            Self::InvalidValue(s) => StyleListStylePositionParseError::InvalidValue(s.as_str()),
227        }
228    }
229}
230
231/// Parses a CSS `list-style-position` value from a string.
232#[cfg(feature = "parser")]
233/// # Errors
234///
235/// Returns an error if `input` is not a valid CSS `list-style-position` value.
236pub fn parse_style_list_style_position(
237    input: &str,
238) -> Result<StyleListStylePosition, StyleListStylePositionParseError<'_>> {
239    let input = input.trim();
240    match input {
241        "inside" => Ok(StyleListStylePosition::Inside),
242        "outside" => Ok(StyleListStylePosition::Outside),
243        _ => Err(StyleListStylePositionParseError::InvalidValue(input)),
244    }
245}