feat(css/minifier): Handle nested calc() (#6153)

This commit is contained in:
Vincent Ricard 2022-10-17 14:08:43 +02:00 committed by GitHub
parent 30f3de2fe2
commit d4a733d764
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 100 additions and 130 deletions

View File

@ -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,
// theyre 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;
}
}
_ => {}
}
}
_ => {}
},
_ => {}
}
}

View File

@ -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,
// theyre 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);
}
_ => {}
}
}
_ => {}
}
}
_ => {}
},
_ => {}
}
}

View File

@ -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<ComponentValue> {
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, theyre 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
}
}
}

View File

@ -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,
// theyre 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);
}
_ => {}
}
}
_ => {}
}
}
_ => {}
},
_ => {}
}
}

View File

@ -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}}

View File

@ -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)))}

View File

@ -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)}

View File

@ -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}}

View File

@ -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}

View File

@ -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}

View File

@ -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}}

View File

@ -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}