diff --git a/crates/swc_css_minifier/src/compressor/calc_sum.rs b/crates/swc_css_minifier/src/compressor/calc_sum.rs index 9ae0c3db8cb6..4386152b5934 100644 --- a/crates/swc_css_minifier/src/compressor/calc_sum.rs +++ b/crates/swc_css_minifier/src/compressor/calc_sum.rs @@ -184,6 +184,20 @@ impl CalcSumContext { let mut sum = s.clone(); self.nested_fold(operator, &mut sum); } + CalcValueOrOperator::Value(CalcValue::Function(Function { + name, value, .. + })) if is_calc_function_name(name) && value.len() == 1 => { + match &value[0] { + ComponentValue::CalcSum(calc_sum) => { + let mut sum = calc_sum.clone(); + self.nested_fold(operator, &mut sum); + } + _ => { + // Other cases (constant, function...), just push the data + self.push(operator, operand); + } + } + } _ => { // Other cases (constant, function...), just push the data self.push(operator, operand); @@ -970,39 +984,23 @@ impl Compressor { ComponentValue::CalcSum(CalcSum { expressions: calc_sum_expressions, .. - }) if calc_sum_expressions.len() == 1 => { - match &calc_sum_expressions[0] { - CalcProductOrOperator::Product(CalcProduct { - expressions: calc_product_expressions, - .. - }) if calc_product_expressions.len() == 1 => { - match &calc_product_expressions[0] { - CalcValueOrOperator::Value(CalcValue::Sum(_)) => { - // Do nothing, we cannot transform a - // CalcSum into a ComponentValue - } - CalcValueOrOperator::Value(CalcValue::Constant(_)) => { - // https://www.w3.org/TR/css-values-4/#calc-constants - // "These keywords are only usable - // within a calculation" - // "If used outside of a calculation, - // they’re treated like any other - // keyword" - } - // `calc` and other math functions can be used in `@supports` to - // check availability, we should leave them as is - CalcValueOrOperator::Value(calc_value) - if !self.in_supports_conidition => - { - *component_value = - transform_calc_value_into_component_value(calc_value); - } - _ => {} + }) if calc_sum_expressions.len() == 1 => match &calc_sum_expressions[0] { + CalcProductOrOperator::Product(CalcProduct { + expressions: calc_product_expressions, + .. + }) if calc_product_expressions.len() == 1 => { + if let CalcValueOrOperator::Value(calc_value) = + &calc_product_expressions[0] + { + if let Some(cv) = + transform_calc_value_into_component_value(calc_value) + { + *component_value = cv; } } - _ => {} } - } + _ => {} + }, _ => {} } } diff --git a/crates/swc_css_minifier/src/compressor/container.rs b/crates/swc_css_minifier/src/compressor/container.rs index 5d03b3273160..45e64b331119 100644 --- a/crates/swc_css_minifier/src/compressor/container.rs +++ b/crates/swc_css_minifier/src/compressor/container.rs @@ -13,46 +13,30 @@ impl Compressor { ComponentValue::CalcSum(CalcSum { expressions: calc_sum_expressions, .. - }) if calc_sum_expressions.len() == 1 => { - match &calc_sum_expressions[0] { - CalcProductOrOperator::Product(CalcProduct { - expressions: calc_product_expressions, - .. - }) if calc_product_expressions.len() == 1 => { - match &calc_product_expressions[0] { - CalcValueOrOperator::Value(CalcValue::Sum(_)) => { - // Do nothing, we cannot transform a - // CalcSum into a ComponentValue + }) if calc_sum_expressions.len() == 1 => match &calc_sum_expressions[0] { + CalcProductOrOperator::Product(CalcProduct { + expressions: calc_product_expressions, + .. + }) if calc_product_expressions.len() == 1 => { + if let CalcValueOrOperator::Value(calc_value) = + &calc_product_expressions[0] + { + match transform_calc_value_into_component_value(calc_value) { + Some(ComponentValue::Function(function)) => { + *n = SizeFeatureValue::Function(function); } - CalcValueOrOperator::Value(CalcValue::Constant(_)) => { - // https://www.w3.org/TR/css-values-4/#calc-constants - // "These keywords are only usable - // within a calculation" - // "If used outside of a calculation, - // they’re treated like any other - // keyword" + Some(ComponentValue::Dimension(dimension)) => { + *n = SizeFeatureValue::Dimension(dimension); } - CalcValueOrOperator::Value(calc_value) => { - match transform_calc_value_into_component_value(calc_value) - { - ComponentValue::Function(function) => { - *n = SizeFeatureValue::Function(function); - } - ComponentValue::Dimension(dimension) => { - *n = SizeFeatureValue::Dimension(dimension); - } - ComponentValue::Number(number) => { - *n = SizeFeatureValue::Number(number); - } - _ => {} - } + Some(ComponentValue::Number(number)) => { + *n = SizeFeatureValue::Number(number); } _ => {} } } - _ => {} } - } + _ => {} + }, _ => {} } } diff --git a/crates/swc_css_minifier/src/compressor/math/mod.rs b/crates/swc_css_minifier/src/compressor/math/mod.rs index b13ae4bb61e7..cb4e31f1bd29 100644 --- a/crates/swc_css_minifier/src/compressor/math/mod.rs +++ b/crates/swc_css_minifier/src/compressor/math/mod.rs @@ -7,72 +7,76 @@ pub fn is_calc_function_name(ident: &Ident) -> bool { || ident.value.to_ascii_lowercase() == js_word!("-moz-calc") } -pub fn transform_calc_value_into_component_value(calc_value: &CalcValue) -> ComponentValue { +pub fn transform_calc_value_into_component_value(calc_value: &CalcValue) -> Option { match &calc_value { - CalcValue::Number(n) => ComponentValue::Number(n.clone()), + CalcValue::Number(n) => Some(ComponentValue::Number(n.clone())), CalcValue::Dimension(Dimension::Length(l)) => { - ComponentValue::Dimension(Dimension::Length(Length { + Some(ComponentValue::Dimension(Dimension::Length(Length { span: l.span, value: l.value.clone(), unit: l.unit.clone(), - })) + }))) } CalcValue::Dimension(Dimension::Angle(a)) => { - ComponentValue::Dimension(Dimension::Angle(Angle { + Some(ComponentValue::Dimension(Dimension::Angle(Angle { span: a.span, value: a.value.clone(), unit: a.unit.clone(), - })) + }))) } CalcValue::Dimension(Dimension::Time(t)) => { - ComponentValue::Dimension(Dimension::Time(Time { + Some(ComponentValue::Dimension(Dimension::Time(Time { span: t.span, value: t.value.clone(), unit: t.unit.clone(), - })) + }))) } CalcValue::Dimension(Dimension::Frequency(f)) => { - ComponentValue::Dimension(Dimension::Frequency(Frequency { + Some(ComponentValue::Dimension(Dimension::Frequency(Frequency { span: f.span, value: f.value.clone(), unit: f.unit.clone(), - })) + }))) } - CalcValue::Dimension(Dimension::Resolution(r)) => { - ComponentValue::Dimension(Dimension::Resolution(Resolution { + CalcValue::Dimension(Dimension::Resolution(r)) => Some(ComponentValue::Dimension( + Dimension::Resolution(Resolution { span: r.span, value: r.value.clone(), unit: r.unit.clone(), - })) - } + }), + )), CalcValue::Dimension(Dimension::Flex(f)) => { - ComponentValue::Dimension(Dimension::Flex(Flex { + Some(ComponentValue::Dimension(Dimension::Flex(Flex { span: f.span, value: f.value.clone(), unit: f.unit.clone(), - })) + }))) } - CalcValue::Dimension(Dimension::UnknownDimension(u)) => { - ComponentValue::Dimension(Dimension::UnknownDimension(UnknownDimension { + CalcValue::Dimension(Dimension::UnknownDimension(u)) => Some(ComponentValue::Dimension( + Dimension::UnknownDimension(UnknownDimension { span: u.span, value: u.value.clone(), unit: u.unit.clone(), - })) - } - CalcValue::Percentage(p) => ComponentValue::Percentage(Percentage { + }), + )), + CalcValue::Percentage(p) => Some(ComponentValue::Percentage(Percentage { span: p.span, value: p.value.clone(), - }), - CalcValue::Function(f) => ComponentValue::Function(Function { + })), + CalcValue::Function(f) => Some(ComponentValue::Function(Function { span: f.span, name: f.name.clone(), value: f.value.to_vec(), - }), + })), CalcValue::Constant(_) => { - unreachable!("CalcValue::Constant cannot be transformed into a ComponentValue per spec") + // https://www.w3.org/TR/css-values-4/#calc-constants + // "These keywords are only usable within a calculation" + // "If used outside of a calculation, they’re treated like any other keyword" + None } CalcValue::Sum(_) => { - unreachable!("CalcValue::Sum cannot be transformed into a ComponentValue") + // Do nothing, we cannot transform a CalcSum into a ComponentValue + None } } } diff --git a/crates/swc_css_minifier/src/compressor/media.rs b/crates/swc_css_minifier/src/compressor/media.rs index aece0afa753c..1d9a2d1b9684 100644 --- a/crates/swc_css_minifier/src/compressor/media.rs +++ b/crates/swc_css_minifier/src/compressor/media.rs @@ -339,46 +339,30 @@ impl Compressor { ComponentValue::CalcSum(CalcSum { expressions: calc_sum_expressions, .. - }) if calc_sum_expressions.len() == 1 => { - match &calc_sum_expressions[0] { - CalcProductOrOperator::Product(CalcProduct { - expressions: calc_product_expressions, - .. - }) if calc_product_expressions.len() == 1 => { - match &calc_product_expressions[0] { - CalcValueOrOperator::Value(CalcValue::Sum(_)) => { - // Do nothing, we cannot transform a - // CalcSum into a ComponentValue + }) if calc_sum_expressions.len() == 1 => match &calc_sum_expressions[0] { + CalcProductOrOperator::Product(CalcProduct { + expressions: calc_product_expressions, + .. + }) if calc_product_expressions.len() == 1 => { + if let CalcValueOrOperator::Value(calc_value) = + &calc_product_expressions[0] + { + match transform_calc_value_into_component_value(calc_value) { + Some(ComponentValue::Function(function)) => { + *n = MediaFeatureValue::Function(function); } - CalcValueOrOperator::Value(CalcValue::Constant(_)) => { - // https://www.w3.org/TR/css-values-4/#calc-constants - // "These keywords are only usable - // within a calculation" - // "If used outside of a calculation, - // they’re treated like any other - // keyword" + Some(ComponentValue::Dimension(dimension)) => { + *n = MediaFeatureValue::Dimension(dimension); } - CalcValueOrOperator::Value(calc_value) => { - match transform_calc_value_into_component_value(calc_value) - { - ComponentValue::Function(function) => { - *n = MediaFeatureValue::Function(function); - } - ComponentValue::Dimension(dimension) => { - *n = MediaFeatureValue::Dimension(dimension); - } - ComponentValue::Number(number) => { - *n = MediaFeatureValue::Number(number); - } - _ => {} - } + Some(ComponentValue::Number(number)) => { + *n = MediaFeatureValue::Number(number); } _ => {} } } - _ => {} } - } + _ => {} + }, _ => {} } } diff --git a/crates/swc_css_minifier/tests/fixture/compress-calc/container/output.min.css b/crates/swc_css_minifier/tests/fixture/compress-calc/container/output.min.css index 5ff4883d8fbf..c43b8ee658f7 100644 --- a/crates/swc_css_minifier/tests/fixture/compress-calc/container/output.min.css +++ b/crates/swc_css_minifier/tests/fixture/compress-calc/container/output.min.css @@ -1 +1 @@ -@container(inline-size>=0){h2{font-size:2cqw}}@container(inline-size>=0){h2{font-size:2cqh}}@container(inline-size>=0){h2{font-size:2cqi}}@container(inline-size>=0){h2{font-size:2cqb}}@container(inline-size>=0){h2{font-size:2cqmin}}@container(inline-size>=0){h2{font-size:2cqmax}}@container(inline-size>=200px){h2{font-size:2cqw}}@container(inline-size>=calc(200px)){h2{font-size:2cqw}} +@container(inline-size>=0){h2{font-size:2cqw}}@container(inline-size>=0){h2{font-size:2cqh}}@container(inline-size>=0){h2{font-size:2cqi}}@container(inline-size>=0){h2{font-size:2cqb}}@container(inline-size>=0){h2{font-size:2cqmin}}@container(inline-size>=0){h2{font-size:2cqmax}}@container(inline-size>=200px){h2{font-size:2cqw}}@container(inline-size>=200px){h2{font-size:2cqw}} diff --git a/crates/swc_css_minifier/tests/fixture/compress-calc/css-variables/output.min.css b/crates/swc_css_minifier/tests/fixture/compress-calc/css-variables/output.min.css index 0b5b3235e34f..b6ebcde49062 100644 --- a/crates/swc_css_minifier/tests/fixture/compress-calc/css-variables/output.min.css +++ b/crates/swc_css_minifier/tests/fixture/compress-calc/css-variables/output.min.css @@ -1 +1 @@ -.class1{width:calc(var(--mouseX)*1px)}.class2{width:calc(10px - 100px*var(--mouseX))}.class3{width:calc(-90px - var(--mouseX))}.class4{width:calc(10px - 100px/var(--mouseX))}.class5{width:calc(-90px + var(--mouseX))}.class6{width:calc(var(--popupHeight)/2)}.class7{width:calc(var(--popupHeight)/2 + var(--popupWidth)/2)}.class8{--foo:calc(var(--bar) / 8)}.class9{transform:translatey(calc(-100% - var(--tooltip-calculated-offset)))}.class10{width:calc(var(--xxx,var(--yyy))/2)}.class11{width:var(--foo)}.class12{width:calc(var(--foo))}.class13{width:calc(var(--foo) + 10px)}.class14{width:calc(var(--foo) + var(--bar))}.class15{width:calc(calc(var(--foo) + var(--bar)) + var(--baz))}.class16{width:calc(var(--foo) + calc(var(--bar) + var(--baz)))}.class17{width:calc(calc(var(--foo) - var(--bar)) - var(--baz))}.class18{width:calc(var(--foo) - calc(var(--bar) - var(--baz)))}.class19{width:calc(calc(var(--foo) + var(--bar)) - var(--baz))}.class20{width:calc(var(--foo) + calc(var(--bar) - var(--baz)))}.class21{width:calc(var(--foo) - calc(var(--bar) + var(--baz)))}.class22{width:calc(calc(var(--foo) + var(--bar))*var(--baz))}.class23{width:calc(var(--foo)*calc(var(--bar) + var(--baz)))}.class24{width:calc(calc(var(--foo) + var(--bar))/var(--baz))}.class25{width:calc(var(--foo)/calc(var(--bar) + var(--baz)))} +.class1{width:calc(var(--mouseX)*1px)}.class2{width:calc(10px - 100px*var(--mouseX))}.class3{width:calc(-90px - var(--mouseX))}.class4{width:calc(10px - 100px/var(--mouseX))}.class5{width:calc(-90px + var(--mouseX))}.class6{width:calc(var(--popupHeight)/2)}.class7{width:calc(var(--popupHeight)/2 + var(--popupWidth)/2)}.class8{--foo:calc(var(--bar) / 8)}.class9{transform:translatey(calc(-100% - var(--tooltip-calculated-offset)))}.class10{width:calc(var(--xxx,var(--yyy))/2)}.class11{width:var(--foo)}.class12{width:var(--foo)}.class13{width:calc(var(--foo) + 10px)}.class14{width:calc(var(--foo) + var(--bar))}.class15{width:calc(var(--foo) + var(--bar) + var(--baz))}.class16{width:calc(var(--foo) + var(--bar) + var(--baz))}.class17{width:calc(var(--foo) - var(--bar) - var(--baz))}.class18{width:calc(var(--foo) - var(--bar) + var(--baz))}.class19{width:calc(var(--foo) + var(--bar) - var(--baz))}.class20{width:calc(var(--foo) + var(--bar) - var(--baz))}.class21{width:calc(var(--foo) - var(--bar) - var(--baz))}.class22{width:calc(calc(var(--foo) + var(--bar))*var(--baz))}.class23{width:calc(var(--foo)*calc(var(--bar) + var(--baz)))}.class24{width:calc(calc(var(--foo) + var(--bar))/var(--baz))}.class25{width:calc(var(--foo)/calc(var(--bar) + var(--baz)))} diff --git a/crates/swc_css_minifier/tests/fixture/compress-calc/discard-zero/output.min.css b/crates/swc_css_minifier/tests/fixture/compress-calc/discard-zero/output.min.css index bda0b82559ad..9e546ff34347 100644 --- a/crates/swc_css_minifier/tests/fixture/compress-calc/discard-zero/output.min.css +++ b/crates/swc_css_minifier/tests/fixture/compress-calc/discard-zero/output.min.css @@ -1 +1 @@ -.class1{width:calc(100vw/2 - 6px)}.class2{width:500px}.class3{width:calc(0 - 10px)}.class4{width:calc(0 - calc(1px + 1em))}.class5{width:calc(0 - (100vw - 10px)/2)}.class6{width:calc(10px - 100vw)}.class7{width:calc(0px - (100vw - 10px)*2)}.class8{width:calc(-10px - 100vw)}.class9{width:calc(0px - var(--foo,4px)/2)} +.class1{width:calc(100vw/2 - 6px)}.class2{width:500px}.class3{width:calc(0 - 10px)}.class4{width:calc(0 - 1px - 1em)}.class5{width:calc(0 - (100vw - 10px)/2)}.class6{width:calc(10px - 100vw)}.class7{width:calc(0px - (100vw - 10px)*2)}.class8{width:calc(-10px - 100vw)}.class9{width:calc(0px - var(--foo,4px)/2)} diff --git a/crates/swc_css_minifier/tests/fixture/compress-calc/media-query/output.min.css b/crates/swc_css_minifier/tests/fixture/compress-calc/media-query/output.min.css index 8df8ea53fa00..af33c88635ef 100644 --- a/crates/swc_css_minifier/tests/fixture/compress-calc/media-query/output.min.css +++ b/crates/swc_css_minifier/tests/fixture/compress-calc/media-query/output.min.css @@ -1 +1 @@ -@media(min-width:20px){.class1{color:red}}@media(min-width:calc(20px)){.class1{color:red}}@media(color:1){.class1{color:red}}@media(min-width:0){.class1{color:red}}@media(min-width:0){.class1{color:red}} +@media(min-width:20px){.class1{color:red}}@media(min-width:20px){.class1{color:red}}@media(color:1){.class1{color:red}}@media(min-width:0){.class1{color:red}}@media(min-width:0){.class1{color:red}} diff --git a/crates/swc_css_minifier/tests/fixture/compress-calc/nested-calc/output.min.css b/crates/swc_css_minifier/tests/fixture/compress-calc/nested-calc/output.min.css index 2a6a8aaf287c..a5f3a6d6a7b5 100644 --- a/crates/swc_css_minifier/tests/fixture/compress-calc/nested-calc/output.min.css +++ b/crates/swc_css_minifier/tests/fixture/compress-calc/nested-calc/output.min.css @@ -1 +1 @@ -.class1{width:calc(100% - calc(50% + 25px))}.class2{width:calc(1px + calc(2px/2))}.class3{width:calc((1em - calc(10px + 1em))/2)}.class4{width:calc(calc(2.25rem + 2px) - 2px)}.class5{width:calc(100vh - 5rem - calc(10rem + 100px))}.class6{width:calc(100% - calc(10px + 2vw))}.class7{width:calc(100% - calc(10px - 2vw))}.class8{width:calc(100px + calc(200px))} +.class1{width:calc(50% - 25px)}.class2{width:calc(1px + 2px/2)}.class3{width:calc((0em - 10px)/2)}.class4{width:calc(2.25rem - 0px)}.class5{width:calc(100vh - 15rem - 100px)}.class6{width:calc(100% - 10px - 2vw)}.class7{width:calc(100% - 10px + 2vw)}.class8{width:300px} diff --git a/crates/swc_css_minifier/tests/fixture/compress-calc/simple-calc/output.min.css b/crates/swc_css_minifier/tests/fixture/compress-calc/simple-calc/output.min.css index b7ead97c203a..191f384b477e 100644 --- a/crates/swc_css_minifier/tests/fixture/compress-calc/simple-calc/output.min.css +++ b/crates/swc_css_minifier/tests/fixture/compress-calc/simple-calc/output.min.css @@ -1 +1 @@ -.class1{width:2px}.class2{width:2px;height:5px}.class3{width:1.5rem}.class4{width:2em}.class5{width:calc(2ex/2)}.class6{width:60px}.class7{width:calc(-0px + 100%)}.class8{width:calc(200px - 100%)}.class9{width:2px}.class10{width:2px}.class11{width:3rem}.class12{width:calc(100% + 1px)}.class13{width:calc(2rem - .14285em)}@supports(width:calc(100% - constant(safe-area-inset-left))){.class14{width:calc(100% - constant(safe-area-inset-left))}}.class15{width:calc(100% + 1163.5px - 75.37%)}.class16{width:calc(((100% + 123.5px)/.7537 - 100vw + 60px)/2 + 30px)}.class17{width:calc(75.37% - 763.5px)}.class18{width:calc(1163.5px - 10%)}.class19{width:calc((1em - calc(10px + 1em))/2)}.class20{width:200px}.class21{width:0}.class22{width:200px}.class23{width:calc(200px/1)}.class24{width:-200px}.class25{width:0}.class26{width:-200px}.class27{width:calc(200px/-1)}.class28{width:200px}.class29{width:200px}.class30{width:200px}.class31{width:22px}.class32{width:200px}.class33{width:22e9px}.class34{width:90px}.class35{width:100%}.class36{width:22px}.class37{width:calc(calc(200px))} +.class1{width:2px}.class2{width:2px;height:5px}.class3{width:1.5rem}.class4{width:2em}.class5{width:calc(2ex/2)}.class6{width:60px}.class7{width:calc(-0px + 100%)}.class8{width:calc(200px - 100%)}.class9{width:2px}.class10{width:2px}.class11{width:3rem}.class12{width:calc(100% + 1px)}.class13{width:calc(2rem - .14285em)}@supports(width:calc(100% - constant(safe-area-inset-left))){.class14{width:calc(100% - constant(safe-area-inset-left))}}.class15{width:calc(100% + 1163.5px - 75.37%)}.class16{width:calc(((100% + 123.5px)/.7537 - 100vw + 60px)/2 + 30px)}.class17{width:calc(75.37% - 763.5px)}.class18{width:calc(1163.5px - 10%)}.class19{width:calc((0em - 10px)/2)}.class20{width:200px}.class21{width:0}.class22{width:200px}.class23{width:calc(200px/1)}.class24{width:-200px}.class25{width:0}.class26{width:-200px}.class27{width:calc(200px/-1)}.class28{width:200px}.class29{width:200px}.class30{width:200px}.class31{width:22px}.class32{width:200px}.class33{width:22e9px}.class34{width:90px}.class35{width:100%}.class36{width:22px}.class37{width:200px} diff --git a/crates/swc_css_minifier/tests/fixture/compress-calc/supports-condition/output.min.css b/crates/swc_css_minifier/tests/fixture/compress-calc/supports-condition/output.min.css index 770ea3ba3f27..734301b38f9e 100644 --- a/crates/swc_css_minifier/tests/fixture/compress-calc/supports-condition/output.min.css +++ b/crates/swc_css_minifier/tests/fixture/compress-calc/supports-condition/output.min.css @@ -1 +1 @@ -@supports(width:calc(200px)){div{background:red}}@supports(width:calc(calc(200px))){div{background:red}}@supports(width:calc(0px)){div{background:red}}@supports(width:calc(0px)){div{background:red}} +@supports(width:200px){div{background:red}}@supports(width:200px){div{background:red}}@supports(width:0){div{background:red}}@supports(width:0){div{background:red}} diff --git a/crates/swc_css_minifier/tests/fixture/compress-calc/vendor/output.min.css b/crates/swc_css_minifier/tests/fixture/compress-calc/vendor/output.min.css index 974c27561dce..bc72d4c00841 100644 --- a/crates/swc_css_minifier/tests/fixture/compress-calc/vendor/output.min.css +++ b/crates/swc_css_minifier/tests/fixture/compress-calc/vendor/output.min.css @@ -1 +1 @@ -.class1{width:2px}.class2{width:2px}.class3{width:-webkit-calc(100% - -webkit-calc(50% + 25px))}.class4{width:-webkit-calc(1px + -webkit-calc(2px/2))}.class5{width:2px}.class6{width:2px} +.class1{width:2px}.class2{width:2px}.class3{width:-webkit-calc(50% - 25px)}.class4{width:-webkit-calc(1px + 2px/2)}.class5{width:2px}.class6{width:2px}