diff --git a/crates/swc_html_minifier/src/lib.rs b/crates/swc_html_minifier/src/lib.rs
index dbb855c50104..f64873216cee 100644
--- a/crates/swc_html_minifier/src/lib.rs
+++ b/crates/swc_html_minifier/src/lib.rs
@@ -221,10 +221,10 @@ static COMMA_SEPARATED_SVG_ATTRIBUTES: &[(&str, &str)] = &[("style", "media")];
static SPACE_SEPARATED_GLOBAL_ATTRIBUTES: &[&str] = &[
"class",
- "part",
- "itemtype",
- "itemref",
"itemprop",
+ "itemref",
+ "itemtype",
+ "part",
"accesskey",
"aria-describedby",
"aria-labelledby",
@@ -238,15 +238,16 @@ static SPACE_SEPARATED_HTML_ATTRIBUTES: &[(&str, &str)] = &[
("area", "ping"),
("link", "rel"),
("link", "sizes"),
- ("input", "autocomplete"),
- ("form", "autocomplete"),
+ ("link", "blocking"),
("iframe", "sandbox"),
("td", "headers"),
("th", "headers"),
("output", "for"),
- ("link", "blocking"),
("script", "blocking"),
("style", "blocking"),
+ ("input", "autocomplete"),
+ ("form", "rel"),
+ ("form", "autocomplete"),
];
enum CssMinificationMode {
@@ -331,6 +332,8 @@ struct Minifier {
minify_css: bool,
minify_additional_attributes: Option>,
minify_additional_scripts_content: Option>,
+
+ sort_space_separated_attribute_values: bool,
}
fn get_white_space(namespace: Namespace, tag_name: &str) -> WhiteSpace {
@@ -418,16 +421,40 @@ impl Minifier {
}
}
- fn is_additional_minifier_attribute(&self, name: &str) -> Option {
- if let Some(minify_additional_attributes) = &self.minify_additional_attributes {
- for item in minify_additional_attributes {
- if item.0.is_match(name) {
- return Some(item.1.clone());
- }
- }
+ fn is_attribute_value_unordered_set(&self, element: &Element, attribute_name: &str) -> bool {
+ if matches!(
+ attribute_name,
+ "class" | "part" | "itemprop" | "itemref" | "itemtype"
+ ) {
+ return true;
}
- None
+ match element.namespace {
+ Namespace::HTML => match &*element.tag_name {
+ "link" if attribute_name == "blocking" => true,
+ "script" if attribute_name == "blocking" => true,
+ "style" if attribute_name == "blocking" => true,
+ "output" if attribute_name == "for" => true,
+ "td" if attribute_name == "headers" => true,
+ "th" if attribute_name == "headers" => true,
+ "form" if attribute_name == "rel" => true,
+ "a" if attribute_name == "rel" => true,
+ "area" if attribute_name == "rel" => true,
+ "link" if attribute_name == "rel" => true,
+ "iframe" if attribute_name == "sandbox" => true,
+ "link"
+ if self.element_has_attribute_with_value(
+ element,
+ "rel",
+ &["icon", "apple-touch-icon", "apple-touch-icon-precomposed"],
+ ) && attribute_name == "sizes" =>
+ {
+ true
+ }
+ _ => false,
+ },
+ _ => false,
+ }
}
fn element_has_attribute_with_value(
@@ -866,6 +893,18 @@ impl Minifier {
collapsed
}
+ fn is_additional_minifier_attribute(&self, name: &str) -> Option {
+ if let Some(minify_additional_attributes) = &self.minify_additional_attributes {
+ for item in minify_additional_attributes {
+ if item.0.is_match(name) {
+ return Some(item.1.clone());
+ }
+ }
+ }
+
+ None
+ }
+
fn minify_children(&mut self, children: &mut Vec) {
let (namespace, tag_name) = match &self.current_element {
Some(element) => (element.namespace, &element.tag_name),
@@ -1472,6 +1511,7 @@ impl Minifier {
minify_css: self.minify_css,
minify_additional_scripts_content: self.minify_additional_scripts_content.clone(),
minify_additional_attributes: self.minify_additional_attributes.clone(),
+ sort_space_separated_attribute_values: self.sort_space_separated_attribute_values,
};
match document_or_document_fragment {
@@ -1735,12 +1775,12 @@ impl VisitMut for Minifier {
}
}
- if &*n.name == "class" {
+ if self.sort_space_separated_attribute_values
+ && self.is_attribute_value_unordered_set(current_element, &n.name)
+ {
let mut values = value.split_whitespace().collect::>();
- if &*n.name == "class" {
- values.sort_unstable();
- }
+ values.sort_unstable();
value = values.join(" ");
} else if self.is_event_handler_attribute(&n.name) {
@@ -2025,6 +2065,8 @@ fn create_minifier(context_element: Option<&Element>, options: &MinifyOptions) -
minify_css: options.minify_css,
minify_additional_attributes: options.minify_additional_attributes.clone(),
minify_additional_scripts_content: options.minify_additional_scripts_content.clone(),
+
+ sort_space_separated_attribute_values: options.sort_space_separated_attribute_values,
}
}
diff --git a/crates/swc_html_minifier/src/option.rs b/crates/swc_html_minifier/src/option.rs
index b8091798a031..2994a9c34f79 100644
--- a/crates/swc_html_minifier/src/option.rs
+++ b/crates/swc_html_minifier/src/option.rs
@@ -49,14 +49,6 @@ pub struct MinifyOptions {
pub minify_json: bool,
#[serde(default = "true_by_default")]
pub minify_css: bool,
- /// Allow to compress value of custom attributes,
- /// i.e. ``
- ///
- /// The first item is tag_name
- /// The second is attribute name
- /// The third is type of minifier
- #[serde(default)]
- pub minify_additional_attributes: Option>,
// Allow to compress value of custom script elements,
// i.e. ``
//
@@ -65,6 +57,16 @@ pub struct MinifyOptions {
// The third is type of minifier
#[serde(default)]
pub minify_additional_scripts_content: Option>,
+ /// Allow to compress value of custom attributes,
+ /// i.e. ``
+ ///
+ /// The first item is tag_name
+ /// The second is attribute name
+ /// The third is type of minifier
+ pub minify_additional_attributes: Option>,
+ /// Sorting the values of `class`, `rel`, etc. of attributes
+ #[serde(default = "true_by_default")]
+ pub sort_space_separated_attribute_values: bool,
}
/// Implement default using serde.
diff --git a/crates/swc_html_minifier/tests/fixture/attribute/disabled-normalize_attributes/output.min.html b/crates/swc_html_minifier/tests/fixture/attribute/disabled-normalize_attributes/output.min.html
index 53871d1dbf80..b4c123c2b3cb 100644
--- a/crates/swc_html_minifier/tests/fixture/attribute/disabled-normalize_attributes/output.min.html
+++ b/crates/swc_html_minifier/tests/fixture/attribute/disabled-normalize_attributes/output.min.html
@@ -1,2 +1,2 @@
-Document
+Document
\ No newline at end of file
diff --git a/crates/swc_html_minifier/tests/fixture/attribute/disabled-sort-classes/config.json b/crates/swc_html_minifier/tests/fixture/attribute/disabled-sort-classes/config.json
new file mode 100644
index 000000000000..c5f920933712
--- /dev/null
+++ b/crates/swc_html_minifier/tests/fixture/attribute/disabled-sort-classes/config.json
@@ -0,0 +1,3 @@
+{
+ "sortSpaceSeparatedAttributeValues": false
+}
\ No newline at end of file
diff --git a/crates/swc_html_minifier/tests/fixture/attribute/disabled-sort-classes/input.html b/crates/swc_html_minifier/tests/fixture/attribute/disabled-sort-classes/input.html
new file mode 100644
index 000000000000..10fdeda9e661
--- /dev/null
+++ b/crates/swc_html_minifier/tests/fixture/attribute/disabled-sort-classes/input.html
@@ -0,0 +1,10 @@
+
+
+
+
+ Document
+
+
+
+
+
\ No newline at end of file
diff --git a/crates/swc_html_minifier/tests/fixture/attribute/disabled-sort-classes/output.min.html b/crates/swc_html_minifier/tests/fixture/attribute/disabled-sort-classes/output.min.html
new file mode 100644
index 000000000000..f2d19c943072
--- /dev/null
+++ b/crates/swc_html_minifier/tests/fixture/attribute/disabled-sort-classes/output.min.html
@@ -0,0 +1 @@
+Document
\ No newline at end of file
diff --git a/crates/swc_html_minifier/tests/fixture/attribute/headers/input.html b/crates/swc_html_minifier/tests/fixture/attribute/headers/input.html
index c5d6521aa9a2..ffd9e6976497 100644
--- a/crates/swc_html_minifier/tests/fixture/attribute/headers/input.html
+++ b/crates/swc_html_minifier/tests/fixture/attribute/headers/input.html
@@ -21,6 +21,12 @@
+45342323
Rosevn 56,4300 Sandnes,Norway
+
+
John Doe
+
someone@example.com
+
+45342323
+
Rosevn 56,4300 Sandnes,Norway
+
\ No newline at end of file
diff --git a/crates/swc_html_minifier/tests/fixture/attribute/headers/output.min.html b/crates/swc_html_minifier/tests/fixture/attribute/headers/output.min.html
index ec562270104a..34562677a317 100644
--- a/crates/swc_html_minifier/tests/fixture/attribute/headers/output.min.html
+++ b/crates/swc_html_minifier/tests/fixture/attribute/headers/output.min.html
@@ -11,4 +11,10 @@
+45342323
Rosevn 56,4300 Sandnes,Norway
+
+
John Doe
+
someone@example.com
+
+45342323
+
Rosevn 56,4300 Sandnes,Norway
+
\ No newline at end of file
diff --git a/crates/swc_html_minifier/tests/fixture/attribute/itemtype/output.min.html b/crates/swc_html_minifier/tests/fixture/attribute/itemtype/output.min.html
index 80f4f6adf8e0..2d9be1df9c0f 100644
--- a/crates/swc_html_minifier/tests/fixture/attribute/itemtype/output.min.html
+++ b/crates/swc_html_minifier/tests/fixture/attribute/itemtype/output.min.html
@@ -11,7 +11,7 @@
in excellent condition
In stock! Order now!
-
\ No newline at end of file
diff --git a/crates/swc_html_minifier/tests/fixture/attribute/part/output.min.html b/crates/swc_html_minifier/tests/fixture/attribute/part/output.min.html
index 0b5a3d8eebad..d8fa624da376 100644
--- a/crates/swc_html_minifier/tests/fixture/attribute/part/output.min.html
+++ b/crates/swc_html_minifier/tests/fixture/attribute/part/output.min.html
@@ -1,7 +1,7 @@
Document
- This text will be red
+ This text will be red
\ No newline at end of file
diff --git a/crates/swc_html_minifier/tests/fixture/attribute/rel/input.html b/crates/swc_html_minifier/tests/fixture/attribute/rel/input.html
index a81310f664c5..796f3c7e69f9 100644
--- a/crates/swc_html_minifier/tests/fixture/attribute/rel/input.html
+++ b/crates/swc_html_minifier/tests/fixture/attribute/rel/input.html
@@ -7,5 +7,9 @@
LinkLinkLink
+
\ No newline at end of file
diff --git a/crates/swc_html_minifier/tests/fixture/attribute/rel/output.min.html b/crates/swc_html_minifier/tests/fixture/attribute/rel/output.min.html
index 97b0740ad52e..86da69997e9a 100644
--- a/crates/swc_html_minifier/tests/fixture/attribute/rel/output.min.html
+++ b/crates/swc_html_minifier/tests/fixture/attribute/rel/output.min.html
@@ -1,3 +1,7 @@
-DocumentLink
-Link
-Link
\ No newline at end of file
+DocumentLink
+Link
+Link
+
\ No newline at end of file
diff --git a/crates/swc_html_minifier/tests/fixture/element/iframe/output.min.html b/crates/swc_html_minifier/tests/fixture/element/iframe/output.min.html
index 89858418a885..a13eb63c8ff9 100644
--- a/crates/swc_html_minifier/tests/fixture/element/iframe/output.min.html
+++ b/crates/swc_html_minifier/tests/fixture/element/iframe/output.min.html
@@ -1 +1 @@
-Document
\ No newline at end of file
+Document
\ No newline at end of file
diff --git a/crates/swc_html_minifier/tests/fixture/element/output/input.html b/crates/swc_html_minifier/tests/fixture/element/output/input.html
new file mode 100644
index 000000000000..aaeee57007bd
--- /dev/null
+++ b/crates/swc_html_minifier/tests/fixture/element/output/input.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+ Document
+
+
+
+
+
\ No newline at end of file
diff --git a/crates/swc_html_minifier/tests/fixture/element/output/output.min.html b/crates/swc_html_minifier/tests/fixture/element/output/output.min.html
new file mode 100644
index 000000000000..395164dc12d5
--- /dev/null
+++ b/crates/swc_html_minifier/tests/fixture/element/output/output.min.html
@@ -0,0 +1,5 @@
+Document
\ No newline at end of file
diff --git a/crates/swc_html_minifier/tests/fixture/element/script/input.html b/crates/swc_html_minifier/tests/fixture/element/script/input.html
index 9ab29aa356f5..fced9c2e9ffc 100644
--- a/crates/swc_html_minifier/tests/fixture/element/script/input.html
+++ b/crates/swc_html_minifier/tests/fixture/element/script/input.html
@@ -181,5 +181,6 @@
Party coffee cake recipe
alert('test')
+
diff --git a/crates/swc_html_minifier/tests/fixture/element/script/output.min.html b/crates/swc_html_minifier/tests/fixture/element/script/output.min.html
index 9fa486fca056..e396a1bbb6ac 100644
--- a/crates/swc_html_minifier/tests/fixture/element/script/output.min.html
+++ b/crates/swc_html_minifier/tests/fixture/element/script/output.min.html
@@ -53,4 +53,5 @@
alert('test')
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/crates/swc_html_minifier/tests/fixture/element/style/input.html b/crates/swc_html_minifier/tests/fixture/element/style/input.html
index ef4e8a4d8b00..92eb5ff820d7 100644
--- a/crates/swc_html_minifier/tests/fixture/element/style/input.html
+++ b/crates/swc_html_minifier/tests/fixture/element/style/input.html
@@ -60,5 +60,6 @@
}
+
\ No newline at end of file
diff --git a/crates/swc_html_minifier/tests/fixture/element/style/output.min.html b/crates/swc_html_minifier/tests/fixture/element/style/output.min.html
index 2f66caeb94a2..2fe67eadc5bf 100644
--- a/crates/swc_html_minifier/tests/fixture/element/style/output.min.html
+++ b/crates/swc_html_minifier/tests/fixture/element/style/output.min.html
@@ -23,4 +23,5 @@
color: red
}
-
\ No newline at end of file
+
+
\ No newline at end of file