From 305e72e67297fabefb5124922e52b15522496467 Mon Sep 17 00:00:00 2001 From: magic-akari Date: Thu, 7 Dec 2023 08:36:41 +0800 Subject: [PATCH] refactor(css/minifier): Support stable rust (#8389) **Related issue:** - #8316 --- .../src/compressor/alpha_value.rs | 9 +- .../swc_css_minifier/src/compressor/angle.rs | 34 +- .../src/compressor/calc_sum.rs | 37 +- .../swc_css_minifier/src/compressor/color.rs | 114 ++-- .../src/compressor/container.rs | 45 +- .../src/compressor/declaration.rs | 506 +++++++----------- .../src/compressor/easing_function.rs | 157 +++--- .../swc_css_minifier/src/compressor/length.rs | 20 +- .../swc_css_minifier/src/compressor/media.rs | 52 +- crates/swc_css_minifier/src/compressor/mod.rs | 24 +- .../swc_css_minifier/src/compressor/rules.rs | 161 +++--- .../src/compressor/transform_function.rs | 466 ++++++---------- crates/swc_css_minifier/src/lib.rs | 1 - 13 files changed, 698 insertions(+), 928 deletions(-) diff --git a/crates/swc_css_minifier/src/compressor/alpha_value.rs b/crates/swc_css_minifier/src/compressor/alpha_value.rs index 6caeda8961d5..e3f018eaf16b 100644 --- a/crates/swc_css_minifier/src/compressor/alpha_value.rs +++ b/crates/swc_css_minifier/src/compressor/alpha_value.rs @@ -48,14 +48,11 @@ impl Compressor { } match component_value { - ComponentValue::Percentage(box Percentage { - span, - value: number, - }) if number.value % 10.0 == 0.0 => { - let new_value = number.value / 100.0; + ComponentValue::Percentage(percentage) if percentage.value.value % 10.0 == 0.0 => { + let new_value = percentage.value.value / 100.0; *component_value = ComponentValue::Number(Box::new(Number { - span: *span, + span: percentage.span, value: new_value, raw: None, })); diff --git a/crates/swc_css_minifier/src/compressor/angle.rs b/crates/swc_css_minifier/src/compressor/angle.rs index 7033571624b8..e506cd5c3cfe 100644 --- a/crates/swc_css_minifier/src/compressor/angle.rs +++ b/crates/swc_css_minifier/src/compressor/angle.rs @@ -8,25 +8,21 @@ impl Compressor { &mut self, component_value: &mut ComponentValue, ) { - if self.ctx.in_transform_function { - match &component_value { - ComponentValue::Dimension(box Dimension::Angle(Angle { - value: - Number { - value: number_value, - .. - }, - span, - .. - })) if *number_value == 0.0 => { - *component_value = ComponentValue::Number(Box::new(Number { - span: *span, - value: 0.0, - raw: None, - })); - } - _ => {} - } + if !self.ctx.in_transform_function { + return; + } + + if let Some(span) = component_value + .as_dimension() + .and_then(|dimension| dimension.as_angle()) + .filter(|angle| angle.value.value == 0.0) + .map(|angle| angle.span) + { + *component_value = ComponentValue::Number(Box::new(Number { + span, + value: 0.0, + raw: None, + })); } } diff --git a/crates/swc_css_minifier/src/compressor/calc_sum.rs b/crates/swc_css_minifier/src/compressor/calc_sum.rs index a60e7142033b..83b2c5098f6b 100644 --- a/crates/swc_css_minifier/src/compressor/calc_sum.rs +++ b/crates/swc_css_minifier/src/compressor/calc_sum.rs @@ -1177,30 +1177,29 @@ impl Compressor { match &component_value { // Transform "calc(calc-sum)" into "simple value" when calc-sum is not a complex // expression - ComponentValue::Function(box Function { name, value, .. }) - if is_calc_function_name(name) && value.len() == 1 => + ComponentValue::Function(function) + if is_calc_function_name(&function.name) && function.value.len() == 1 => { - match &value[0] { - ComponentValue::CalcSum(box 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 => { - if let CalcValueOrOperator::Value(calc_value) = - &calc_product_expressions[0] - { - if let Some(cv) = - transform_calc_value_into_component_value(calc_value) + match &function.value[0] { + ComponentValue::CalcSum(calc_sum) 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] { - *component_value = cv; + if let Some(cv) = + transform_calc_value_into_component_value(calc_value) + { + *component_value = cv; + } } } + _ => {} } - _ => {} - }, + } _ => {} } } diff --git a/crates/swc_css_minifier/src/compressor/color.rs b/crates/swc_css_minifier/src/compressor/color.rs index 072992f4b08d..e611314a9533 100644 --- a/crates/swc_css_minifier/src/compressor/color.rs +++ b/crates/swc_css_minifier/src/compressor/color.rs @@ -224,42 +224,43 @@ impl Compressor { } fn get_alpha_value(&self, alpha_value: Option<&&ComponentValue>) -> Option { - match alpha_value { - Some(ComponentValue::AlphaValue(box AlphaValue::Number(Number { value, .. }))) => { - if *value > 1.0 { - return Some(1.0); - } else if *value < 0.0 { - return Some(0.0); - } + let Some(alpha_value) = alpha_value else { + return Some(1.0); + }; - Some(*value) - } - Some(ComponentValue::AlphaValue(box AlphaValue::Percentage(Percentage { - value: Number { value, .. }, - .. - }))) => { - if *value > 100.0 { - return Some(1.0); - } else if *value < 0.0 { - return Some(0.0); + match &alpha_value { + ComponentValue::AlphaValue(alpha_value) => match &**alpha_value { + AlphaValue::Number(Number { value, .. }) => { + if *value > 1.0 { + return Some(1.0); + } else if *value < 0.0 { + return Some(0.0); + } + + Some(*value) } + AlphaValue::Percentage(Percentage { + value: Number { value, .. }, + .. + }) => { + if *value > 100.0 { + return Some(1.0); + } else if *value < 0.0 { + return Some(0.0); + } - Some(*value / 100.0) - } - Some(ComponentValue::Ident(box Ident { value, .. })) - if value.eq_ignore_ascii_case("none") => - { - Some(0.0) - } - None => Some(1.0), + Some(*value / 100.0) + } + }, + ComponentValue::Ident(ident) if ident.value.eq_ignore_ascii_case("none") => Some(0.0), _ => None, } } fn get_hue(&self, hue: Option<&&ComponentValue>) -> Option { match hue { - Some(ComponentValue::Hue(box hue)) => { - let mut value = match hue { + Some(ComponentValue::Hue(hue)) => { + let mut value = match &**hue { Hue::Number(Number { value, .. }) => *value, Hue::Angle(Angle { value: Number { value, .. }, @@ -276,9 +277,7 @@ impl Compressor { Some(value) } - Some(ComponentValue::Ident(box Ident { value, .. })) - if value.eq_ignore_ascii_case("none") => - { + Some(ComponentValue::Ident(ident)) if ident.value.eq_ignore_ascii_case("none") => { Some(0.0) } _ => None, @@ -287,10 +286,8 @@ impl Compressor { fn get_percentage(&self, percentage: Option<&&ComponentValue>) -> Option { match percentage { - Some(ComponentValue::Percentage(box Percentage { - value: Number { value, .. }, - .. - })) => { + Some(ComponentValue::Percentage(percentage)) => { + let Number { value, .. } = &percentage.value; if *value > 100.0 { return Some(1.0); } else if *value < 0.0 { @@ -299,9 +296,7 @@ impl Compressor { Some(*value / 100.0) } - Some(ComponentValue::Ident(box Ident { value, .. })) - if value.eq_ignore_ascii_case("none") => - { + Some(ComponentValue::Ident(ident)) if ident.value.eq_ignore_ascii_case("none") => { Some(0.0) } _ => None, @@ -313,30 +308,25 @@ impl Compressor { number_or_percentage: Option<&&ComponentValue>, ) -> Option { match number_or_percentage { - Some(ComponentValue::Number(box Number { value, .. })) => { - if *value > 255.0 { + Some(ComponentValue::Number(number)) => { + if number.value > 255.0 { return Some(255.0); - } else if *value < 0.0 { + } else if number.value < 0.0 { return Some(0.0); } - Some(*value) + Some(number.value) } - Some(ComponentValue::Percentage(box Percentage { - value: Number { value, .. }, - .. - })) => { - if *value > 100.0 { + Some(ComponentValue::Percentage(percentage)) => { + if percentage.value.value > 100.0 { return Some(255.0); - } else if *value < 0.0 { + } else if percentage.value.value < 0.0 { return Some(0.0); } - Some((2.55 * *value).round()) + Some((2.55 * percentage.value.value).round()) } - Some(ComponentValue::Ident(box Ident { value, .. })) - if value.eq_ignore_ascii_case("none") => - { + Some(ComponentValue::Ident(ident)) if ident.value.eq_ignore_ascii_case("none") => { Some(0.0) } _ => None, @@ -391,13 +381,10 @@ impl Compressor { let rgba: Vec<_> = value .iter() .filter(|n| { - !matches!( - n, - ComponentValue::Delimiter(box Delimiter { - value: DelimiterValue::Comma | DelimiterValue::Solidus, - .. - }) - ) + !n.as_delimiter() + .map(|delimiter| delimiter.value) + .map(|v| matches!(v, DelimiterValue::Comma | DelimiterValue::Solidus)) + .unwrap_or_default() }) .collect(); @@ -429,13 +416,10 @@ impl Compressor { let hsla: Vec<_> = value .iter() .filter(|n| { - !matches!( - n, - ComponentValue::Delimiter(box Delimiter { - value: DelimiterValue::Comma | DelimiterValue::Solidus, - .. - }) - ) + !n.as_delimiter() + .map(|delimiter| delimiter.value) + .map(|v| matches!(v, DelimiterValue::Comma | DelimiterValue::Solidus)) + .unwrap_or_default() }) .collect(); diff --git a/crates/swc_css_minifier/src/compressor/container.rs b/crates/swc_css_minifier/src/compressor/container.rs index 045fcd1f7359..a6f553c689c8 100644 --- a/crates/swc_css_minifier/src/compressor/container.rs +++ b/crates/swc_css_minifier/src/compressor/container.rs @@ -10,33 +10,32 @@ impl Compressor { if is_calc_function_name(name) && value.len() == 1 => { match &value[0] { - ComponentValue::CalcSum(box 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 => { - 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); + ComponentValue::CalcSum(calc_sum) 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); + } + Some(ComponentValue::Dimension(dimension)) => { + *n = SizeFeatureValue::Dimension(*dimension); + } + Some(ComponentValue::Number(number)) => { + *n = SizeFeatureValue::Number(*number); + } + _ => {} } - Some(ComponentValue::Dimension(dimension)) => { - *n = SizeFeatureValue::Dimension(*dimension); - } - Some(ComponentValue::Number(number)) => { - *n = SizeFeatureValue::Number(*number); - } - _ => {} } } + _ => {} } - _ => {} - }, + } _ => {} } } diff --git a/crates/swc_css_minifier/src/compressor/declaration.rs b/crates/swc_css_minifier/src/compressor/declaration.rs index cc37644eb80e..908f751932bc 100644 --- a/crates/swc_css_minifier/src/compressor/declaration.rs +++ b/crates/swc_css_minifier/src/compressor/declaration.rs @@ -14,16 +14,19 @@ impl Compressor { for value in declaration.value.iter() { match value { - outside_node @ ComponentValue::Ident(box Ident { value, .. }) + outside_node @ ComponentValue::Ident(ident) if matches_eq_ignore_ascii_case!( - value, "block", "inline", "run-in" + ident.value, + "block", + "inline", + "run-in" ) => { outside = Some(outside_node); } - inside_node @ ComponentValue::Ident(box Ident { value, .. }) + inside_node @ ComponentValue::Ident(ident) if matches_eq_ignore_ascii_case!( - value, + ident.value, "flow", "flow-root", "table", @@ -34,12 +37,15 @@ impl Compressor { { inside = Some(inside_node); } - list_item_node @ ComponentValue::Ident(box Ident { value, .. }) - if value.eq_ignore_ascii_case("list-item") => + list_item_node @ ComponentValue::Ident(ident) + if ident.value.eq_ignore_ascii_case("list-item") => { - if let Some(ComponentValue::Ident(box Ident { value, .. })) = inside - { - if !matches_eq_ignore_ascii_case!(value, "flow", "flow-root") { + if let Some(ComponentValue::Ident(ident)) = inside { + if !matches_eq_ignore_ascii_case!( + ident.value, + "flow", + "flow-root" + ) { continue; } } @@ -54,108 +60,64 @@ impl Compressor { // `block flow` -> `block` // `inline flow` -> `inline` // `run-in flow` -> `run-in` - ( - Some(outside), - Some(ComponentValue::Ident(box Ident { - value: inside_value, - .. - })), - None, - ) if inside_value.eq_ignore_ascii_case("flow") => { + (Some(outside), Some(ComponentValue::Ident(inside_ident)), None) + if inside_ident.value.eq_ignore_ascii_case("flow") => + { declaration.value = vec![outside.clone()]; } // `block flow-root` -> `flow-root` ( - Some(ComponentValue::Ident(box Ident { - value: outside_value, - .. - })), - Some( - inside @ ComponentValue::Ident(box Ident { - value: inside_value, - .. - }), - ), + Some(ComponentValue::Ident(outside_ident)), + Some(inside @ ComponentValue::Ident(inside_ident)), None, - ) if outside_value.eq_ignore_ascii_case("block") - && inside_value.eq_ignore_ascii_case("flow-root") => + ) if outside_ident.value.eq_ignore_ascii_case("block") + && inside_ident.value.eq_ignore_ascii_case("flow-root") => { declaration.value = vec![inside.clone()]; } // `inline flow-root` -> `inline-block` ( - Some(ComponentValue::Ident(box Ident { - value: outside_value, - span, - .. - })), - Some(ComponentValue::Ident(box Ident { - value: inside_value, - .. - })), + Some(ComponentValue::Ident(outside_ident)), + Some(ComponentValue::Ident(inside_ident)), None, - ) if outside_value.eq_ignore_ascii_case("inline") - && inside_value.eq_ignore_ascii_case("flow-root") => + ) if outside_ident.value.eq_ignore_ascii_case("inline") + && inside_ident.value.eq_ignore_ascii_case("flow-root") => { declaration.value = vec![ComponentValue::Ident(Box::new(Ident { - span: *span, + span: outside_ident.span, value: "inline-block".into(), raw: None, }))]; } // `block flow list-item` -> `list-item` ( - Some(ComponentValue::Ident(box Ident { - value: outside_value, - .. - })), - Some(ComponentValue::Ident(box Ident { - value: inside_value, - .. - })), + Some(ComponentValue::Ident(outside_ident)), + Some(ComponentValue::Ident(inside_ident)), Some(list_item), - ) if outside_value.eq_ignore_ascii_case("block") - && inside_value.eq_ignore_ascii_case("flow") => + ) if outside_ident.value.eq_ignore_ascii_case("block") + && inside_ident.value.eq_ignore_ascii_case("flow") => { declaration.value = vec![list_item.clone()]; } // `block list-item` -> `list-item` - ( - Some(ComponentValue::Ident(box Ident { - value: outside_value, - .. - })), - None, - Some(list_item), - ) if outside_value.eq_ignore_ascii_case("block") => { + (Some(ComponentValue::Ident(outside_ident)), None, Some(list_item)) + if outside_ident.value.eq_ignore_ascii_case("block") => + { declaration.value = vec![list_item.clone()]; } // `flow list-item` -> `list-item` - ( - None, - Some(ComponentValue::Ident(box Ident { - value: inside_value, - .. - })), - Some(list_item), - ) if inside_value.eq_ignore_ascii_case("flow") => { + (None, Some(ComponentValue::Ident(inside_ident)), Some(list_item)) + if inside_ident.value.eq_ignore_ascii_case("flow") => + { declaration.value = vec![list_item.clone()]; } // `inline flow list-item` -> `inline list-item` ( - Some( - outside @ ComponentValue::Ident(box Ident { - value: outside_value, - .. - }), - ), - Some(ComponentValue::Ident(box Ident { - value: inside_value, - .. - })), + Some(outside @ ComponentValue::Ident(outside_ident)), + Some(ComponentValue::Ident(inside_ident)), Some(list_item), - ) if outside_value.eq_ignore_ascii_case("inline") - && inside_value.eq_ignore_ascii_case("flow") => + ) if outside_ident.value.eq_ignore_ascii_case("inline") + && inside_ident.value.eq_ignore_ascii_case("flow") => { declaration.value = vec![outside.clone(), list_item.clone()]; } @@ -163,20 +125,12 @@ impl Compressor { // `block grid` -> `grid` // `block table` -> `table` ( - Some(ComponentValue::Ident(box Ident { - value: outside_value, - .. - })), - Some( - inside @ ComponentValue::Ident(box Ident { - value: inside_value, - .. - }), - ), + Some(ComponentValue::Ident(outside_ident)), + Some(inside @ ComponentValue::Ident(inside_ident)), None, - ) if outside_value.eq_ignore_ascii_case("block") + ) if outside_ident.value.eq_ignore_ascii_case("block") && matches_eq_ignore_ascii_case!( - inside_value, + inside_ident.value, "flex", "grid", "table" @@ -186,19 +140,11 @@ impl Compressor { } // `inline ruby` -> `ruby` ( - Some(ComponentValue::Ident(box Ident { - value: outside_value, - .. - })), - Some( - inside @ ComponentValue::Ident(box Ident { - value: inside_value, - .. - }), - ), + Some(ComponentValue::Ident(outside_ident)), + Some(inside @ ComponentValue::Ident(inside_ident)), None, - ) if outside_value.eq_ignore_ascii_case("inline") - && inside_value.eq_ignore_ascii_case("ruby") => + ) if outside_ident.value.eq_ignore_ascii_case("inline") + && inside_ident.value.eq_ignore_ascii_case("ruby") => { declaration.value = vec![inside.clone()]; } @@ -330,20 +276,20 @@ impl Compressor { .take() .into_iter() .map(|node| match node { - ComponentValue::Ident(box Ident { value, span, .. }) - if value.eq_ignore_ascii_case("normal") => + ComponentValue::Ident(ident) + if ident.value.eq_ignore_ascii_case("normal") => { ComponentValue::Integer(Box::new(Integer { - span, + span: ident.span, value: 400, raw: None, })) } - ComponentValue::Ident(box Ident { value, span, .. }) - if value.eq_ignore_ascii_case("bold") => + ComponentValue::Ident(ident) + if ident.value.eq_ignore_ascii_case("bold") => { ComponentValue::Integer(Box::new(Integer { - span, + span: ident.span, value: 700, raw: None, })) @@ -359,31 +305,24 @@ impl Compressor { let second = declaration.value.get(1); if let ( - Some(ComponentValue::Ident(box Ident { - span, - value: first_value, - .. - })), - Some(ComponentValue::Ident(box Ident { - value: second_value, - .. - })), + Some(ComponentValue::Ident(first_ident)), + Some(ComponentValue::Ident(second_ident)), ) = (first, second) { match ( - &*first_value.to_ascii_lowercase(), - &*second_value.to_ascii_lowercase(), + &*first_ident.value.to_ascii_lowercase(), + &*second_ident.value.to_ascii_lowercase(), ) { ("repeat", "no-repeat") => { declaration.value = vec![ComponentValue::Ident(Box::new(Ident { - span: *span, + span: first_ident.span, value: "repeat-x".into(), raw: None, }))]; } ("no-repeat", "repeat") => { declaration.value = vec![ComponentValue::Ident(Box::new(Ident { - span: *span, + span: first_ident.span, value: "repeat-y".into(), raw: None, }))]; @@ -485,11 +424,9 @@ impl Compressor { _ => {} } - let is_initial = if let Some(ComponentValue::Ident(box Ident { value, span, .. })) = - declaration.value.first() - { - if value.eq_ignore_ascii_case("initial") { - Some(span) + let is_initial = if let Some(ComponentValue::Ident(ident)) = declaration.value.first() { + if ident.value.eq_ignore_ascii_case("initial") { + Some(ident.span) } else { None } @@ -498,7 +435,7 @@ impl Compressor { }; if let Some(span) = is_initial { - self.compress_from_initial(declaration, *span); + self.compress_from_initial(declaration, span); } // TODO `browserslist` support // else { @@ -512,33 +449,27 @@ impl Compressor { node_1: Option<&ComponentValue>, node_2: Option<&ComponentValue>, ) -> bool { + let Some(node_1) = node_1 else { return false }; + let Some(node_2) = node_2 else { return false }; + match (node_1, node_2) { - ( - Some(ComponentValue::Dimension(box Dimension::Length(Length { - value: value_1, - unit: unit_1, - .. - }))), - Some(ComponentValue::Dimension(box Dimension::Length(Length { - value: value_2, - unit: unit_2, - .. - }))), - ) if value_1.value == value_2.value && unit_1.value == unit_2.value => true, - ( - Some(ComponentValue::Integer(box Integer { value: 0, .. })), - Some(ComponentValue::Integer(box Integer { value: 0, .. })), - ) => true, - ( - Some(ComponentValue::Number(box Number { - value: first_number, - .. - })), - Some(ComponentValue::Number(box Number { - value: second_number, - .. - })), - ) if first_number == second_number => true, + (ComponentValue::Dimension(dimension_1), ComponentValue::Dimension(dimension_2)) => { + let result_1 = dimension_1 + .as_length() + .map(|length| (&length.value.value, &length.unit.value)); + + let result_2 = dimension_2 + .as_length() + .map(|length| (&length.value.value, &length.unit.value)); + + result_1.is_some() && result_1 == result_2 + } + (ComponentValue::Integer(integer_1), ComponentValue::Integer(integer_2)) => { + integer_1.value == 0 && integer_2.value == 0 + } + (ComponentValue::Number(number_1), ComponentValue::Number(number_2)) => { + number_1.value == number_2.value + } _ => false, } } @@ -548,37 +479,31 @@ impl Compressor { node_1: Option<&ComponentValue>, node_2: Option<&ComponentValue>, ) -> bool { + let Some(node_1) = node_1 else { return false }; + let Some(node_2) = node_2 else { return false }; + match (node_1, node_2) { + (ComponentValue::Dimension(dimension_1), ComponentValue::Dimension(dimension_2)) => { + let result_1 = dimension_1 + .as_length() + .map(|length| (&length.value.value, &length.unit.value)); + + let result_2 = dimension_2 + .as_length() + .map(|length| (&length.value.value, &length.unit.value)); + + result_1.is_some() && result_1 == result_2 + } ( - Some(ComponentValue::Dimension(box Dimension::Length(Length { - value: value_1, - unit: unit_1, - .. - }))), - Some(ComponentValue::Dimension(box Dimension::Length(Length { - value: value_2, - unit: unit_2, - .. - }))), - ) if value_1.value == value_2.value && unit_1.value == unit_2.value => true, - ( - Some(ComponentValue::Percentage(box Percentage { value: value_1, .. })), - Some(ComponentValue::Percentage(box Percentage { value: value_2, .. })), - ) if value_1.value == value_2.value => true, - ( - Some(ComponentValue::Integer(box Integer { value: 0, .. })), - Some(ComponentValue::Integer(box Integer { value: 0, .. })), - ) => true, - ( - Some(ComponentValue::Number(box Number { - value: first_number, - .. - })), - Some(ComponentValue::Number(box Number { - value: second_number, - .. - })), - ) if first_number == second_number => true, + ComponentValue::Percentage(percentage_1), + ComponentValue::Percentage(percentage_2), + ) => percentage_1.value.value == percentage_2.value.value, + (ComponentValue::Integer(integer_1), ComponentValue::Integer(integer_2)) => { + integer_1.value == 0 && integer_2.value == 0 + } + (ComponentValue::Number(number_1), ComponentValue::Number(number_2)) => { + number_1.value == number_2.value + } _ => false, } } @@ -588,10 +513,17 @@ impl Compressor { node_1: Option<&ComponentValue>, node_2: Option<&ComponentValue>, ) -> bool { - matches!((node_1, node_2), ( - Some(ComponentValue::Ident(box Ident { value: value_1, .. })), - Some(ComponentValue::Ident(box Ident { value: value_2, .. })), - ) if value_1.eq_ignore_ascii_case(value_2)) + let Some(node_1) = node_1 else { return false }; + let Some(node_2) = node_2 else { return false }; + + let Some(value_1) = node_1.as_ident().map(|ident| &ident.value) else { + return false; + }; + let Some(value_2) = node_2.as_ident().map(|ident| &ident.value) else { + return false; + }; + + value_1.eq_ignore_ascii_case(value_2) } fn compress_from_initial(&self, declaration: &mut Declaration, span: Span) { @@ -1269,12 +1201,10 @@ impl Compressor { match &**name { "background-clip" | "mask-clip" | "mask-origin" => { - if let Some(ComponentValue::Ident(box Ident { value, span, .. })) = - declaration.value.first() - { - if value.eq_ignore_ascii_case("border-box") { + if let Some(ComponentValue::Ident(ident)) = declaration.value.first() { + if ident.value.eq_ignore_ascii_case("border-box") { declaration.value = vec![ComponentValue::Ident(Box::new(Ident { - span: *span, + span: ident.span, value: "initial".into(), raw: None, }))]; @@ -1282,12 +1212,10 @@ impl Compressor { } } "background-color" => { - if let Some(ComponentValue::Ident(box Ident { value, span, .. })) = - declaration.value.first() - { - if value.eq_ignore_ascii_case("transparent") { + if let Some(ComponentValue::Ident(ident)) = declaration.value.first() { + if ident.value.eq_ignore_ascii_case("transparent") { declaration.value = vec![ComponentValue::Ident(Box::new(Ident { - span: *span, + span: ident.span, value: "initial".into(), raw: None, }))]; @@ -1295,12 +1223,10 @@ impl Compressor { } } "background-origin" => { - if let Some(ComponentValue::Ident(box Ident { value, span, .. })) = - declaration.value.first() - { - if value.eq_ignore_ascii_case("padding-box") { + if let Some(ComponentValue::Ident(ident)) = declaration.value.first() { + if ident.value.eq_ignore_ascii_case("padding-box") { declaration.value = vec![ComponentValue::Ident(Box::new(Ident { - span: *span, + span: ident.span, value: "initial".into(), raw: None, }))]; @@ -1308,19 +1234,15 @@ impl Compressor { } } "background-size" => { - if let ( - Some(ComponentValue::Ident(box Ident { - value: first, span, .. - })), - Some(ComponentValue::Ident(box Ident { value: second, .. })), - ) = (declaration.value.first(), declaration.value.get(1)) + if let (Some(ComponentValue::Ident(first)), Some(ComponentValue::Ident(second))) = + (declaration.value.first(), declaration.value.get(1)) { - if first.eq_ignore_ascii_case("auto") - && second.eq_ignore_ascii_case("auto") + if first.value.eq_ignore_ascii_case("auto") + && second.value.eq_ignore_ascii_case("auto") && declaration.value.len() == 2 { declaration.value = vec![ComponentValue::Ident(Box::new(Ident { - span: *span, + span: first.span, value: "initial".into(), raw: None, }))]; @@ -1340,12 +1262,10 @@ impl Compressor { | "column-rule-color" | "text-emphasis-color" | "text-decoration-color" => { - if let Some(ComponentValue::Ident(box Ident { value, span, .. })) = - declaration.value.first() - { - if value.eq_ignore_ascii_case("currentcolor") { + if let Some(ComponentValue::Ident(ident)) = declaration.value.first() { + if ident.value.eq_ignore_ascii_case("currentcolor") { declaration.value = vec![ComponentValue::Ident(Box::new(Ident { - span: *span, + span: ident.span, value: "initial".into(), raw: None, }))]; @@ -1353,12 +1273,10 @@ impl Compressor { } } "border-collapse" => { - if let Some(ComponentValue::Ident(box Ident { value, span, .. })) = - declaration.value.first() - { - if value.eq_ignore_ascii_case("separate") { + if let Some(ComponentValue::Ident(ident)) = declaration.value.first() { + if ident.value.eq_ignore_ascii_case("separate") { declaration.value = vec![ComponentValue::Ident(Box::new(Ident { - span: *span, + span: ident.span, value: "initial".into(), raw: None, }))]; @@ -1366,12 +1284,10 @@ impl Compressor { } } "box-sizing" => { - if let Some(ComponentValue::Ident(box Ident { value, span, .. })) = - declaration.value.first() - { - if value.eq_ignore_ascii_case("content-box") { + if let Some(ComponentValue::Ident(ident)) = declaration.value.first() { + if ident.value.eq_ignore_ascii_case("content-box") { declaration.value = vec![ComponentValue::Ident(Box::new(Ident { - span: *span, + span: ident.span, value: "initial".into(), raw: None, }))]; @@ -1379,12 +1295,10 @@ impl Compressor { } } "color" => { - if let Some(ComponentValue::Ident(box Ident { value, span, .. })) = - declaration.value.first() - { - if value.eq_ignore_ascii_case("canvastext") { + if let Some(ComponentValue::Ident(ident)) = declaration.value.first() { + if ident.value.eq_ignore_ascii_case("canvastext") { declaration.value = vec![ComponentValue::Ident(Box::new(Ident { - span: *span, + span: ident.span, value: "initial".into(), raw: None, }))]; @@ -1392,19 +1306,15 @@ impl Compressor { } } "font-synthesis" => { - if let ( - Some(ComponentValue::Ident(box Ident { - value: first, span, .. - })), - Some(ComponentValue::Ident(box Ident { value: second, .. })), - ) = (declaration.value.first(), declaration.value.get(1)) + if let (Some(ComponentValue::Ident(first)), Some(ComponentValue::Ident(second))) = + (declaration.value.first(), declaration.value.get(1)) { - if first.eq_ignore_ascii_case("weight") - && second.eq_ignore_ascii_case("style") + if first.value.eq_ignore_ascii_case("weight") + && second.value.eq_ignore_ascii_case("style") && declaration.value.len() == 2 { declaration.value = vec![ComponentValue::Ident(Box::new(Ident { - span: *span, + span: first.span, value: "initial".into(), raw: None, }))]; @@ -1412,12 +1322,10 @@ impl Compressor { } } "image-orientation" => { - if let Some(ComponentValue::Ident(box Ident { value, span, .. })) = - declaration.value.first() - { - if value.eq_ignore_ascii_case("from-image") { + if let Some(ComponentValue::Ident(ident)) = declaration.value.first() { + if ident.value.eq_ignore_ascii_case("from-image") { declaration.value = vec![ComponentValue::Ident(Box::new(Ident { - span: *span, + span: ident.span, value: "initial".into(), raw: None, }))]; @@ -1425,12 +1333,12 @@ impl Compressor { } } "mask-mode" => { - if let Some(ComponentValue::Ident(box Ident { value, span, .. })) = - declaration.value.first() - { - if value.eq_ignore_ascii_case("match-source") && declaration.value.len() == 1 { + if let Some(ComponentValue::Ident(ident)) = declaration.value.first() { + if ident.value.eq_ignore_ascii_case("match-source") + && declaration.value.len() == 1 + { declaration.value = vec![ComponentValue::Ident(Box::new(Ident { - span: *span, + span: ident.span, value: "initial".into(), raw: None, }))]; @@ -1438,12 +1346,10 @@ impl Compressor { } } "mask-type" => { - if let Some(ComponentValue::Ident(box Ident { value, span, .. })) = - declaration.value.first() - { - if value.eq_ignore_ascii_case("luminance") { + if let Some(ComponentValue::Ident(ident)) = declaration.value.first() { + if ident.value.eq_ignore_ascii_case("luminance") { declaration.value = vec![ComponentValue::Ident(Box::new(Ident { - span: *span, + span: ident.span, value: "initial".into(), raw: None, }))]; @@ -1451,12 +1357,10 @@ impl Compressor { } } "ruby-align" => { - if let Some(ComponentValue::Ident(box Ident { value, span, .. })) = - declaration.value.first() - { - if value.eq_ignore_ascii_case("space-around") { + if let Some(ComponentValue::Ident(ident)) = declaration.value.first() { + if ident.value.eq_ignore_ascii_case("space-around") { declaration.value = vec![ComponentValue::Ident(Box::new(Ident { - span: *span, + span: ident.span, value: "initial".into(), raw: None, }))]; @@ -1464,12 +1368,10 @@ impl Compressor { } } "ruby-merge" => { - if let Some(ComponentValue::Ident(box Ident { value, span, .. })) = - declaration.value.first() - { - if value.eq_ignore_ascii_case("separate") { + if let Some(ComponentValue::Ident(ident)) = declaration.value.first() { + if ident.value.eq_ignore_ascii_case("separate") { declaration.value = vec![ComponentValue::Ident(Box::new(Ident { - span: *span, + span: ident.span, value: "initial".into(), raw: None, }))]; @@ -1477,12 +1379,10 @@ impl Compressor { } } "ruby-position" => { - if let Some(ComponentValue::Ident(box Ident { value, span, .. })) = - declaration.value.first() - { - if value.eq_ignore_ascii_case("alternate") { + if let Some(ComponentValue::Ident(ident)) = declaration.value.first() { + if ident.value.eq_ignore_ascii_case("alternate") { declaration.value = vec![ComponentValue::Ident(Box::new(Ident { - span: *span, + span: ident.span, value: "initial".into(), raw: None, }))]; @@ -1490,16 +1390,14 @@ impl Compressor { } } "text-emphasis-position" => { - if let ( - Some(ComponentValue::Ident(box Ident { - value: first, span, .. - })), - Some(ComponentValue::Ident(box Ident { value: second, .. })), - ) = (declaration.value.first(), declaration.value.get(1)) + if let (Some(ComponentValue::Ident(first)), Some(ComponentValue::Ident(second))) = + (declaration.value.first(), declaration.value.get(1)) { - if first.eq_ignore_ascii_case("over") && second.eq_ignore_ascii_case("right") { + if first.value.eq_ignore_ascii_case("over") + && second.value.eq_ignore_ascii_case("right") + { declaration.value = vec![ComponentValue::Ident(Box::new(Ident { - span: *span, + span: first.span, value: "initial".into(), raw: None, }))]; @@ -1507,12 +1405,10 @@ impl Compressor { } } "transform-box" => { - if let Some(ComponentValue::Ident(box Ident { value, span, .. })) = - declaration.value.first() - { - if value.eq_ignore_ascii_case("view-box") { + if let Some(ComponentValue::Ident(ident)) = declaration.value.first() { + if ident.value.eq_ignore_ascii_case("view-box") { declaration.value = vec![ComponentValue::Ident(Box::new(Ident { - span: *span, + span: ident.span, value: "initial".into(), raw: None, }))]; @@ -1521,20 +1417,32 @@ impl Compressor { } "transform-origin" => { if let ( - Some(ComponentValue::Percentage(box Percentage { + Some(Percentage { value: Number { value: first, .. }, span, .. - })), - Some(ComponentValue::Percentage(box Percentage { + }), + Some(Percentage { value: Number { value: second, .. }, .. - })), - Some(ComponentValue::Integer(box Integer { value: third, .. })), + }), + Some(Integer { value: third, .. }), ) = ( - declaration.value.first(), - declaration.value.get(1), - declaration.value.get(2), + declaration + .value + .first() + .and_then(|x| x.as_percentage()) + .map(|x| x.as_ref()), + declaration + .value + .get(1) + .and_then(|x| x.as_percentage()) + .map(|x| x.as_ref()), + declaration + .value + .get(2) + .and_then(|x| x.as_integer()) + .map(|x| x.as_ref()), ) { if *first == 50.0 && *second == 50.0 @@ -1550,12 +1458,10 @@ impl Compressor { } } "vertical-align" => { - if let Some(ComponentValue::Ident(box Ident { value, span, .. })) = - declaration.value.first() - { - if value.eq_ignore_ascii_case("baseline") { + if let Some(ComponentValue::Ident(ident)) = declaration.value.first() { + if ident.value.eq_ignore_ascii_case("baseline") { declaration.value = vec![ComponentValue::Ident(Box::new(Ident { - span: *span, + span: ident.span, value: "initial".into(), raw: None, }))]; @@ -1563,12 +1469,10 @@ impl Compressor { } } "writing-mode" => { - if let Some(ComponentValue::Ident(box Ident { value, span, .. })) = - declaration.value.first() - { - if value.eq_ignore_ascii_case("horizontal-tb") { + if let Some(ComponentValue::Ident(ident)) = declaration.value.first() { + if ident.value.eq_ignore_ascii_case("horizontal-tb") { declaration.value = vec![ComponentValue::Ident(Box::new(Ident { - span: *span, + span: ident.span, value: "initial".into(), raw: None, }))]; diff --git a/crates/swc_css_minifier/src/compressor/easing_function.rs b/crates/swc_css_minifier/src/compressor/easing_function.rs index 13df11cf156f..ab2dd50549f0 100644 --- a/crates/swc_css_minifier/src/compressor/easing_function.rs +++ b/crates/swc_css_minifier/src/compressor/easing_function.rs @@ -5,129 +5,110 @@ use super::Compressor; impl Compressor { pub(super) fn compress_easing_function(&mut self, component_value: &mut ComponentValue) { match component_value { - ComponentValue::Function(box Function { - name, - value: function_value, - span, - }) if name == "cubic-bezier" && function_value.len() == 7 => { - if let ( - first, - second, - third, - ComponentValue::Integer(box Integer { value: fourth, .. }), - ) = ( - &function_value[0], - &function_value[2], - &function_value[4], - &function_value[6], + ComponentValue::Function(function) + if function.name == "cubic-bezier" && function.value.len() == 7 => + { + if let (first, second, third, ComponentValue::Integer(fourth)) = ( + &function.value[0], + &function.value[2], + &function.value[4], + &function.value[6], ) { - if matches!(first, ComponentValue::Integer(box Integer { value, .. }) if *value == 0) - && matches!(second, ComponentValue::Integer(box Integer { value, .. }) if *value == 0) - && matches!(third, ComponentValue::Integer(box Integer { value, .. }) if *value == 1) - && *fourth == 1 + if matches!(first, ComponentValue::Integer(integer) if integer.value == 0) + && matches!(second, ComponentValue::Integer(integer) if integer.value == 0) + && matches!(third, ComponentValue::Integer(integer) if integer.value == 1) + && fourth.value == 1 { *component_value = ComponentValue::Ident(Box::new(Ident { - span: *span, + span: function.span, value: "linear".into(), raw: None, })) - } else if matches!(first, ComponentValue::Number(box Number { value, .. }) if *value == 0.25) - && matches!(second, ComponentValue::Number(box Number { value, .. }) if *value == 0.1) - && matches!(third, ComponentValue::Number(box Number { value, .. }) if *value == 0.25) - && *fourth == 1 + } else if matches!(first, ComponentValue::Number(number) if number.value == 0.25) + && matches!(second, ComponentValue::Number(number) if number.value == 0.1) + && matches!(third, ComponentValue::Number(number) if number.value == 0.25) + && fourth.value == 1 { *component_value = ComponentValue::Ident(Box::new(Ident { - span: *span, + span: function.span, value: "ease".into(), raw: None, })) - } else if matches!(first, ComponentValue::Number(box Number { value: first, .. }) if *first == 0.42) - && matches!(second, ComponentValue::Integer(box Integer { value, .. }) if *value == 0) - && matches!(third, ComponentValue::Integer(box Integer { value, .. }) if *value == 1) - && *fourth == 1 + } else if matches!(first, ComponentValue::Number(number) if number.value == 0.42) + && matches!(second, ComponentValue::Integer(integer) if integer.value == 0) + && matches!(third, ComponentValue::Integer(integer) if integer.value == 1) + && fourth.value == 1 { *component_value = ComponentValue::Ident(Box::new(Ident { - span: *span, + span: function.span, value: "ease-in".into(), raw: None, })) - } else if matches!(first, ComponentValue::Integer(box Integer { value: first, .. }) if *first == 0) - && matches!(second, ComponentValue::Integer(box Integer { value, .. }) if *value == 0) - && matches!(third, ComponentValue::Number(box Number { value, .. }) if *value == 0.58) - && *fourth == 1 + } else if matches!(first, ComponentValue::Integer(integer) if integer.value == 0) + && matches!(second, ComponentValue::Integer(integer) if integer.value == 0) + && matches!(third, ComponentValue::Number(number) if number.value == 0.58) + && fourth.value == 1 { *component_value = ComponentValue::Ident(Box::new(Ident { - span: *span, + span: function.span, value: "ease-out".into(), raw: None, })) - } else if matches!(first, ComponentValue::Number(box Number { value: first, .. }) if *first == 0.42) - && matches!(second, ComponentValue::Integer(box Integer { value, .. }) if *value == 0) - && matches!(third, ComponentValue::Number(box Number { value, .. }) if *value == 0.58) - && *fourth == 1 + } else if matches!(first, ComponentValue::Number(number) if number.value == 0.42) + && matches!(second, ComponentValue::Integer(integer) if integer.value == 0) + && matches!(third, ComponentValue::Number(number) if number.value == 0.58) + && fourth.value == 1 { *component_value = ComponentValue::Ident(Box::new(Ident { - span: *span, + span: function.span, value: "ease-in-out".into(), raw: None, })) } } } - ComponentValue::Function(box Function { - name, - value: function_value, - span, - }) if name == "steps" && function_value.len() == 3 => { - match (&function_value[0], &function_value[2]) { - ( - ComponentValue::Integer(box Integer { - value: number_value, - .. - }), - ComponentValue::Ident(box Ident { - value: ident_value, .. - }), - ) if *number_value == 1 => match &*ident_value.to_ascii_lowercase() { - "start" | "jump-start" => { - *component_value = ComponentValue::Ident(Box::new(Ident { - span: *span, - value: "step-start".into(), - raw: None, - })) - } - "end" | "jump-end" => { - *component_value = ComponentValue::Ident(Box::new(Ident { - span: *span, - value: "step-end".into(), - raw: None, - })) + ComponentValue::Function(function) + if function.name == "steps" && function.value.len() == 3 => + { + match (&function.value[0], &function.value[2]) { + (ComponentValue::Integer(integer), ComponentValue::Ident(ident)) + if integer.value == 1 => + { + match &*ident.value.to_ascii_lowercase() { + "start" | "jump-start" => { + *component_value = ComponentValue::Ident(Box::new(Ident { + span: function.span, + value: "step-start".into(), + raw: None, + })) + } + "end" | "jump-end" => { + *component_value = ComponentValue::Ident(Box::new(Ident { + span: function.span, + value: "step-end".into(), + raw: None, + })) + } + _ => {} } - _ => {} - }, - ( - ComponentValue::Integer(box Integer { .. }), - ComponentValue::Ident(box Ident { - value: ident_value, .. - }), - ) if ident_value.eq_ignore_ascii_case("jump-start") => { - function_value[2] = ComponentValue::Ident(Box::new(Ident { - span: *span, + } + (ComponentValue::Integer(..), ComponentValue::Ident(ident)) + if ident.value.eq_ignore_ascii_case("jump-start") => + { + function.value[2] = ComponentValue::Ident(Box::new(Ident { + span: function.span, value: "start".into(), raw: None, })) } - ( - ComponentValue::Integer(number), - ComponentValue::Ident(box Ident { - value: ident_value, .. - }), - ) => match &*ident_value.to_ascii_lowercase() { - "end" | "jump-end" => { - *function_value = vec![ComponentValue::Integer(number.clone())]; + (ComponentValue::Integer(number), ComponentValue::Ident(ident)) => { + match &*ident.value.to_ascii_lowercase() { + "end" | "jump-end" => { + function.value = vec![ComponentValue::Integer(number.clone())]; + } + _ => {} } - _ => {} - }, + } _ => {} } } diff --git a/crates/swc_css_minifier/src/compressor/length.rs b/crates/swc_css_minifier/src/compressor/length.rs index 72b95ce282fa..6f5611d4c2f4 100644 --- a/crates/swc_css_minifier/src/compressor/length.rs +++ b/crates/swc_css_minifier/src/compressor/length.rs @@ -121,15 +121,19 @@ impl Compressor { return; } - if let ComponentValue::Dimension(box Dimension::Length(length)) = n { - if let Some(number) = self.length_to_zero(length) { - *n = ComponentValue::Number(Box::new(number)) + let length = match n { + ComponentValue::Dimension(dimension) => dimension.as_mut_length(), + ComponentValue::LengthPercentage(length_percentage) => { + length_percentage.as_mut_length() } - } else if let ComponentValue::LengthPercentage(box LengthPercentage::Length(length)) = n { - if let Some(number) = self.length_to_zero(length) { - *n = ComponentValue::Number(Box::new(number)) - } - } + _ => None, + }; + + let Some(number) = length.and_then(|length| self.length_to_zero(length)) else { + return; + }; + + *n = ComponentValue::Number(Box::new(number)); } pub(super) fn compress_length(&mut self, length: &mut Length) { diff --git a/crates/swc_css_minifier/src/compressor/media.rs b/crates/swc_css_minifier/src/compressor/media.rs index 31f7ce8efa0a..435c1bbb0f11 100644 --- a/crates/swc_css_minifier/src/compressor/media.rs +++ b/crates/swc_css_minifier/src/compressor/media.rs @@ -345,33 +345,32 @@ impl Compressor { if is_calc_function_name(name) && value.len() == 1 => { match &value[0] { - ComponentValue::CalcSum(box 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 => { - 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); - } - Some(ComponentValue::Dimension(dimension)) => { - *n = MediaFeatureValue::Dimension(*dimension); - } - Some(ComponentValue::Number(number)) => { - *n = MediaFeatureValue::Number(*number); + ComponentValue::CalcSum(calc_sum) 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); + } + Some(ComponentValue::Dimension(dimension)) => { + *n = MediaFeatureValue::Dimension(*dimension); + } + Some(ComponentValue::Number(number)) => { + *n = MediaFeatureValue::Number(*number); + } + _ => {} } - _ => {} } } + _ => {} } - _ => {} - }, + } _ => {} } } @@ -392,12 +391,15 @@ impl Compressor { MediaFeature::Plain(MediaFeaturePlain { span, name: MediaFeatureName::Ident(name), - value: box MediaFeatureValue::Number(value), + value, }) => { if matches!( &*name.value, "min-color" | "min-color-index" | "min-monochrome" - ) && value.value == 1.0 + ) && value + .as_number() + .map(|value| value.value == 1.0) + .unwrap_or_default() { *n = MediaFeature::Boolean(MediaFeatureBoolean { span: *span, diff --git a/crates/swc_css_minifier/src/compressor/mod.rs b/crates/swc_css_minifier/src/compressor/mod.rs index 60f18c0da324..3e00a951dbe9 100644 --- a/crates/swc_css_minifier/src/compressor/mod.rs +++ b/crates/swc_css_minifier/src/compressor/mod.rs @@ -59,16 +59,16 @@ impl VisitMut for Compressor { self.compress_stylesheet(n); - if !self.need_utf8_at_rule { - match n.rules.first() { - Some(Rule::AtRule(box AtRule { - prelude: Some(box AtRulePrelude::CharsetPrelude(Str { value, .. })), - .. - })) if value.as_ref().eq_ignore_ascii_case("utf-8") => { - n.rules.remove(0); - } - _ => {} - } + if !self.need_utf8_at_rule + && n.rules + .first() + .and_then(|rule| rule.as_at_rule()) + .and_then(|at_rule| at_rule.prelude.as_ref()) + .and_then(|prelude| prelude.as_charset_prelude()) + .filter(|x| x.value.eq_ignore_ascii_case("utf-8")) + .is_some() + { + n.rules.remove(0); } } @@ -412,8 +412,8 @@ impl VisitMut for Compressor { Token::BadUrl { raw: value, .. } if !contains_only_ascii_characters(value) => { self.need_utf8_at_rule = true; } - Token::Dimension(box DimensionToken { unit: value, .. }) - if !contains_only_ascii_characters(value) => + Token::Dimension(dimension_token) + if !contains_only_ascii_characters(&dimension_token.unit) => { self.need_utf8_at_rule = true; } diff --git a/crates/swc_css_minifier/src/compressor/rules.rs b/crates/swc_css_minifier/src/compressor/rules.rs index 3d4b77c7485c..fc2fbe086931 100644 --- a/crates/swc_css_minifier/src/compressor/rules.rs +++ b/crates/swc_css_minifier/src/compressor/rules.rs @@ -81,20 +81,26 @@ impl Compressor { } fn collect_names(&self, at_rule: &AtRule, names: &mut AHashMap) { - match &at_rule.prelude { - Some(box AtRulePrelude::CounterStylePrelude(CustomIdent { value: name, .. })) => { + let Some(prelude) = &at_rule.prelude else { + return; + }; + + match &**prelude { + AtRulePrelude::CounterStylePrelude(CustomIdent { value: name, .. }) => { names .entry(Name::CounterStyle(name.clone())) .and_modify(|mana| *mana += 1) .or_insert(1); } - Some(box AtRulePrelude::KeyframesPrelude(KeyframesName::CustomIdent( - box CustomIdent { value: name, .. }, - ))) - | Some(box AtRulePrelude::KeyframesPrelude(KeyframesName::Str(box Str { - value: name, - .. - }))) => { + prelude => { + let name = match prelude { + AtRulePrelude::KeyframesPrelude(KeyframesName::CustomIdent(custom_ident)) => { + &custom_ident.value + } + AtRulePrelude::KeyframesPrelude(KeyframesName::Str(s)) => &s.value, + _ => return, + }; + names .entry(Name::Keyframes( self.get_at_rule_name(at_rule), @@ -103,7 +109,6 @@ impl Compressor { .and_modify(|mana| *mana += 1) .or_insert(1); } - _ => {} } } @@ -113,45 +118,52 @@ impl Compressor { names: &mut AHashMap, remove_rules_list: &mut Vec, ) { - let mut discarder = |at_rule: &AtRule| match &at_rule.prelude { - Some(box AtRulePrelude::CounterStylePrelude(CustomIdent { value: name, .. })) => { - if let Some(counter) = names.get_mut(&Name::CounterStyle(name.clone())) { - if *counter > 1 { - *counter -= 1; + let mut discarder = |at_rule: &AtRule| { + let Some(prelude) = &at_rule.prelude else { + return true; + }; - false + match &**prelude { + AtRulePrelude::CounterStylePrelude(CustomIdent { value: name, .. }) => { + if let Some(counter) = names.get_mut(&Name::CounterStyle(name.clone())) { + if *counter > 1 { + *counter -= 1; + + false + } else { + true + } } else { - true + false } - } else { - false } - } - Some(box AtRulePrelude::KeyframesPrelude(KeyframesName::CustomIdent( - box CustomIdent { value: name, .. }, - ))) - | Some(box AtRulePrelude::KeyframesPrelude(KeyframesName::Str(box Str { - value: name, - .. - }))) => { - let counter = names.get_mut(&Name::Keyframes( - self.get_at_rule_name(at_rule), - name.clone(), - )); - - if let Some(counter) = counter { - if *counter > 1 { - *counter -= 1; + prelude => { + let name = match prelude { + AtRulePrelude::KeyframesPrelude(KeyframesName::CustomIdent( + custom_ident, + )) => &custom_ident.value, + AtRulePrelude::KeyframesPrelude(KeyframesName::Str(s)) => &s.value, + _ => return true, + }; - false + let counter = names.get_mut(&Name::Keyframes( + self.get_at_rule_name(at_rule), + name.clone(), + )); + + if let Some(counter) = counter { + if *counter > 1 { + *counter -= 1; + + false + } else { + true + } } else { - true + false } - } else { - false } } - _ => true, }; match parent_node { @@ -159,7 +171,7 @@ impl Compressor { for index in 0..stylesheet.rules.len() { let node = stylesheet.rules.get(index); - if let Some(Rule::AtRule(box at_rule)) = node { + if let Some(Rule::AtRule(at_rule)) = node { if !discarder(at_rule) { remove_rules_list.push(index); } @@ -170,7 +182,7 @@ impl Compressor { for index in 0..simple_block.value.len() { let node = simple_block.value.get(index); - if let Some(ComponentValue::AtRule(box at_rule)) = node { + if let Some(ComponentValue::AtRule(at_rule)) = node { if !discarder(at_rule) { remove_rules_list.push(index); } @@ -385,19 +397,28 @@ impl Compressor { }; let result = match rule { - Rule::AtRule(box AtRule { - name: AtRuleName::Ident(Ident { value, .. }), - block: Some(block), - .. - }) if !need_keep_by_name(value) && block.value.is_empty() => false, - Rule::QualifiedRule(box QualifiedRule { block, .. }) if block.value.is_empty() => { + Rule::AtRule(at_rule) + if at_rule + .name + .as_ident() + .map(|ident| !need_keep_by_name(&ident.value)) + .unwrap_or_default() + && at_rule + .block + .as_ref() + .map(|block| block.value.is_empty()) + .unwrap_or_default() => + { + false + } + Rule::QualifiedRule(qualified_rule) if qualified_rule.block.value.is_empty() => { false } - Rule::AtRule(box at_rule @ AtRule { .. }) + Rule::AtRule(at_rule) if self.is_mergeable_at_rule(at_rule) && matches!(prev_rule, Some(Rule::AtRule(_))) => { - if let Some(Rule::AtRule(box prev_rule)) = &mut prev_rule { + if let Some(Rule::AtRule(prev_rule)) = &mut prev_rule { if let Some(at_rule) = self.try_merge_at_rule(prev_rule, at_rule) { *rule = Rule::AtRule(Box::new(at_rule)); @@ -407,10 +428,10 @@ impl Compressor { true } - Rule::QualifiedRule(box qualified_rule @ QualifiedRule { .. }) + Rule::QualifiedRule(qualified_rule) if matches!(prev_rule, Some(Rule::QualifiedRule(_))) => { - if let Some(Rule::QualifiedRule(box prev_rule)) = &mut prev_rule { + if let Some(Rule::QualifiedRule(prev_rule)) = &mut prev_rule { if let Some(qualified_rule) = self.try_merge_qualified_rules(prev_rule, qualified_rule) { @@ -433,9 +454,7 @@ impl Compressor { if result { match rule { - Rule::AtRule(box at_rule @ AtRule { .. }) - if self.is_mergeable_at_rule(at_rule) => - { + Rule::AtRule(at_rule) if self.is_mergeable_at_rule(at_rule) => { prev_index = index; prev_rule_idx = Some(index); } @@ -515,12 +534,22 @@ impl Compressor { }; let result = match rule { - ComponentValue::AtRule(box AtRule { - block: Some(block), .. - }) - | ComponentValue::QualifiedRule(box QualifiedRule { block, .. }) - | ComponentValue::KeyframeBlock(box KeyframeBlock { block, .. }) - if block.value.is_empty() => + ComponentValue::AtRule(at_rule) + if at_rule + .block + .as_ref() + .map(|block| block.value.is_empty()) + .unwrap_or_default() => + { + false + } + ComponentValue::QualifiedRule(qualified_rule) + if qualified_rule.block.value.is_empty() => + { + false + } + ComponentValue::KeyframeBlock(keyframe_block) + if keyframe_block.block.value.is_empty() => { false } @@ -537,8 +566,8 @@ impl Compressor { true } - ComponentValue::QualifiedRule(box qualified_rule) if prev_rule.is_some() => { - if let Some(ComponentValue::QualifiedRule(box prev_rule)) = &mut prev_rule { + ComponentValue::QualifiedRule(qualified_rule) if prev_rule.is_some() => { + if let Some(ComponentValue::QualifiedRule(prev_rule)) = &mut prev_rule { if let Some(qualified_rule) = self.try_merge_qualified_rules(prev_rule, qualified_rule) { @@ -550,8 +579,8 @@ impl Compressor { true } - ComponentValue::Declaration(box declaration) if prev_rule.is_some() => { - if let Some(ComponentValue::Declaration(box prev_rule)) = &mut prev_rule { + ComponentValue::Declaration(declaration) if prev_rule.is_some() => { + if let Some(ComponentValue::Declaration(prev_rule)) = &mut prev_rule { if self.is_same_declaration_name(prev_rule, declaration) && prev_rule.value.eq_ignore_span(&declaration.value) { @@ -572,7 +601,7 @@ impl Compressor { if result { match rule { - ComponentValue::AtRule(box at_rule) if self.is_mergeable_at_rule(at_rule) => { + ComponentValue::AtRule(at_rule) if self.is_mergeable_at_rule(at_rule) => { prev_index = index; prev_rule_idx = Some(index); } diff --git a/crates/swc_css_minifier/src/compressor/transform_function.rs b/crates/swc_css_minifier/src/compressor/transform_function.rs index f8e1a88233a9..d56a8e724ddb 100644 --- a/crates/swc_css_minifier/src/compressor/transform_function.rs +++ b/crates/swc_css_minifier/src/compressor/transform_function.rs @@ -6,284 +6,192 @@ use super::Compressor; impl Compressor { pub(super) fn compress_transform_function(&self, component_value: &mut ComponentValue) { match component_value { - ComponentValue::Function(box Function { - name, - value: function_value, - .. - }) if name == "translate" && function_value.len() == 3 => { - match (function_value.first(), function_value.get(2)) { - ( - Some(first), - Some(ComponentValue::Integer(box Integer { - value: second_number, - .. - })), - ) if *second_number == 0 => { - *function_value = vec![first.clone()]; + ComponentValue::Function(function) + if function.name == "translate" && function.value.len() == 3 => + { + match (function.value.first(), function.value.get(2)) { + (Some(first), Some(ComponentValue::Integer(second))) if second.value == 0 => { + function.value = vec![first.clone()]; } - ( - Some(ComponentValue::Integer(box Integer { - value: first_number, - .. - })), - Some(second), - ) if *first_number == 0 => { - *name = FunctionName::Ident(Ident { - span: name.span(), + (Some(ComponentValue::Integer(first)), Some(second)) if first.value == 0 => { + function.name = FunctionName::Ident(Ident { + span: function.name.span(), value: "translatey".into(), raw: None, }); - *function_value = vec![second.clone()]; + function.value = vec![second.clone()]; } _ => {} } } - ComponentValue::Function(box Function { - name, - value: function_value, - .. - }) if name == "translate3d" && function_value.len() == 5 => { + ComponentValue::Function(function) + if function.name == "translate3d" && function.value.len() == 5 => + { match ( - function_value.first(), - function_value.get(2), - function_value.get(4), + function.value.first(), + function.value.get(2), + function.value.get(4), ) { ( - Some(ComponentValue::Integer(box Integer { - value: first_number, - .. - })), - Some(ComponentValue::Integer(box Integer { - value: second_number, - .. - })), + Some(ComponentValue::Integer(first)), + Some(ComponentValue::Integer(second)), Some(third), - ) if *first_number == 0 && *second_number == 0 => { - *name = FunctionName::Ident(Ident { - span: name.span(), + ) if first.value == 0 && second.value == 0 => { + function.name = FunctionName::Ident(Ident { + span: function.name.span(), value: "translatez".into(), raw: None, }); - *function_value = vec![third.clone()]; + function.value = vec![third.clone()]; } _ => {} } } - ComponentValue::Function(box Function { - name, - value: function_value, - .. - }) if name == "scale" && function_value.len() == 3 => { - match (function_value.first(), function_value.get(2)) { + ComponentValue::Function(function) + if function.name == "scale" && function.value.len() == 3 => + { + match (function.value.first(), function.value.get(2)) { ( - Some( - first @ ComponentValue::Integer(box Integer { - value: first_number, - .. - }), - ), - Some(ComponentValue::Integer(box Integer { - value: second_number, - .. - })), - ) if first_number == second_number => { - *function_value = vec![first.clone()]; + Some(first @ ComponentValue::Integer(first_number)), + Some(ComponentValue::Integer(second_number)), + ) if first_number.value == second_number.value => { + function.value = vec![first.clone()]; } - ( - Some(first), - Some(ComponentValue::Integer(box Integer { - value: second_number, - .. - })), - ) if *second_number == 1 => { - *name = FunctionName::Ident(Ident { - span: name.span(), + (Some(first), Some(ComponentValue::Integer(second_number))) + if second_number.value == 1 => + { + function.name = FunctionName::Ident(Ident { + span: function.name.span(), value: "scalex".into(), raw: None, }); - *function_value = vec![first.clone()]; + function.value = vec![first.clone()]; } - ( - Some(ComponentValue::Integer(box Integer { - value: first_number, - .. - })), - Some(second), - ) if *first_number == 1 => { - *name = FunctionName::Ident(Ident { - span: name.span(), + (Some(ComponentValue::Integer(first_number)), Some(second)) + if first_number.value == 1 => + { + function.name = FunctionName::Ident(Ident { + span: function.name.span(), value: "scaley".into(), raw: None, }); - *function_value = vec![second.clone()]; + function.value = vec![second.clone()]; } _ => {} } } - ComponentValue::Function(box Function { - name, - value: function_value, - .. - }) if name == "scale3d" && function_value.len() == 5 => { + ComponentValue::Function(function) + if function.name == "scale3d" && function.value.len() == 5 => + { match ( - function_value.first(), - function_value.get(2), - function_value.get(4), + function.value.first(), + function.value.get(2), + function.value.get(4), ) { ( Some(first), - Some(ComponentValue::Integer(box Integer { - value: second_number, - .. - })), - Some(ComponentValue::Integer(box Integer { - value: third_number, - .. - })), - ) if *second_number == 1 && *third_number == 1 => { - *name = FunctionName::Ident(Ident { - span: name.span(), + Some(ComponentValue::Integer(second_number)), + Some(ComponentValue::Integer(third_number)), + ) if second_number.value == 1 && third_number.value == 1 => { + function.name = FunctionName::Ident(Ident { + span: function.name.span(), value: "scalex".into(), raw: None, }); - *function_value = vec![first.clone()]; + function.value = vec![first.clone()]; } ( - Some(ComponentValue::Integer(box Integer { - value: first_number, - .. - })), + Some(ComponentValue::Integer(first_number)), Some(second), - Some(ComponentValue::Integer(box Integer { - value: third_number, - .. - })), - ) if *first_number == 1 && *third_number == 1 => { - *name = FunctionName::Ident(Ident { - span: name.span(), + Some(ComponentValue::Integer(third_number)), + ) if first_number.value == 1 && third_number.value == 1 => { + function.name = FunctionName::Ident(Ident { + span: function.name.span(), value: "scaley".into(), raw: None, }); - *function_value = vec![second.clone()]; + function.value = vec![second.clone()]; } ( - Some(ComponentValue::Integer(box Integer { - value: first_number, - .. - })), - Some(ComponentValue::Integer(box Integer { - value: second_number, - .. - })), + Some(ComponentValue::Integer(first_number)), + Some(ComponentValue::Integer(second_number)), Some(third), - ) if *first_number == 1 && *second_number == 1 => { - *name = FunctionName::Ident(Ident { - span: name.span(), + ) if first_number.value == 1 && second_number.value == 1 => { + function.name = FunctionName::Ident(Ident { + span: function.name.span(), value: "scalez".into(), raw: None, }); - *function_value = vec![third.clone()]; + function.value = vec![third.clone()]; } _ => {} } } - ComponentValue::Function(box Function { - name, - value: function_value, - .. - }) if name == "matrix3d" && function_value.len() == 31 => { + ComponentValue::Function(function) + if function.name == "matrix3d" && function.value.len() == 31 => + { match ( - function_value.first(), - function_value.get(1), - function_value.get(2), - function_value.get(3), - function_value.get(4), - function_value.get(6), - function_value.get(8), - function_value.get(9), - function_value.get(10), - function_value.get(11), - function_value.get(12), - function_value.get(14), - function_value.get(16), - function_value.get(18), - function_value.get(20), - function_value.get(22), - function_value.get(24), - function_value.get(25), - function_value.get(26), - function_value.get(28), - function_value.get(30), + function.value.first(), + function.value.get(1), + function.value.get(2), + function.value.get(3), + function.value.get(4), + function.value.get(6), + function.value.get(8), + function.value.get(9), + function.value.get(10), + function.value.get(11), + function.value.get(12), + function.value.get(14), + function.value.get(16), + function.value.get(18), + function.value.get(20), + function.value.get(22), + function.value.get(24), + function.value.get(25), + function.value.get(26), + function.value.get(28), + function.value.get(30), ) { ( Some(first), Some(first_comma), Some(second), Some(second_comma), - Some(ComponentValue::Integer(box Integer { - value: third_number, - .. - })), - Some(ComponentValue::Integer(box Integer { - value: fourth_number, - .. - })), + Some(ComponentValue::Integer(third_number)), + Some(ComponentValue::Integer(fourth_number)), Some(fifth), Some(fifth_comma), Some(sixth), Some(sixth_comma), - Some(ComponentValue::Integer(box Integer { - value: seventh_number, - .. - })), - Some(ComponentValue::Integer(box Integer { - value: eighth_number, - .. - })), - Some(ComponentValue::Integer(box Integer { - value: ninth_number, - .. - })), - Some(ComponentValue::Integer(box Integer { - value: tenth_number, - .. - })), - Some(ComponentValue::Integer(box Integer { - value: eleventh_number, - .. - })), - Some(ComponentValue::Integer(box Integer { - value: twelfth_number, - .. - })), + Some(ComponentValue::Integer(seventh_number)), + Some(ComponentValue::Integer(eighth_number)), + Some(ComponentValue::Integer(ninth_number)), + Some(ComponentValue::Integer(tenth_number)), + Some(ComponentValue::Integer(eleventh_number)), + Some(ComponentValue::Integer(twelfth_number)), Some(thirteenth), Some(thirteenth_comma), Some(fourteenth), - Some(ComponentValue::Integer(box Integer { - value: fifteenth_number, - .. - })), - Some(ComponentValue::Integer(box Integer { - value: sixteenth_number, - .. - })), - ) if *third_number == 0 - && *fourth_number == 0 - && *seventh_number == 0 - && *eighth_number == 0 - && *ninth_number == 0 - && *tenth_number == 0 - && *eleventh_number == 1 - && *twelfth_number == 0 - && *fifteenth_number == 0 - && *sixteenth_number == 1 => + Some(ComponentValue::Integer(fifteenth_number)), + Some(ComponentValue::Integer(sixteenth_number)), + ) if third_number.value == 0 + && fourth_number.value == 0 + && seventh_number.value == 0 + && eighth_number.value == 0 + && ninth_number.value == 0 + && tenth_number.value == 0 + && eleventh_number.value == 1 + && twelfth_number.value == 0 + && fifteenth_number.value == 0 + && sixteenth_number.value == 1 => { - *name = FunctionName::Ident(Ident { - span: name.span(), + function.name = FunctionName::Ident(Ident { + span: function.name.span(), value: "matrix".into(), raw: None, }); - *function_value = vec![ + function.value = vec![ first.clone(), first_comma.clone(), second.clone(), @@ -300,132 +208,100 @@ impl Compressor { _ => {} } } - ComponentValue::Function(box Function { - name, - value: function_value, - .. - }) if name == "rotate3d" && function_value.len() == 7 => { + ComponentValue::Function(function) + if function.name == "rotate3d" && function.value.len() == 7 => + { match ( - function_value.first(), - function_value.get(2), - function_value.get(4), - function_value.get(6), + function.value.first(), + function.value.get(2), + function.value.get(4), + function.value.get(6), ) { ( - Some(ComponentValue::Integer(box Integer { - value: first_number, - .. - })), - Some(ComponentValue::Integer(box Integer { - value: second_number, - .. - })), - Some(ComponentValue::Integer(box Integer { - value: third_number, - .. - })), + Some(ComponentValue::Integer(first_number)), + Some(ComponentValue::Integer(second_number)), + Some(ComponentValue::Integer(third_number)), Some(fourth_value), - ) if *first_number == 1 && *second_number == 0 && *third_number == 0 => { - *name = FunctionName::Ident(Ident { - span: name.span(), + ) if first_number.value == 1 + && second_number.value == 0 + && third_number.value == 0 => + { + function.name = FunctionName::Ident(Ident { + span: function.name.span(), value: "rotatex".into(), raw: None, }); - *function_value = vec![fourth_value.clone()]; + function.value = vec![fourth_value.clone()]; } ( - Some(ComponentValue::Integer(box Integer { - value: first_number, - .. - })), - Some(ComponentValue::Integer(box Integer { - value: second_number, - .. - })), - Some(ComponentValue::Integer(box Integer { - value: third_number, - .. - })), + Some(ComponentValue::Integer(first_number)), + Some(ComponentValue::Integer(second_number)), + Some(ComponentValue::Integer(third_number)), Some(fourth_value), - ) if *first_number == 0 && *second_number == 1 && *third_number == 0 => { - *name = FunctionName::Ident(Ident { - span: name.span(), + ) if first_number.value == 0 + && second_number.value == 1 + && third_number.value == 0 => + { + function.name = FunctionName::Ident(Ident { + span: function.name.span(), value: "rotatey".into(), raw: None, }); - *function_value = vec![fourth_value.clone()]; + function.value = vec![fourth_value.clone()]; } ( - Some(ComponentValue::Integer(box Integer { - value: first_number, - .. - })), - Some(ComponentValue::Integer(box Integer { - value: second_number, - .. - })), - Some(ComponentValue::Integer(box Integer { - value: third_number, - .. - })), + Some(ComponentValue::Integer(first_number)), + Some(ComponentValue::Integer(second_number)), + Some(ComponentValue::Integer(third_number)), Some(fourth_value), - ) if *first_number == 0 && *second_number == 0 && *third_number == 1 => { - *name = FunctionName::Ident(Ident { - span: name.span(), + ) if first_number.value == 0 + && second_number.value == 0 + && third_number.value == 1 => + { + function.name = FunctionName::Ident(Ident { + span: function.name.span(), value: "rotate".into(), raw: None, }); - *function_value = vec![fourth_value.clone()]; + function.value = vec![fourth_value.clone()]; } _ => {} } } - ComponentValue::Function(box Function { - name, - value: function_value, - .. - }) if name == "rotatez" && function_value.len() == 1 => { - *name = FunctionName::Ident(Ident { - span: name.span(), + ComponentValue::Function(function) + if function.name == "rotatez" && function.value.len() == 1 => + { + function.name = FunctionName::Ident(Ident { + span: function.name.span(), value: "rotate".into(), raw: None, }); } - ComponentValue::Function(box Function { - name, - value: function_value, - .. - }) if name == "skew" && function_value.len() == 3 => { - match (function_value.first(), function_value.get(2)) { - ( - Some(first), - Some(ComponentValue::Integer(box Integer { - value: second_number, - .. - })), - ) if *second_number == 0 => { - *name = FunctionName::Ident(Ident { - span: name.span(), + ComponentValue::Function(function) + if function.name == "skew" && function.value.len() == 3 => + { + match (function.value.first(), function.value.get(2)) { + (Some(first), Some(ComponentValue::Integer(second_number))) + if second_number.value == 0 => + { + function.name = FunctionName::Ident(Ident { + span: function.name.span(), value: "skewx".into(), raw: None, }); - *function_value = vec![first.clone()]; + function.value = vec![first.clone()]; } - ( - Some(ComponentValue::Integer(box Integer { - value: first_number, - .. - })), - Some(second), - ) if *first_number == 0 => { - *name = FunctionName::Ident(Ident { - span: name.span(), + (Some(ComponentValue::Integer(first_number)), Some(second)) + if first_number.value == 0 => + { + function.name = FunctionName::Ident(Ident { + span: function.name.span(), value: "skewy".into(), raw: None, }); - *function_value = vec![second.clone()]; + function.value = vec![second.clone()]; } _ => {} } diff --git a/crates/swc_css_minifier/src/lib.rs b/crates/swc_css_minifier/src/lib.rs index baa353cdb4f4..f379576a8784 100644 --- a/crates/swc_css_minifier/src/lib.rs +++ b/crates/swc_css_minifier/src/lib.rs @@ -1,4 +1,3 @@ -#![feature(box_patterns)] #![deny(clippy::all)] #![allow(clippy::match_like_matches_macro)] #![allow(clippy::needless_update)]