diff --git a/crates/swc_html_minifier/src/lib.rs b/crates/swc_html_minifier/src/lib.rs index af0f67fa8098..8ec3bf52aba4 100644 --- a/crates/swc_html_minifier/src/lib.rs +++ b/crates/swc_html_minifier/src/lib.rs @@ -608,17 +608,15 @@ impl Minifier<'_> { } } - fn is_default_attribute_value( - &self, - namespace: Namespace, - tag_name: &JsWord, - attribute: &Attribute, - ) -> bool { - let attribute_value = attribute.value.as_ref().unwrap(); + fn is_default_attribute_value(&self, element: &Element, attribute: &Attribute) -> bool { + let attribute_value = match &attribute.value { + Some(value) => value, + _ => return false, + }; - match namespace { + match element.namespace { Namespace::HTML | Namespace::SVG => { - match *tag_name { + match element.tag_name { js_word!("html") => match attribute.name { js_word!("xmlns") => { if &*attribute_value.trim().to_ascii_lowercase() @@ -671,7 +669,7 @@ impl Minifier<'_> { _ => {} } - let default_attributes = if namespace == Namespace::HTML { + let default_attributes = if element.namespace == Namespace::HTML { &HTML_ELEMENTS_AND_ATTRIBUTES } else { &SVG_ELEMENTS_AND_ATTRIBUTES @@ -691,7 +689,7 @@ impl Minifier<'_> { }; let normalized_value = attribute_value.trim(); - let attributes = match default_attributes.get(tag_name) { + let attributes = match default_attributes.get(&element.tag_name) { Some(element) => element, None => return false, }; @@ -715,15 +713,15 @@ impl Minifier<'_> { // It it safe to remove svg redundant attributes, they used for // styling - if namespace == Namespace::SVG { + if element.namespace == Namespace::SVG { return true; } // It it safe to remove redundant attributes for metadata // elements - if namespace == Namespace::HTML + if element.namespace == Namespace::HTML && matches!( - *tag_name, + element.tag_name, js_word!("base") | js_word!("link") | js_word!("noscript") @@ -747,8 +745,8 @@ impl Minifier<'_> { _ => { matches!( ( - namespace, - tag_name, + element.namespace, + &element.tag_name, &attribute.name, attribute_value.to_ascii_lowercase().trim() ), @@ -798,9 +796,9 @@ impl Minifier<'_> { !matches!(self.options.collapse_whitespaces, CollapseWhitespaces::None) } - fn is_custom_element(&self, tag_name: &JsWord) -> bool { + fn is_custom_element(&self, element: &Element) -> bool { // https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name - match *tag_name { + match element.tag_name { js_word!("annotation-xml") | js_word!("color-profile") | js_word!("font-face") @@ -809,13 +807,16 @@ impl Minifier<'_> { | js_word!("font-face-format") | js_word!("font-face-name") | js_word!("missing-glyph") => false, - _ => matches!(tag_name.chars().next(), Some('a'..='z')) && tag_name.contains('-'), + _ => { + matches!(element.tag_name.chars().next(), Some('a'..='z')) + && element.tag_name.contains('-') + } } } - fn get_display(&self, namespace: Namespace, tag_name: &JsWord) -> Display { - match namespace { - Namespace::HTML => match *tag_name { + fn get_display(&self, element: &Element) -> Display { + match element.namespace { + Namespace::HTML => match element.tag_name { js_word!("area") | js_word!("base") | js_word!("basefont") @@ -978,7 +979,7 @@ impl Minifier<'_> { _ => Display::Inline, }, - Namespace::SVG => match *tag_name { + Namespace::SVG => match element.tag_name { js_word!("text") | js_word!("foreignObject") => Display::Block, _ => Display::Inline, }, @@ -986,8 +987,8 @@ impl Minifier<'_> { } } - fn is_element_displayed(&self, namespace: Namespace, tag_name: &JsWord) -> bool { - match namespace { + fn is_element_displayed(&self, element: &Element) -> bool { + match element.namespace { Namespace::HTML => { // https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_categories#metadata_content // @@ -995,7 +996,7 @@ impl Minifier<'_> { // `noscript` - can be displayed if JavaScript disabled // `script` - can insert markup using `document.write` !matches!( - *tag_name, + element.tag_name, js_word!("base") | js_word!("command") | js_word!("link") @@ -1005,7 +1006,7 @@ impl Minifier<'_> { | js_word!("template") ) } - Namespace::SVG => !matches!(*tag_name, js_word!("style")), + Namespace::SVG => !matches!(element.tag_name, js_word!("style")), _ => true, } } @@ -1080,7 +1081,7 @@ impl Minifier<'_> { } } Some(Child::Element(element)) => { - if !self.is_element_displayed(element.namespace, &element.tag_name) && index >= 1 { + if !self.is_element_displayed(element) && index >= 1 { self.get_prev_displayed_node(children, index - 1) } else if !element.children.is_empty() { self.get_prev_displayed_node(&element.children, element.children.len() - 1) @@ -1109,7 +1110,7 @@ impl Minifier<'_> { } } Some(Child::Element(element)) => { - if !self.is_element_displayed(element.namespace, &element.tag_name) && index >= 1 { + if !self.is_element_displayed(element) && index >= 1 { self.get_last_displayed_text_node(children, index - 1) } else if !element.children.is_empty() { for index in (0..=element.children.len() - 1).rev() { @@ -1140,7 +1141,7 @@ impl Minifier<'_> { match next { Some(Child::Comment(_)) => self.get_first_displayed_text_node(children, index + 1), Some(Child::Element(element)) => { - if !self.is_element_displayed(element.namespace, &element.tag_name) && index >= 1 { + if !self.is_element_displayed(element) && index >= 1 { self.get_first_displayed_text_node(children, index - 1) } else if !element.children.is_empty() { for index in 0..=element.children.len() - 1 { @@ -1170,9 +1171,7 @@ impl Minifier<'_> { match next { Some(Child::Comment(_)) => self.get_next_displayed_node(children, index + 1), - Some(Child::Element(element)) - if !self.is_element_displayed(element.namespace, &element.tag_name) => - { + Some(Child::Element(element)) if !self.is_element_displayed(element) => { self.get_next_displayed_node(children, index + 1) } Some(_) => next, @@ -1180,11 +1179,7 @@ impl Minifier<'_> { } } - fn get_whitespace_minification_for_tag( - &self, - namespace: Namespace, - tag_name: &JsWord, - ) -> WhitespaceMinificationMode { + fn get_whitespace_minification_for_tag(&self, element: &Element) -> WhitespaceMinificationMode { let default_collapse = match self.options.collapse_whitespaces { CollapseWhitespaces::All | CollapseWhitespaces::Smart @@ -1201,8 +1196,8 @@ impl Minifier<'_> { | CollapseWhitespaces::None => false, }; - match namespace { - Namespace::HTML => match *tag_name { + match element.namespace { + Namespace::HTML => match element.tag_name { js_word!("script") | js_word!("style") => WhitespaceMinificationMode { collapse: false, trim: !matches!( @@ -1211,7 +1206,7 @@ impl Minifier<'_> { ), }, _ => { - if get_white_space(namespace, tag_name) == WhiteSpace::Pre { + if get_white_space(element.namespace, &element.tag_name) == WhiteSpace::Pre { WhitespaceMinificationMode { collapse: false, trim: false, @@ -1224,14 +1219,14 @@ impl Minifier<'_> { } } }, - Namespace::SVG => match *tag_name { + Namespace::SVG => match element.tag_name { js_word!("script") | js_word!("style") => WhitespaceMinificationMode { collapse: false, trim: true, }, // https://svgwg.org/svg2-draft/render.html#Definitions _ if matches!( - *tag_name, + element.tag_name, js_word!("a") | js_word!("circle") | js_word!("ellipse") @@ -1310,7 +1305,7 @@ impl Minifier<'_> { fn is_empty_metadata_element(&self, child: &Child) -> bool { if let Child::Element(element) = child { - if (!self.is_element_displayed(element.namespace, &element.tag_name) + if (!self.is_element_displayed(element) || (matches!(element.namespace, Namespace::HTML | Namespace::SVG) && element.tag_name == js_word!("script")) || (element.namespace == Namespace::HTML @@ -1378,7 +1373,12 @@ impl Minifier<'_> { true } } - _ => true, + _ => !self.is_default_attribute_value(left, attribute), + }) + .map(|mut attribute| { + self.minify_attribute(left, &mut attribute); + + attribute }) .collect::>(); @@ -1411,7 +1411,12 @@ impl Minifier<'_> { true } } - _ => true, + _ => !self.is_default_attribute_value(right, attribute), + }) + .map(|mut attribute| { + self.minify_attribute(right, &mut attribute); + + attribute }) .collect::>(); @@ -1467,14 +1472,12 @@ impl Minifier<'_> { return vec![]; } - let (namespace, tag_name) = match &self.current_element { - Some(element) => (element.namespace, &element.tag_name), - _ => { - unreachable!(); - } + let parent = match &self.current_element { + Some(element) => element, + _ => return children.to_vec(), }; - let mode = self.get_whitespace_minification_for_tag(namespace, tag_name); + let mode = self.get_whitespace_minification_for_tag(parent); let child_will_be_retained = |child: &mut Child, prev_children: &mut Vec, next_children: &mut Vec| { @@ -1495,15 +1498,16 @@ impl Minifier<'_> { Child::Text(text) if text.data.is_empty() => false, Child::Text(text) if self.need_collapse_whitespace() - && namespace == Namespace::HTML - && matches!(*tag_name, js_word!("html") | js_word!("head")) + && parent.namespace == Namespace::HTML + && matches!(parent.tag_name, js_word!("html") | js_word!("head")) && text.data.chars().all(is_whitespace) => { false } Child::Text(text) if !self.descendant_of_pre - && get_white_space(namespace, tag_name) == WhiteSpace::Normal + && get_white_space(parent.namespace, &parent.tag_name) + == WhiteSpace::Normal && matches!( self.options.collapse_whitespaces, CollapseWhitespaces::All @@ -1530,11 +1534,7 @@ impl Minifier<'_> { let prev = prev_children.last(); let prev_display = match prev { - Some(Child::Element(Element { - namespace, - tag_name, - .. - })) => Some(self.get_display(*namespace, tag_name)), + Some(Child::Element(element)) => Some(self.get_display(element)), Some(Child::Comment(_)) => match need_remove_metadata_whitespaces { true => None, _ => Some(Display::None), @@ -1572,7 +1572,7 @@ impl Minifier<'_> { // the behavior of spaces let is_custom_element = if let Some(Child::Element(element)) = &prev { - self.is_custom_element(&element.tag_name) + self.is_custom_element(element) } else { false }; @@ -1604,8 +1604,7 @@ impl Minifier<'_> { } } _ => { - let parent_display = - self.get_display(namespace, tag_name); + let parent_display = self.get_display(parent); match parent_display { Display::Inline => { @@ -1637,13 +1636,13 @@ impl Minifier<'_> { // attribute. This includes text nodes. // Also they can be used for custom logic - if (namespace == Namespace::HTML - && *tag_name == js_word!("template")) - || self.is_custom_element(tag_name) + if (parent.namespace == Namespace::HTML + && parent.tag_name == js_word!("template")) + || self.is_custom_element(parent) { false } else { - let parent_display = self.get_display(namespace, tag_name); + let parent_display = self.get_display(parent); match parent_display { Display::Inline => { @@ -1663,11 +1662,7 @@ impl Minifier<'_> { let next = next_children.first(); let next_display = match next { - Some(Child::Element(Element { - namespace, - tag_name, - .. - })) => Some(self.get_display(*namespace, tag_name)), + Some(Child::Element(element)) => Some(self.get_display(element)), Some(Child::Comment(_)) => match need_remove_metadata_whitespaces { true => None, _ => Some(Display::None), @@ -1716,8 +1711,7 @@ impl Minifier<'_> { } } _ => { - let parent_display = - self.get_display(namespace, tag_name); + let parent_display = self.get_display(parent); !matches!(parent_display, Display::Inline) } @@ -1726,13 +1720,13 @@ impl Minifier<'_> { Some(_) => false, None => { // Template can be used in any place, so let's keep whitespaces - let is_template = namespace == Namespace::HTML - && *tag_name == js_word!("template"); + let is_template = parent.namespace == Namespace::HTML + && parent.tag_name == js_word!("template"); if is_template { false } else { - let parent_display = self.get_display(namespace, tag_name); + let parent_display = self.get_display(parent); !matches!(parent_display, Display::Inline) } @@ -2352,167 +2346,14 @@ impl Minifier<'_> { Some(minified) } -} - -impl VisitMut for Minifier<'_> { - fn visit_mut_document(&mut self, n: &mut Document) { - n.visit_mut_children_with(self); - - n.children - .retain(|child| !matches!(child, Child::Comment(_) if self.options.remove_comments)); - } - - fn visit_mut_document_fragment(&mut self, n: &mut DocumentFragment) { - n.children = self.minify_children(&mut n.children); - - n.visit_mut_children_with(self); - } - - fn visit_mut_document_type(&mut self, n: &mut DocumentType) { - n.visit_mut_children_with(self); - - if !self.options.force_set_html5_doctype { - return; - } - - n.name = Some(js_word!("html")); - n.system_id = None; - n.public_id = None; - } - - fn visit_mut_child(&mut self, n: &mut Child) { - n.visit_mut_children_with(self); - - self.current_element = None; - - if matches!( - self.options.collapse_whitespaces, - CollapseWhitespaces::Smart - | CollapseWhitespaces::AdvancedConservative - | CollapseWhitespaces::OnlyMetadata - ) { - match n { - Child::Text(_) | Child::Element(_) => { - self.latest_element = Some(n.clone()); - } - _ => {} - } - } - } - - fn visit_mut_element(&mut self, n: &mut Element) { - // Don't copy children to save memory - self.current_element = Some(Element { - span: Default::default(), - tag_name: n.tag_name.clone(), - namespace: n.namespace, - attributes: n.attributes.clone(), - children: vec![], - content: None, - is_self_closing: n.is_self_closing, - }); - - let old_descendant_of_pre = self.descendant_of_pre; - - if self.need_collapse_whitespace() && !old_descendant_of_pre { - self.descendant_of_pre = get_white_space(n.namespace, &n.tag_name) == WhiteSpace::Pre; - } - - n.children = self.minify_children(&mut n.children); - - n.visit_mut_children_with(self); - - // Remove all leading and trailing whitespaces for the `body` element - if n.namespace == Namespace::HTML - && n.tag_name == js_word!("body") - && self.need_collapse_whitespace() - { - self.remove_leading_and_trailing_whitespaces(&mut n.children, true, true); - } - - if self.need_collapse_whitespace() { - self.descendant_of_pre = old_descendant_of_pre; - } - - let mut remove_list = vec![]; - - for (i, i1) in n.attributes.iter().enumerate() { - if i1.value.is_some() { - if self.options.remove_redundant_attributes != RemoveRedundantAttributes::None - && self.is_default_attribute_value(n.namespace, &n.tag_name, i1) - { - remove_list.push(i); - - continue; - } - - if self.options.remove_empty_attributes { - let value = i1.value.as_ref().unwrap(); - - if (matches!(i1.name, js_word!("id")) && value.is_empty()) - || (matches!(i1.name, js_word!("class") | js_word!("style")) - && value.is_empty()) - || self.is_event_handler_attribute(i1) && value.is_empty() - { - remove_list.push(i); - - continue; - } - } - } - - for (j, j1) in n.attributes.iter().enumerate() { - if i < j && i1.name == j1.name { - remove_list.push(j); - } - } - } - - // Fast path. We don't face real duplicates in most cases. - if !remove_list.is_empty() { - let new = take(&mut n.attributes) - .into_iter() - .enumerate() - .filter_map(|(idx, value)| { - if remove_list.contains(&idx) { - None - } else { - Some(value) - } - }) - .collect::>(); - - n.attributes = new; - } - - if let Some(attribute_name_counter) = &self.attribute_name_counter { - n.attributes.sort_by(|a, b| { - let ordeing = attribute_name_counter - .get(&b.name) - .cmp(&attribute_name_counter.get(&a.name)); - - match ordeing { - Ordering::Equal => b.name.cmp(&a.name), - _ => ordeing, - } - }); - } - } - - fn visit_mut_attribute(&mut self, n: &mut Attribute) { - n.visit_mut_children_with(self); + fn minify_attribute(&self, element: &Element, n: &mut Attribute) { if let Some(value) = &n.value { - let current_element = match &self.current_element { - Some(current_element) => current_element, - _ => return, - }; - if value.is_empty() { if (self.options.collapse_boolean_attributes - && self.is_boolean_attribute(current_element, n)) + && self.is_boolean_attribute(element, n)) || (self.options.normalize_attributes - && self.is_crossorigin_attribute(current_element, n) + && self.is_crossorigin_attribute(element, n) && value.is_empty()) { n.value = None; @@ -2521,11 +2362,7 @@ impl VisitMut for Minifier<'_> { return; } - match ( - current_element.namespace, - ¤t_element.tag_name, - &n.name, - ) { + match (element.namespace, &element.tag_name, &n.name) { (Namespace::HTML, &js_word!("iframe"), &js_word!("srcdoc")) => { if let Some(minified) = self.minify_html( value.to_string(), @@ -2545,13 +2382,13 @@ impl VisitMut for Minifier<'_> { n.value = Some(value.trim().to_ascii_lowercase().into()); } _ if self.options.normalize_attributes - && self.is_crossorigin_attribute(current_element, n) + && self.is_crossorigin_attribute(element, n) && value.to_ascii_lowercase() == js_word!("anonymous") => { n.value = None; } _ if self.options.collapse_boolean_attributes - && self.is_boolean_attribute(current_element, n) => + && self.is_boolean_attribute(element, n) => { n.value = None; } @@ -2575,14 +2412,14 @@ impl VisitMut for Minifier<'_> { } } _ if self.options.normalize_attributes - && current_element.namespace == Namespace::HTML + && element.namespace == Namespace::HTML && n.name == js_word!("contenteditable") && n.value == Some(js_word!("true")) => { n.value = Some(js_word!("")); } _ if self.options.normalize_attributes - && self.is_semicolon_separated_attribute(current_element, n) => + && self.is_semicolon_separated_attribute(element, n) => { n.value = Some( value @@ -2596,7 +2433,7 @@ impl VisitMut for Minifier<'_> { _ if self.options.normalize_attributes && n.name == js_word!("content") && self.element_has_attribute_with_value( - current_element, + element, &js_word!("http-equiv"), &[js_word!("content-security-policy")], ) => @@ -2623,7 +2460,7 @@ impl VisitMut for Minifier<'_> { n.value = Some(value.into()); } _ if self.options.sort_space_separated_attribute_values - && self.is_attribute_value_unordered_set(current_element, n) => + && self.is_attribute_value_unordered_set(element, n) => { let mut values = value.split_whitespace().collect::>(); @@ -2632,7 +2469,7 @@ impl VisitMut for Minifier<'_> { n.value = Some(values.join(" ").into()); } _ if self.options.normalize_attributes - && self.is_space_separated_attribute(current_element, n) => + && self.is_space_separated_attribute(element, n) => { n.value = Some( value @@ -2642,7 +2479,7 @@ impl VisitMut for Minifier<'_> { .into(), ); } - _ if self.is_comma_separated_attribute(current_element, n) => { + _ if self.is_comma_separated_attribute(element, n) => { let mut value = value.to_string(); if self.options.normalize_attributes { @@ -2678,7 +2515,7 @@ impl VisitMut for Minifier<'_> { n.value = Some(value.into()); } } - _ if self.is_trimable_separated_attribute(current_element, n) => { + _ if self.is_trimable_separated_attribute(element, n) => { let mut value = value.to_string(); let fallback = |n: &mut Attribute| { @@ -2697,9 +2534,7 @@ impl VisitMut for Minifier<'_> { } else { fallback(n); } - } else if self.need_minify_js() - && self.is_javascript_url_element(current_element) - { + } else if self.need_minify_js() && self.is_javascript_url_element(element) { if value.trim().to_lowercase().starts_with("javascript:") { value = value.trim().chars().skip(11).collect(); @@ -2759,6 +2594,163 @@ impl VisitMut for Minifier<'_> { } } } +} + +impl VisitMut for Minifier<'_> { + fn visit_mut_document(&mut self, n: &mut Document) { + n.visit_mut_children_with(self); + + n.children + .retain(|child| !matches!(child, Child::Comment(_) if self.options.remove_comments)); + } + + fn visit_mut_document_fragment(&mut self, n: &mut DocumentFragment) { + n.children = self.minify_children(&mut n.children); + + n.visit_mut_children_with(self); + } + + fn visit_mut_document_type(&mut self, n: &mut DocumentType) { + n.visit_mut_children_with(self); + + if !self.options.force_set_html5_doctype { + return; + } + + n.name = Some(js_word!("html")); + n.system_id = None; + n.public_id = None; + } + + fn visit_mut_child(&mut self, n: &mut Child) { + n.visit_mut_children_with(self); + + self.current_element = None; + + if matches!( + self.options.collapse_whitespaces, + CollapseWhitespaces::Smart + | CollapseWhitespaces::AdvancedConservative + | CollapseWhitespaces::OnlyMetadata + ) { + match n { + Child::Text(_) | Child::Element(_) => { + self.latest_element = Some(n.clone()); + } + _ => {} + } + } + } + + fn visit_mut_element(&mut self, n: &mut Element) { + // Don't copy children to save memory + self.current_element = Some(Element { + span: Default::default(), + tag_name: n.tag_name.clone(), + namespace: n.namespace, + attributes: n.attributes.clone(), + children: vec![], + content: None, + is_self_closing: n.is_self_closing, + }); + + let old_descendant_of_pre = self.descendant_of_pre; + + if self.need_collapse_whitespace() && !old_descendant_of_pre { + self.descendant_of_pre = get_white_space(n.namespace, &n.tag_name) == WhiteSpace::Pre; + } + + n.children = self.minify_children(&mut n.children); + + n.visit_mut_children_with(self); + + // Remove all leading and trailing whitespaces for the `body` element + if n.namespace == Namespace::HTML + && n.tag_name == js_word!("body") + && self.need_collapse_whitespace() + { + self.remove_leading_and_trailing_whitespaces(&mut n.children, true, true); + } + + if self.need_collapse_whitespace() { + self.descendant_of_pre = old_descendant_of_pre; + } + + let mut remove_list = vec![]; + + for (i, i1) in n.attributes.iter().enumerate() { + if i1.value.is_some() { + if self.options.remove_redundant_attributes != RemoveRedundantAttributes::None + && self.is_default_attribute_value(n, i1) + { + remove_list.push(i); + + continue; + } + + if self.options.remove_empty_attributes { + let value = i1.value.as_ref().unwrap(); + + if (matches!(i1.name, js_word!("id")) && value.is_empty()) + || (matches!(i1.name, js_word!("class") | js_word!("style")) + && value.is_empty()) + || self.is_event_handler_attribute(i1) && value.is_empty() + { + remove_list.push(i); + + continue; + } + } + } + + for (j, j1) in n.attributes.iter().enumerate() { + if i < j && i1.name == j1.name { + remove_list.push(j); + } + } + } + + // Fast path. We don't face real duplicates in most cases. + if !remove_list.is_empty() { + let new = take(&mut n.attributes) + .into_iter() + .enumerate() + .filter_map(|(idx, value)| { + if remove_list.contains(&idx) { + None + } else { + Some(value) + } + }) + .collect::>(); + + n.attributes = new; + } + + if let Some(attribute_name_counter) = &self.attribute_name_counter { + n.attributes.sort_by(|a, b| { + let ordeing = attribute_name_counter + .get(&b.name) + .cmp(&attribute_name_counter.get(&a.name)); + + match ordeing { + Ordering::Equal => b.name.cmp(&a.name), + _ => ordeing, + } + }); + } + } + + fn visit_mut_attribute(&mut self, n: &mut Attribute) { + n.visit_mut_children_with(self); + + let element = match &self.current_element { + Some(current_element) => current_element, + _ => return, + }; + + self.minify_attribute(element, n); + } fn visit_mut_text(&mut self, n: &mut Text) { n.visit_mut_children_with(self); diff --git a/crates/swc_html_minifier/tests/fixture/attribute/script-type/output.min.html b/crates/swc_html_minifier/tests/fixture/attribute/script-type/output.min.html index f7c39847dad9..9b94c93741ed 100644 --- a/crates/swc_html_minifier/tests/fixture/attribute/script-type/output.min.html +++ b/crates/swc_html_minifier/tests/fixture/attribute/script-type/output.min.html @@ -3,4 +3,4 @@ test \n - \ No newline at end of file + \ No newline at end of file diff --git a/crates/swc_html_minifier/tests/fixture/element/script-group/input.html b/crates/swc_html_minifier/tests/fixture/element/script-group/input.html index 218581957bae..6fa23d5a6f3c 100644 --- a/crates/swc_html_minifier/tests/fixture/element/script-group/input.html +++ b/crates/swc_html_minifier/tests/fixture/element/script-group/input.html @@ -69,5 +69,17 @@
breaker
+
breaker
+ + + +
breaker
+ + + +
breaker
+ + + \ No newline at end of file diff --git a/crates/swc_html_minifier/tests/fixture/element/script-group/output.min.html b/crates/swc_html_minifier/tests/fixture/element/script-group/output.min.html index 5c54be64d0c7..95f505b2e3af 100644 --- a/crates/swc_html_minifier/tests/fixture/element/script-group/output.min.html +++ b/crates/swc_html_minifier/tests/fixture/element/script-group/output.min.html @@ -41,4 +41,14 @@
breaker
-
breaker
\ No newline at end of file +
breaker
+ + +
breaker
+ + +
breaker
+ + +
breaker
+ \ No newline at end of file diff --git a/crates/swc_html_minifier/tests/fixture/element/style-group/input.html b/crates/swc_html_minifier/tests/fixture/element/style-group/input.html index c40db483849f..5ba9e6bb42d3 100644 --- a/crates/swc_html_minifier/tests/fixture/element/style-group/input.html +++ b/crates/swc_html_minifier/tests/fixture/element/style-group/input.html @@ -88,5 +88,7 @@

Text

test
+
test
+ \ No newline at end of file diff --git a/crates/swc_html_minifier/tests/fixture/element/style-group/output.min.html b/crates/swc_html_minifier/tests/fixture/element/style-group/output.min.html index 03df388ab2ad..b231222997e0 100644 --- a/crates/swc_html_minifier/tests/fixture/element/style-group/output.min.html +++ b/crates/swc_html_minifier/tests/fixture/element/style-group/output.min.html @@ -18,4 +18,6 @@
test
test
- \ No newline at end of file + +
test
+ \ No newline at end of file