swc_css_minifier/compressor/
length.rs

1use swc_atoms::atom;
2use swc_css_ast::*;
3
4use super::Compressor;
5
6impl Compressor {
7    fn convert_length(&mut self, value: f64, from_unit: &str, to_unit: &str) -> f64 {
8        match to_unit {
9            "cm" => match from_unit {
10                "cm" => value,
11                "mm" => value / 10.0,
12                "q" => value / 40.0,
13                "in" => 2.54 * value,
14                "pc" => 2.54 / 6.0 * value,
15                "pt" => 2.54 / 72.0 * value,
16                "px" => 2.54 / 96.0 * value,
17                _ => {
18                    unreachable!()
19                }
20            },
21            "mm" => match from_unit {
22                "cm" => 10.0 * value,
23                "mm" => value,
24                "q" => value / 4.0,
25                "in" => 25.4 * value,
26                "pc" => 25.4 / 6.0 * value,
27                "pt" => 25.4 / 72.0 * value,
28                "px" => 25.4 / 96.0 * value,
29                _ => {
30                    unreachable!()
31                }
32            },
33            "q" => match from_unit {
34                "cm" => 40.0 * value,
35                "mm" => 4.0 * value,
36                "q" => value,
37                "in" => 101.6 * value,
38                "pc" => 101.6 / 6.0 * value,
39                "pt" => 101.6 / 72.0 * value,
40                "px" => 101.6 / 96.0 * value,
41                _ => {
42                    unreachable!()
43                }
44            },
45            "in" => match from_unit {
46                "cm" => value / 2.54,
47                "mm" => value / 25.4,
48                "q" => value / 101.6,
49                "in" => value,
50                "pc" => value / 6.0,
51                "pt" => value / 72.0,
52                "px" => value / 96.0,
53                _ => {
54                    unreachable!()
55                }
56            },
57            "pc" => match from_unit {
58                "cm" => 6.0 / 2.54 * value,
59                "mm" => 6.0 / 25.4 * value,
60                "q" => 6.0 / 101.6 * value,
61                "in" => 6.0 * value,
62                "pc" => value,
63                "pt" => 6.0 / 72.0 * value,
64                "px" => 6.0 / 96.0 * value,
65                _ => {
66                    unreachable!()
67                }
68            },
69            "pt" => match from_unit {
70                "cm" => 72.0 / 2.54 * value,
71                "mm" => 72.0 / 25.4 * value,
72                "q" => 72.0 / 101.6 * value,
73                "in" => 72.0 * value,
74                "pc" => 12.0 * value,
75                "pt" => value,
76                "px" => 0.75 * value,
77                _ => {
78                    unreachable!()
79                }
80            },
81            "px" => match from_unit {
82                "cm" => 96.0 / 2.54 * value,
83                "mm" => 96.0 / 25.4 * value,
84                "q" => 96.0 / 101.6 * value,
85                "in" => 96.0 * value,
86                "pc" => 16.0 * value,
87                "pt" => 96.0 / 72.0 * value,
88                "px" => value,
89                _ => {
90                    unreachable!()
91                }
92            },
93            _ => {
94                unreachable!()
95            }
96        }
97    }
98}
99
100impl Compressor {
101    pub(super) fn length_to_zero(&mut self, n: &mut Length) -> Option<Number> {
102        match &n {
103            Length {
104                value:
105                    Number {
106                        value: number_value,
107                        ..
108                    },
109                span,
110                ..
111            } if *number_value == 0.0 => Some(Number {
112                span: *span,
113                value: 0.0,
114                raw: None,
115            }),
116            _ => None,
117        }
118    }
119
120    pub(super) fn compress_component_value_for_length(&mut self, n: &mut ComponentValue) {
121        if self.ctx.in_math_function {
122            return;
123        }
124
125        let length = match n {
126            ComponentValue::Dimension(dimension) => dimension.as_mut_length(),
127            ComponentValue::LengthPercentage(length_percentage) => {
128                length_percentage.as_mut_length()
129            }
130            _ => None,
131        };
132
133        let Some(number) = length.and_then(|length| self.length_to_zero(length)) else {
134            return;
135        };
136
137        *n = ComponentValue::Number(Box::new(number));
138    }
139
140    pub(super) fn compress_length(&mut self, length: &mut Length) {
141        let value = length.value.value;
142
143        match &*length.unit.value {
144            "cm" => {
145                if value % 2.54 == 0.0 {
146                    let new_value = self.convert_length(value, &length.unit.value, "in");
147
148                    length.value = Number {
149                        span: length.value.span,
150                        value: new_value,
151                        raw: None,
152                    };
153                    length.unit = Ident {
154                        span: length.unit.span,
155                        value: atom!("in"),
156                        raw: None,
157                    };
158                } else if value <= 0.1 {
159                    let new_value = self.convert_length(value, &length.unit.value, "mm");
160
161                    length.value = Number {
162                        span: length.value.span,
163                        value: new_value,
164                        raw: None,
165                    };
166                    length.unit = Ident {
167                        span: length.unit.span,
168                        value: atom!("mm"),
169                        raw: None,
170                    };
171                }
172            }
173            "mm" => {
174                if value % 25.4 == 0.0 {
175                    let new_value = self.convert_length(value, &length.unit.value, "in");
176
177                    length.value = Number {
178                        span: length.value.span,
179                        value: new_value,
180                        raw: None,
181                    };
182                    length.unit = Ident {
183                        span: length.unit.span,
184                        value: atom!("in"),
185                        raw: None,
186                    };
187                } else if value % 10.0 == 0.0 {
188                    let new_value = self.convert_length(value, &length.unit.value, "cm");
189
190                    length.value = Number {
191                        span: length.value.span,
192                        value: new_value,
193                        raw: None,
194                    };
195                    length.unit = Ident {
196                        span: length.unit.span,
197                        value: atom!("cm"),
198                        raw: None,
199                    };
200                }
201            }
202            "q" => {
203                if value > 80.0 && value % 40.0 == 0.0 {
204                    let new_value = self.convert_length(value, &length.unit.value, "cm");
205
206                    length.value = Number {
207                        span: length.value.span,
208                        value: new_value,
209                        raw: None,
210                    };
211                    length.unit = Ident {
212                        span: length.unit.span,
213                        value: atom!("cm"),
214                        raw: None,
215                    };
216                } else if value % 101.6 == 0.0 {
217                    let new_value = self.convert_length(value, &length.unit.value, "in");
218
219                    length.value = Number {
220                        span: length.value.span,
221                        value: new_value,
222                        raw: None,
223                    };
224                    length.unit = Ident {
225                        span: length.unit.span,
226                        value: atom!("in"),
227                        raw: None,
228                    };
229                }
230            }
231            "pc" => {
232                if value % 6.0 == 0.0 {
233                    let new_value = self.convert_length(value, &length.unit.value, "in");
234
235                    length.value = Number {
236                        span: length.value.span,
237                        value: new_value,
238                        raw: None,
239                    };
240                    length.unit = Ident {
241                        span: length.unit.span,
242                        value: atom!("in"),
243                        raw: None,
244                    };
245                }
246            }
247            "pt" => {
248                if value % 72.0 == 0.0 {
249                    let new_value = self.convert_length(value, &length.unit.value, "in");
250
251                    length.value = Number {
252                        span: length.value.span,
253                        value: new_value,
254                        raw: None,
255                    };
256                    length.unit = Ident {
257                        span: length.unit.span,
258                        value: atom!("in"),
259                        raw: None,
260                    };
261                } else if value % 12.0 == 0.0 {
262                    let new_value = self.convert_length(value, &length.unit.value, "pc");
263
264                    length.value = Number {
265                        span: length.value.span,
266                        value: new_value,
267                        raw: None,
268                    };
269                    length.unit = Ident {
270                        span: length.unit.span,
271                        value: atom!("pc"),
272                        raw: None,
273                    };
274                } else if value % 0.75 == 0.0 {
275                    let new_value = self.convert_length(value, &length.unit.value, "px");
276
277                    length.value = Number {
278                        span: length.value.span,
279                        value: new_value,
280                        raw: None,
281                    };
282                    length.unit = Ident {
283                        span: length.unit.span,
284                        value: atom!("px"),
285                        raw: None,
286                    };
287                }
288            }
289            _ => {}
290        }
291    }
292}