diff --git a/crates/swc_css_minifier/src/compress/declaration.rs b/crates/swc_css_minifier/src/compress/declaration.rs index 7fc904bad2b5..0ed3e97728d7 100644 --- a/crates/swc_css_minifier/src/compress/declaration.rs +++ b/crates/swc_css_minifier/src/compress/declaration.rs @@ -43,6 +43,197 @@ impl VisitMut for CompressDeclaration { if let DeclarationName::Ident(Ident { value, .. }) = &declaration.name { match &*value.to_lowercase() { + "display" if declaration.value.len() > 1 => { + let mut outside = None; + let mut inside = None; + let mut list_item = None; + + for value in declaration.value.iter() { + match value { + outside_node @ Value::Ident(Ident { value, .. }) + if matches!( + &*value.to_lowercase(), + "block" | "inline" | "run-in" + ) => + { + outside = Some(outside_node); + } + inside_node @ Value::Ident(Ident { value, .. }) + if matches!( + &*value.to_lowercase(), + "flow" | "flow-root" | "table" | "flex" | "grid" | "ruby" + ) => + { + inside = Some(inside_node); + } + list_item_node @ Value::Ident(Ident { value, .. }) + if &*value.to_lowercase() == "list-item" => + { + if let Some(Value::Ident(Ident { value, .. })) = inside { + if !matches!(&*value.to_lowercase(), "flow" | "flow-root") { + continue; + } + } + + list_item = Some(list_item_node) + } + _ => {} + } + } + + match (outside, inside, list_item) { + // `block flow` -> `block` + // `inline flow` -> `inline` + // `run-in flow` -> `run-in` + ( + Some(outside), + Some(Value::Ident(Ident { + value: inside_value, + .. + })), + None, + ) if &*inside_value.to_lowercase() == "flow" => { + declaration.value = vec![outside.clone()]; + } + // `block flow-root` -> `flow-root` + ( + Some(Value::Ident(Ident { + value: outside_value, + .. + })), + Some( + inside @ Value::Ident(Ident { + value: inside_value, + .. + }), + ), + None, + ) if &*outside_value.to_lowercase() == "block" + && &*inside_value.to_lowercase() == "flow-root" => + { + declaration.value = vec![inside.clone()]; + } + // `inline flow-root` -> `inline-block` + ( + Some(Value::Ident(Ident { + value: outside_value, + span, + .. + })), + Some(Value::Ident(Ident { + value: inside_value, + .. + })), + None, + ) if &*outside_value.to_lowercase() == "inline" + && &*inside_value.to_lowercase() == "flow-root" => + { + declaration.value = vec![Value::Ident(Ident { + span: *span, + value: "inline-block".into(), + raw: "inline-block".into(), + })]; + } + // `block flow list-item` -> `list-item` + ( + Some(Value::Ident(Ident { + value: outside_value, + .. + })), + Some(Value::Ident(Ident { + value: inside_value, + .. + })), + Some(list_item), + ) if &*outside_value.to_lowercase() == "block" + && &*inside_value.to_lowercase() == "flow" => + { + declaration.value = vec![list_item.clone()]; + } + // `block list-item` -> `list-item` + ( + Some(Value::Ident(Ident { + value: outside_value, + .. + })), + None, + Some(list_item), + ) if &*outside_value.to_lowercase() == "block" => { + declaration.value = vec![list_item.clone()]; + } + // `flow list-item` -> `list-item` + ( + None, + Some(Value::Ident(Ident { + value: inside_value, + .. + })), + Some(list_item), + ) if &*inside_value.to_lowercase() == "flow" => { + declaration.value = vec![list_item.clone()]; + } + // `inline flow list-item` -> `inline list-item` + ( + Some( + outside @ Value::Ident(Ident { + value: outside_value, + .. + }), + ), + Some(Value::Ident(Ident { + value: inside_value, + .. + })), + Some(list_item), + ) if &*outside_value.to_lowercase() == "inline" + && &*inside_value.to_lowercase() == "flow" => + { + declaration.value = vec![outside.clone(), list_item.clone()]; + } + // `block flex` -> `flex` + // `block grid` -> `grid` + // `block table` -> `table` + ( + Some(Value::Ident(Ident { + value: outside_value, + .. + })), + Some( + inside @ Value::Ident(Ident { + value: inside_value, + .. + }), + ), + None, + ) if &*outside_value.to_lowercase() == "block" + && matches!( + &*inside_value.to_lowercase(), + "flex" | "grid" | "table" + ) => + { + declaration.value = vec![inside.clone()]; + } + // `inline ruby` -> `ruby` + ( + Some(Value::Ident(Ident { + value: outside_value, + .. + })), + Some( + inside @ Value::Ident(Ident { + value: inside_value, + .. + }), + ), + None, + ) if &*outside_value.to_lowercase() == "inline" + && inside_value.to_lowercase() == "ruby" => + { + declaration.value = vec![inside.clone()]; + } + _ => {} + } + } "padding" | "margin" | "inset" | "scroll-margin" | "scroll-padding" if declaration.value.len() > 1 => { diff --git a/crates/swc_css_minifier/tests/fixture/compress-declaration/display/input.css b/crates/swc_css_minifier/tests/fixture/compress-declaration/display/input.css new file mode 100644 index 000000000000..9fe0ec5a618a --- /dev/null +++ b/crates/swc_css_minifier/tests/fixture/compress-declaration/display/input.css @@ -0,0 +1,159 @@ +.class1 { + display: block flow; +} + +.class2 { + DISPLAY: BLOCK FLOW; +} + +.class3 { + display: flow block; +} + +.class4 { + display: FLOW BLOCK; +} + +.class5 { + display: block flow-root; +} + +.class6 { + display: inline flow; +} + +.class7 { + display: inline flow-root; +} + +.class8 { + display: run-in flow; +} + +.class9 { + display: block flow list-item; +} + +.class10 { + display: flow list-item; +} + +.class11 { + display: block list-item; +} + +.class12 { + display: inline flow list-item; +} + +.class13 { + display: inline flow-root list-item; +} + +.class14 { + display: inline list-item; +} + +.class15 { + display: flow-root list-item; +} + +.class16 { + display: block flex; +} + +.class17 { + display: inline flex; +} + +.class18 { + display: block grid; +} + +.class19 { + display: inline grid; +} + +.class20 { + display: inline ruby; +} + +.class21 { + display: block ruby; +} + +.class22 { + display: block table; +} + +.class23 { + display: inline table; +} + +.class23 { + display: block; +} + +.class23 { + display: inline; +} + +.class23 { + display: inline-block; +} + +.class23 { + display: flex; +} + +.class23 { + display: inline-flex; +} + +.class23 { + display: grid; +} + +.class23 { + display: inline-grid; +} + +.class23 { + display: flow-root; +} + +.class23 { + display: none; +} + +.class23 { + display: contents; +} + +.class23 { + display: table-row; +} + +.class23 { + display: inherit; +} + +.class23 { + display: initial; +} + +.class23 { + display: revert; +} + +.class23 { + display: unset; +} + +.class24 { + display: -webkit-flex; +} + +.class25 { + display: -moz-box; +} diff --git a/crates/swc_css_minifier/tests/fixture/compress-declaration/display/output.min.css b/crates/swc_css_minifier/tests/fixture/compress-declaration/display/output.min.css new file mode 100644 index 000000000000..63c157072f42 --- /dev/null +++ b/crates/swc_css_minifier/tests/fixture/compress-declaration/display/output.min.css @@ -0,0 +1 @@ +.class1{display:block}.class2{DISPLAY:BLOCK}.class3{display:block}.class4{display:BLOCK}.class5{display:flow-root}.class6{display:inline}.class7{display:inline-block}.class8{display:run-in}.class9{display:list-item}.class10{display:list-item}.class11{display:list-item}.class12{display:inline list-item}.class13{display:inline flow-root list-item}.class14{display:inline list-item}.class15{display:flow-root list-item}.class16{display:flex}.class17{display:inline flex}.class18{display:grid}.class19{display:inline grid}.class20{display:ruby}.class21{display:block ruby}.class22{display:table}.class23{display:inline table}.class23{display:block}.class23{display:inline}.class23{display:inline-block}.class23{display:flex}.class23{display:inline-flex}.class23{display:grid}.class23{display:inline-grid}.class23{display:flow-root}.class23{display:none}.class23{display:contents}.class23{display:table-row}.class23{display:inherit}.class23{display:initial}.class23{display:revert}.class23{display:unset}.class24{display:-webkit-flex}.class25{display:-moz-box}