polished_css/style/
mod.rs1use crate::{
4 property::Property,
5 selector::{pseudo::PseudoSelector, Selector, SelectorDisplay},
6};
7
8pub type Content = String;
9pub type Declarations = Vec<String>;
10
11#[derive(Clone, Debug, Default, PartialEq, typed_builder::TypedBuilder)]
12pub struct Style {
13 #[builder(default, setter(into))]
14 pub selector: Selector,
15 #[builder(default, setter(transform = |list: &[&impl Property]| properties_to_declarations(list)))]
16 pub declarations: Declarations,
17 #[builder(default, setter(strip_option))]
18 pub pseudo: Option<PseudoSelector>,
19 }
22
23fn properties_to_declarations(properties: &[&impl Property]) -> Declarations {
24 properties
25 .iter()
26 .map(|property| property.declaration())
27 .collect()
28}
29
30impl Style {
31 #[must_use]
32 pub fn content(&self) -> Content {
33 let declarations = self.declarations.join(";");
34
35 if self.selector.is_inlined() {
36 declarations
37 } else {
38 let selector = self.selector.as_styles_content();
39 format!("{selector}{{{declarations}}}")
40 }
41 }
42}
43
44#[cfg(test)]
45mod test {
46 #[test]
47 fn builder() {
48 use crate::{
49 data_type::{AlphaStorage, PercentageStorage},
50 selector::{Class, Element, Id},
51 };
52 assert_eq!(
53 super::Style::builder()
54 .declarations(&[&crate::property::Opacity::invisible()])
55 .build()
56 .content(),
57 String::from("opacity:0")
58 );
59
60 assert_eq!(
61 super::Style::builder()
62 .selector(Id::from("test"))
63 .declarations(&[&crate::property::Opacity::visible()])
64 .build()
65 .content(),
66 String::from("#test{opacity:1}")
67 );
68
69 assert_eq!(
70 super::Style::builder()
71 .selector(Element::Main)
72 .declarations(&[&crate::property::Opacity::invisible()])
73 .build()
74 .content(),
75 String::from("main{opacity:0}")
76 );
77
78 assert_eq!(
79 super::Style::builder()
80 .selector(Class::from("my-example-class"))
81 .declarations(&[&crate::property::Opacity::percentage(100.0)])
82 .build()
83 .content(),
84 String::from(".my-example-class{opacity:100%}")
85 );
86 }
87}