From 7079e88744ece43ebf82b05a376c5683c8015084 Mon Sep 17 00:00:00 2001 From: Alexander Akait <4567934+alexander-akait@users.noreply.github.com> Date: Wed, 23 Feb 2022 18:21:51 +0300 Subject: [PATCH] feat(css/minifier): Compress lengths (#3698) --- .../swc_css_minifier/src/compress/length.rs | 51 ++++++++++ crates/swc_css_minifier/src/compress/mod.rs | 1 + crates/swc_css_minifier/src/lib.rs | 7 +- .../compress-keyframe-selector/output.min.css | 2 +- .../tests/fixture/compress-length/input.css | 92 +++++++++++++++++++ .../fixture/compress-length/output.min.css | 1 + 6 files changed, 150 insertions(+), 4 deletions(-) create mode 100644 crates/swc_css_minifier/src/compress/length.rs create mode 100644 crates/swc_css_minifier/tests/fixture/compress-length/input.css create mode 100644 crates/swc_css_minifier/tests/fixture/compress-length/output.min.css diff --git a/crates/swc_css_minifier/src/compress/length.rs b/crates/swc_css_minifier/src/compress/length.rs new file mode 100644 index 00000000000..f4729e5637f --- /dev/null +++ b/crates/swc_css_minifier/src/compress/length.rs @@ -0,0 +1,51 @@ +use swc_css_ast::*; +use swc_css_visit::{VisitMut, VisitMutWith}; + +pub fn compress_length() -> impl VisitMut { + CompressLength { + in_math_function: false, + } +} + +struct CompressLength { + in_math_function: bool, +} + +impl VisitMut for CompressLength { + fn visit_mut_calc_sum(&mut self, function: &mut CalcSum) { + let old_in_math_function = self.in_math_function; + + self.in_math_function = true; + + function.visit_mut_children_with(self); + + self.in_math_function = old_in_math_function; + } + + fn visit_mut_value(&mut self, value: &mut Value) { + value.visit_mut_children_with(self); + + if self.in_math_function { + return; + } + + match &value { + Value::Dimension(Dimension::Length(Length { + value: + Number { + value: number_value, + .. + }, + span, + .. + })) if *number_value == 0.0 => { + *value = Value::Number(Number { + span: *span, + value: 0.0, + raw: "0".into(), + }); + } + _ => {} + } + } +} diff --git a/crates/swc_css_minifier/src/compress/mod.rs b/crates/swc_css_minifier/src/compress/mod.rs index 00b7587ce06..667871ace06 100644 --- a/crates/swc_css_minifier/src/compress/mod.rs +++ b/crates/swc_css_minifier/src/compress/mod.rs @@ -4,6 +4,7 @@ pub mod easing_function; pub mod empty; pub mod frequency; pub mod keyframes; +pub mod length; pub mod selector; pub mod time; pub mod transform_function; diff --git a/crates/swc_css_minifier/src/lib.rs b/crates/swc_css_minifier/src/lib.rs index 651cbcd80d1..24c9b444ffc 100644 --- a/crates/swc_css_minifier/src/lib.rs +++ b/crates/swc_css_minifier/src/lib.rs @@ -6,15 +6,16 @@ use swc_css_visit::VisitMutWith; use self::compress::{ angle::compress_angle, declaration::compress_declaration, easing_function::compress_easing_function, empty::compress_empty, - frequency::compress_frequency, keyframes::compress_keyframes, selector::compress_selector, - time::compress_time, transform_function::compress_transform_function, urange::compress_urange, - url::compress_url, + frequency::compress_frequency, keyframes::compress_keyframes, length::compress_length, + selector::compress_selector, time::compress_time, + transform_function::compress_transform_function, urange::compress_urange, url::compress_url, }; mod compress; pub fn minify(stylesheet: &mut Stylesheet) { stylesheet.visit_mut_with(&mut compress_empty()); + stylesheet.visit_mut_with(&mut compress_length()); stylesheet.visit_mut_with(&mut compress_angle()); stylesheet.visit_mut_with(&mut compress_time()); stylesheet.visit_mut_with(&mut compress_frequency()); diff --git a/crates/swc_css_minifier/tests/fixture/compress-keyframe-selector/output.min.css b/crates/swc_css_minifier/tests/fixture/compress-keyframe-selector/output.min.css index 91ef2f8fd10..20b4e827132 100644 --- a/crates/swc_css_minifier/tests/fixture/compress-keyframe-selector/output.min.css +++ b/crates/swc_css_minifier/tests/fixture/compress-keyframe-selector/output.min.css @@ -1 +1 @@ -@keyframes slide-right{0%{margin-left:0px}50%{margin-left:110px;opacity:1}50%{opacity:.9}to{margin-left:200px}}@keyframes slide-right-upper-case{0%{margin-left:0px}50%{margin-left:110px;opacity:1}50%{opacity:.9}TO{margin-left:200px}}@keyframes slide-right-one{0%{margin-left:0px}50%{margin-left:110px;opacity:1}50%{opacity:.9}to{margin-left:200px}}@keyframes slide-right-two{0%{margin-left:0px}50%{margin-left:110px;opacity:1}50%{opacity:.9}to{margin-left:200px}}@keyframes slide-right-three{0%,50%{margin-left:0px}60%,to{margin-left:200px}}@keyframes foo{0%{margin-left:0px}to{margin-left:200px}}@keyframes"initial"{0%{margin-left:0px}to{margin-left:200px}} +@keyframes slide-right{0%{margin-left:0}50%{margin-left:110px;opacity:1}50%{opacity:.9}to{margin-left:200px}}@keyframes slide-right-upper-case{0%{margin-left:0}50%{margin-left:110px;opacity:1}50%{opacity:.9}TO{margin-left:200px}}@keyframes slide-right-one{0%{margin-left:0}50%{margin-left:110px;opacity:1}50%{opacity:.9}to{margin-left:200px}}@keyframes slide-right-two{0%{margin-left:0}50%{margin-left:110px;opacity:1}50%{opacity:.9}to{margin-left:200px}}@keyframes slide-right-three{0%,50%{margin-left:0}60%,to{margin-left:200px}}@keyframes foo{0%{margin-left:0}to{margin-left:200px}}@keyframes"initial"{0%{margin-left:0}to{margin-left:200px}} diff --git a/crates/swc_css_minifier/tests/fixture/compress-length/input.css b/crates/swc_css_minifier/tests/fixture/compress-length/input.css new file mode 100644 index 00000000000..bb043661ac5 --- /dev/null +++ b/crates/swc_css_minifier/tests/fixture/compress-length/input.css @@ -0,0 +1,92 @@ +.class1 { + width: 0px; +} + +.class2 { + width: 100px +} + +.class3 { + width: calc(100px + 0px); +} + +.class4 { + width: caLc(100px + 0px); +} + +.class5 { + padding: calc(1in + 0in * 2) 0 calc(0px) 0; +} + +.class6 { + padding: calc(var(--foo, 0px) + 10px) 0; +} + +.class7 { + padding: max(10px, var(--foo, 0px)) 0; +} + +.class8 { + right: max(100vw, 0rem); +} + +.class9 { + right: calc(max(100vw, 0rem)); +} + +.class10 { + top: 0.000px; +} + +@media (min-width: 0px) { + .foo { + color: red + } +} + +@media (min-width: 0) { + .bar { + color: red; + } +} + +.class11 { + font: normal normal 400 0px/ 0px cursive; +} + +.class12 { + grid-template-columns: repeat(2, 50px 0px) 100px; +} + + +.class13 { + margin: 0q; +} + +.class14 { + transform: translate(0px); +} + +.class15 { + padding: min(1vw, 0in) max(1vw, 0px) clamp(0em, 1vw, 10px) 0px; +} + +.class16 { + padding: 1px 0vmax 2px 3px; +} + +.class17 { + padding: 1px 2px 0rem 3px; +} + +.class18 { + width: 0PX; +} + +.class19 { + width: +0px; +} + +.class20 { + top: -0.000px; +} diff --git a/crates/swc_css_minifier/tests/fixture/compress-length/output.min.css b/crates/swc_css_minifier/tests/fixture/compress-length/output.min.css new file mode 100644 index 00000000000..0462ac36e1d --- /dev/null +++ b/crates/swc_css_minifier/tests/fixture/compress-length/output.min.css @@ -0,0 +1 @@ +.class1{width:0}.class2{width:100px}.class3{width:calc(100px + 0px)}.class4{width:caLc(100px + 0px)}.class5{padding:calc(1in + 0in*2)0 calc(0px)0}.class6{padding:calc(var(--foo,0px) + 10px)0}.class7{padding:max(10px,var(--foo,0px))0}.class8{right:max(100vw,0rem)}.class9{right:calc(max(100vw,0rem))}.class10{top:0}@media(min-width:0px){.foo{color:red}}@media(min-width:0){.bar{color:red}}.class11{font:normal normal 400 0/0 cursive}.class12{grid-template-columns:repeat(2,50px 0)100px}.class13{margin:0}.class14{transform:translate(0)}.class15{padding:min(1vw,0in)max(1vw,0px)clamp(0em,1vw,10px)0}.class16{padding:1px 0 2px 3px}.class17{padding:1px 2px 0 3px}.class18{width:0}.class19{width:0}.class20{top:0}