mirror of
https://github.com/swc-project/swc.git
synced 2024-12-01 01:13:56 +03:00
feat(css/minifier): Compress declarations (#3649)
This commit is contained in:
parent
60b3d2e4a3
commit
7d15316ee1
111
crates/swc_css_minifier/src/compress/declaration.rs
Normal file
111
crates/swc_css_minifier/src/compress/declaration.rs
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
use swc_common::util::take::Take;
|
||||||
|
use swc_css_ast::*;
|
||||||
|
use swc_css_visit::{VisitMut, VisitMutWith};
|
||||||
|
pub fn compress_declaration() -> impl VisitMut {
|
||||||
|
CompressDeclaration {}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CompressDeclaration {}
|
||||||
|
|
||||||
|
impl CompressDeclaration {
|
||||||
|
fn is_same_dimension_length_nodes(
|
||||||
|
&mut self,
|
||||||
|
node_1: Option<&Value>,
|
||||||
|
node_2: Option<&Value>,
|
||||||
|
) -> bool {
|
||||||
|
if let Some(Value::Dimension(Dimension::Length(Length {
|
||||||
|
value: value_1,
|
||||||
|
unit: unit_1,
|
||||||
|
..
|
||||||
|
}))) = node_1
|
||||||
|
{
|
||||||
|
if let Some(Value::Dimension(Dimension::Length(Length {
|
||||||
|
value: value_2,
|
||||||
|
unit: unit_2,
|
||||||
|
..
|
||||||
|
}))) = node_2
|
||||||
|
{
|
||||||
|
if value_1.value == value_2.value
|
||||||
|
&& unit_1.value.to_lowercase() == unit_2.value.to_lowercase()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VisitMut for CompressDeclaration {
|
||||||
|
fn visit_mut_declaration(&mut self, declaration: &mut Declaration) {
|
||||||
|
declaration.visit_mut_children_with(self);
|
||||||
|
|
||||||
|
if let DeclarationName::Ident(Ident { value, .. }) = &declaration.name {
|
||||||
|
match &*value.to_lowercase() {
|
||||||
|
"padding" | "margin" | "inset" if declaration.value.len() > 1 => {
|
||||||
|
let top = declaration.value.get(0);
|
||||||
|
let right = declaration
|
||||||
|
.value
|
||||||
|
.get(1)
|
||||||
|
.or_else(|| declaration.value.get(0));
|
||||||
|
let bottom = declaration
|
||||||
|
.value
|
||||||
|
.get(2)
|
||||||
|
.or_else(|| declaration.value.get(0));
|
||||||
|
let left = declaration
|
||||||
|
.value
|
||||||
|
.get(3)
|
||||||
|
.or_else(|| declaration.value.get(1))
|
||||||
|
.or_else(|| declaration.value.get(0));
|
||||||
|
|
||||||
|
if self.is_same_dimension_length_nodes(left, right) {
|
||||||
|
if self.is_same_dimension_length_nodes(bottom, top) {
|
||||||
|
if self.is_same_dimension_length_nodes(right, top) {
|
||||||
|
declaration.value = vec![top.unwrap().clone()];
|
||||||
|
} else {
|
||||||
|
declaration.value =
|
||||||
|
vec![top.unwrap().clone(), right.unwrap().clone()];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
declaration.value = vec![
|
||||||
|
top.unwrap().clone(),
|
||||||
|
right.unwrap().clone(),
|
||||||
|
bottom.unwrap().clone(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"font-weight" => {
|
||||||
|
declaration.value = declaration
|
||||||
|
.value
|
||||||
|
.take()
|
||||||
|
.into_iter()
|
||||||
|
.map(|node| match node {
|
||||||
|
Value::Ident(Ident { value, span, .. })
|
||||||
|
if value.to_lowercase() == "normal" =>
|
||||||
|
{
|
||||||
|
Value::Number(Number {
|
||||||
|
span,
|
||||||
|
value: 400.0,
|
||||||
|
raw: "400".into(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Value::Ident(Ident { value, span, .. })
|
||||||
|
if value.to_lowercase() == "bold" =>
|
||||||
|
{
|
||||||
|
Value::Number(Number {
|
||||||
|
span,
|
||||||
|
value: 700.0,
|
||||||
|
raw: "700".into(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => node,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
pub mod angle;
|
pub mod angle;
|
||||||
|
pub mod declaration;
|
||||||
pub mod easing_function;
|
pub mod easing_function;
|
||||||
pub mod empty;
|
pub mod empty;
|
||||||
pub mod keyframes;
|
pub mod keyframes;
|
||||||
|
@ -2,7 +2,8 @@ use swc_css_ast::*;
|
|||||||
use swc_css_visit::VisitMutWith;
|
use swc_css_visit::VisitMutWith;
|
||||||
|
|
||||||
use self::compress::{
|
use self::compress::{
|
||||||
angle::compress_angle, easing_function::compress_easing_function, empty::compress_empty,
|
angle::compress_angle, declaration::compress_declaration,
|
||||||
|
easing_function::compress_easing_function, empty::compress_empty,
|
||||||
keyframes::compress_keyframes, selector::compress_selector, time::compress_time,
|
keyframes::compress_keyframes, selector::compress_selector, time::compress_time,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -15,4 +16,7 @@ pub fn minify(stylesheet: &mut Stylesheet) {
|
|||||||
stylesheet.visit_mut_with(&mut compress_easing_function());
|
stylesheet.visit_mut_with(&mut compress_easing_function());
|
||||||
stylesheet.visit_mut_with(&mut compress_time());
|
stylesheet.visit_mut_with(&mut compress_time());
|
||||||
stylesheet.visit_mut_with(&mut compress_angle());
|
stylesheet.visit_mut_with(&mut compress_angle());
|
||||||
|
stylesheet.visit_mut_with(&mut compress_declaration());
|
||||||
|
stylesheet.visit_mut_with(&mut compress_keyframes());
|
||||||
|
stylesheet.visit_mut_with(&mut compress_empty());
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
.class1 {font-weight: 1;}
|
||||||
|
.class1 {font-weight: 400;}
|
||||||
|
.class1 {font-weight: 1000;}
|
||||||
|
.class2 {font-weight: normal;}
|
||||||
|
.class3 {font-weight: bold;}
|
||||||
|
.class3 {font-WEIGHT: BOLD;}
|
||||||
|
.class4 {font-weight: normal bold;}
|
||||||
|
.class5 {font-weight: 600 bold;}
|
1
crates/swc_css_minifier/tests/fixture/compress-declaration/font-weight/output.min.css
vendored
Normal file
1
crates/swc_css_minifier/tests/fixture/compress-declaration/font-weight/output.min.css
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
.class1{font-weight:1}.class1{font-weight:400}.class1{font-weight:1e3}.class2{font-weight:400}.class3{font-weight:700}.class3{font-WEIGHT:700}.class4{font-weight:400 700}.class5{font-weight:600 700}
|
@ -0,0 +1,77 @@
|
|||||||
|
.class1 {
|
||||||
|
inset: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.class2 {
|
||||||
|
inset: 20px 21px 22px 23px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 4 -> 3 */
|
||||||
|
.class4 {
|
||||||
|
inset: 20px 21px 22px 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 4 -> 2 */
|
||||||
|
.class5 {
|
||||||
|
inset: 20px 21px 20px 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 4 -> 1 */
|
||||||
|
.class6 {
|
||||||
|
inset: 20px 20px 20px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 3 -> 2 */
|
||||||
|
.class7 {
|
||||||
|
inset: 20px 21px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 3 -> 1 */
|
||||||
|
.class8 {
|
||||||
|
inset: 20px 20px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 2 -> 1 */
|
||||||
|
.class10 {
|
||||||
|
inset: 20px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.class11 {
|
||||||
|
inset: 20px 20px 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.class12 {
|
||||||
|
inset: var(--inset);
|
||||||
|
}
|
||||||
|
|
||||||
|
.class13 {
|
||||||
|
inset: 20px var(--inset);
|
||||||
|
}
|
||||||
|
|
||||||
|
.class14 {
|
||||||
|
inset: 20px 20px var(--inset);
|
||||||
|
}
|
||||||
|
|
||||||
|
.class15 {
|
||||||
|
inset: 20px 20px 20px var(--inset);
|
||||||
|
}
|
||||||
|
|
||||||
|
.class16 {
|
||||||
|
inset: var(--inset);
|
||||||
|
}
|
||||||
|
|
||||||
|
.class17 {
|
||||||
|
inset: var(--inset) var(--inset);
|
||||||
|
}
|
||||||
|
|
||||||
|
.class18 {
|
||||||
|
inset: var(--inset) var(--inset) var(--inset) var(--inset);
|
||||||
|
}
|
||||||
|
|
||||||
|
.class19 {
|
||||||
|
INSET: 20PX 20pX 20Px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.class20 {
|
||||||
|
inset: 20px 3em 20px 3em;
|
||||||
|
}
|
1
crates/swc_css_minifier/tests/fixture/compress-declaration/inset/output.min.css
vendored
Normal file
1
crates/swc_css_minifier/tests/fixture/compress-declaration/inset/output.min.css
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
.class1{inset:20px}.class2{inset:20px 21px 22px 23px}.class4{inset:20px 21px 22px}.class5{inset:20px 21px}.class6{inset:20px}.class7{inset:20px 21px}.class8{inset:20px}.class10{inset:20px}.class11{inset:20px 20px 21px}.class12{inset:var(--inset)}.class13{inset:20px var(--inset)}.class14{inset:20px 20px var(--inset)}.class15{inset:20px 20px 20px var(--inset)}.class16{inset:var(--inset)}.class17{inset:var(--inset)var(--inset)}.class18{inset:var(--inset)var(--inset)var(--inset)var(--inset)}.class19{INSET:20PX}.class20{inset:20px 3em}
|
@ -0,0 +1,77 @@
|
|||||||
|
.class1 {
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.class2 {
|
||||||
|
margin: 20px 21px 22px 23px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 4 -> 3 */
|
||||||
|
.class4 {
|
||||||
|
margin: 20px 21px 22px 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 4 -> 2 */
|
||||||
|
.class5 {
|
||||||
|
margin: 20px 21px 20px 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 4 -> 1 */
|
||||||
|
.class6 {
|
||||||
|
margin: 20px 20px 20px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 3 -> 2 */
|
||||||
|
.class7 {
|
||||||
|
margin: 20px 21px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 3 -> 1 */
|
||||||
|
.class8 {
|
||||||
|
margin: 20px 20px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 2 -> 1 */
|
||||||
|
.class10 {
|
||||||
|
margin: 20px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.class11 {
|
||||||
|
margin: 20px 20px 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.class12 {
|
||||||
|
margin: var(--margin);
|
||||||
|
}
|
||||||
|
|
||||||
|
.class13 {
|
||||||
|
margin: 20px var(--margin);
|
||||||
|
}
|
||||||
|
|
||||||
|
.class14 {
|
||||||
|
margin: 20px 20px var(--margin);
|
||||||
|
}
|
||||||
|
|
||||||
|
.class15 {
|
||||||
|
margin: 20px 20px 20px var(--margin);
|
||||||
|
}
|
||||||
|
|
||||||
|
.class16 {
|
||||||
|
margin: var(--margin);
|
||||||
|
}
|
||||||
|
|
||||||
|
.class17 {
|
||||||
|
margin: var(--margin) var(--margin);
|
||||||
|
}
|
||||||
|
|
||||||
|
.class18 {
|
||||||
|
margin: var(--margin) var(--margin) var(--margin) var(--margin);
|
||||||
|
}
|
||||||
|
|
||||||
|
.class19 {
|
||||||
|
MARGIN: 20PX 20pX 20Px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.class20 {
|
||||||
|
margin: 20px 3em 20px 3em;
|
||||||
|
}
|
1
crates/swc_css_minifier/tests/fixture/compress-declaration/margin/output.min.css
vendored
Normal file
1
crates/swc_css_minifier/tests/fixture/compress-declaration/margin/output.min.css
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
.class1{margin:20px}.class2{margin:20px 21px 22px 23px}.class4{margin:20px 21px 22px}.class5{margin:20px 21px}.class6{margin:20px}.class7{margin:20px 21px}.class8{margin:20px}.class10{margin:20px}.class11{margin:20px 20px 21px}.class12{margin:var(--margin)}.class13{margin:20px var(--margin)}.class14{margin:20px 20px var(--margin)}.class15{margin:20px 20px 20px var(--margin)}.class16{margin:var(--margin)}.class17{margin:var(--margin)var(--margin)}.class18{margin:var(--margin)var(--margin)var(--margin)var(--margin)}.class19{MARGIN:20PX}.class20{margin:20px 3em}
|
@ -0,0 +1,77 @@
|
|||||||
|
.class1 {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.class2 {
|
||||||
|
padding: 20px 21px 22px 23px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 4 -> 3 */
|
||||||
|
.class4 {
|
||||||
|
padding: 20px 21px 22px 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 4 -> 2 */
|
||||||
|
.class5 {
|
||||||
|
padding: 20px 21px 20px 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 4 -> 1 */
|
||||||
|
.class6 {
|
||||||
|
padding: 20px 20px 20px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 3 -> 2 */
|
||||||
|
.class7 {
|
||||||
|
padding: 20px 21px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 3 -> 1 */
|
||||||
|
.class8 {
|
||||||
|
padding: 20px 20px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 2 -> 1 */
|
||||||
|
.class10 {
|
||||||
|
padding: 20px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.class11 {
|
||||||
|
padding: 20px 20px 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.class12 {
|
||||||
|
padding: var(--padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
.class13 {
|
||||||
|
padding: 20px var(--padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
.class14 {
|
||||||
|
padding: 20px 20px var(--padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
.class15 {
|
||||||
|
padding: 20px 20px 20px var(--padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
.class16 {
|
||||||
|
padding: var(--padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
.class17 {
|
||||||
|
padding: var(--padding) var(--padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
.class18 {
|
||||||
|
padding: var(--padding) var(--padding) var(--padding) var(--padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
.class19 {
|
||||||
|
PADDING: 20PX 20pX 20Px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.class20 {
|
||||||
|
padding: 20px 3em 20px 3em;
|
||||||
|
}
|
1
crates/swc_css_minifier/tests/fixture/compress-declaration/padding/output.min.css
vendored
Normal file
1
crates/swc_css_minifier/tests/fixture/compress-declaration/padding/output.min.css
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
.class1{padding:20px}.class2{padding:20px 21px 22px 23px}.class4{padding:20px 21px 22px}.class5{padding:20px 21px}.class6{padding:20px}.class7{padding:20px 21px}.class8{padding:20px}.class10{padding:20px}.class11{padding:20px 20px 21px}.class12{padding:var(--padding)}.class13{padding:20px var(--padding)}.class14{padding:20px 20px var(--padding)}.class15{padding:20px 20px 20px var(--padding)}.class16{padding:var(--padding)}.class17{padding:var(--padding)var(--padding)}.class18{padding:var(--padding)var(--padding)var(--padding)var(--padding)}.class19{PADDING:20PX}.class20{padding:20px 3em}
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user