sunbeam_ir/
generate_css_file.rs1use crate::{Classes, RetrievedClassDefinition};
2use std::collections::HashSet;
3
4impl Classes {
5 pub fn to_css_file_contents(&self) -> String {
7 let classes: HashSet<&RetrievedClassDefinition> = self.classes.iter().collect();
8 let mut classes: Vec<&RetrievedClassDefinition> = classes.into_iter().collect();
9 classes.sort_by(|a, b| {
10 let a_hover = a.modifiers.hover();
11 let b_hover = b.modifiers.hover();
12
13 if a_hover || b_hover {
14 return a_hover.cmp(&b_hover);
15 }
16
17 a.css_class_definition.cmp(&b.css_class_definition)
18 });
19
20 let mut class_file_contents = "".to_string();
21
22 for class in classes {
23 class_file_contents += &class.css_class_definition;
24 class_file_contents += "\n";
25 }
26
27 class_file_contents.trim().to_string()
28 }
29}
30
31#[cfg(test)]
32mod tests {
33 use super::*;
34 use crate::{Modifiers, RetrievedClassDefinition};
35
36 #[test]
38 fn write_css_sorted() {
39 let classes = Classes {
40 classes: vec![
41 RetrievedClassDefinition::new(
42 "mb10".to_string(),
43 r#".mb10 {
44 margin-bottom: 10px;
45}"#
46 .to_string(),
47 Modifiers::default(),
48 ),
49 RetrievedClassDefinition::new(
50 "mt5".to_string(),
51 r#".mt5 {
52 margin-top: 5px;
53}"#
54 .to_string(),
55 Modifiers::default(),
56 ),
57 RetrievedClassDefinition::new(
58 "mb2".to_string(),
59 r#".mb2 {
60 margin-bottom: 2px;
61}"#
62 .to_string(),
63 Modifiers::default(),
64 ),
65 ],
66 };
67
68 let contents = classes.to_css_file_contents();
69
70 assert_eq!(
71 contents,
72 r#"
73.mb10 {
74 margin-bottom: 10px;
75}
76.mb2 {
77 margin-bottom: 2px;
78}
79.mt5 {
80 margin-top: 5px;
81}
82"#
83 .trim()
84 );
85 }
86
87 #[test]
89 fn does_not_duplicate() {
90 let classes = Classes {
91 classes: vec![
92 RetrievedClassDefinition::new(
93 "mb10".to_string(),
94 r#".mb10 {
95 margin-bottom: 10px;
96}"#
97 .to_string(),
98 Modifiers::default(),
99 ),
100 RetrievedClassDefinition::new(
101 "mb10".to_string(),
102 r#".mb10 {
103 margin-bottom: 10px;
104}"#
105 .to_string(),
106 Modifiers::default(),
107 ),
108 ],
109 };
110
111 let contents = classes.to_css_file_contents();
112
113 assert_eq!(
114 contents,
115 r#"
116.mb10 {
117 margin-bottom: 10px;
118}
119"#
120 .trim()
121 );
122 }
123
124 #[test]
127 fn hover_comes_before_visited() {
128 let mut mod1 = Modifiers::default();
129 mod1.set_hover_enabled().unwrap();
130 let mod1 = (5, mod1);
131
132 let mod2 = Modifiers::default();
133 let mod2 = (10, mod2);
134
135 for (a, b) in vec![(mod1, mod2), (mod2, mod1)] {
136 let classes = Classes {
137 classes: vec![
138 RetrievedClassDefinition::new(
139 "".to_string(),
140 format!(
141 r#".mb{size} {{
142 margin-bottom: {size}px;
143}}"#,
144 size = a.0
145 ),
146 a.1,
147 ),
148 RetrievedClassDefinition::new(
149 "".to_string(),
150 format!(
151 r#".mb{size} {{
152 margin-bottom: {size}px;
153}}"#,
154 size = b.0
155 ),
156 b.1,
157 ),
158 ],
159 };
160
161 let contents = classes.to_css_file_contents();
162 assert!(
163 contents.find("margin-bottom: 5px").unwrap()
164 > contents.find("margin-bottom: 10px").unwrap()
165 )
166 }
167 }
168}