diff --git a/Cargo.lock b/Cargo.lock index a9b9515023c..9a0cec71ade 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3965,6 +3965,7 @@ dependencies = [ "serde", "serde_json", "swc_atoms", + "swc_cached", "swc_common", "swc_css_codegen", "swc_css_minifier", diff --git a/crates/swc_html_minifier/Cargo.toml b/crates/swc_html_minifier/Cargo.toml index 95096411fea..41037c80bcf 100644 --- a/crates/swc_html_minifier/Cargo.toml +++ b/crates/swc_html_minifier/Cargo.toml @@ -19,6 +19,7 @@ bench = false serde = { version = "1.0.118", features = ["derive"] } serde_json = "1.0.61" swc_atoms = { version = "0.2.9", path = "../swc_atoms" } +swc_cached = { version = "0.1.0", path = "../swc_cached" } swc_common = { version = "0.18.0", path = "../swc_common" } swc_css_codegen = { version = "0.103.0", path = "../swc_css_codegen" } swc_css_parser = { version = "0.102.0", path = "../swc_css_parser" } diff --git a/crates/swc_html_minifier/src/lib.rs b/crates/swc_html_minifier/src/lib.rs index 99f7957b588..c95c105cba6 100644 --- a/crates/swc_html_minifier/src/lib.rs +++ b/crates/swc_html_minifier/src/lib.rs @@ -2,6 +2,7 @@ use serde_json::Value; use swc_atoms::{js_word, JsWord}; +use swc_cached::regex::CachedRegex; use swc_common::{collections::AHashSet, sync::Lrc, FileName, FilePathMapping, SourceMap}; use swc_css_codegen::{ writer::basic::{BasicCssWriter, BasicCssWriterConfig}, @@ -284,6 +285,7 @@ struct Minifier { remove_empty_attributes: bool, collapse_boolean_attributes: bool, minify_css: bool, + preserve_comments: Option>, } impl Minifier { @@ -459,11 +461,9 @@ impl Minifier { ) } - fn is_conditional_comment(&self, data: &str) -> bool { - let trimmed = data.trim(); - - if trimmed.starts_with("[if") || trimmed.ends_with("[endif]") { - return true; + fn is_preserved_comment(&self, data: &str) -> bool { + if let Some(preserve_comments) = &self.preserve_comments { + return preserve_comments.iter().any(|regex| regex.is_match(data)); } false @@ -707,7 +707,7 @@ impl VisitMut for Minifier { index += 1; match child { - Child::Comment(comment) if !self.is_conditional_comment(&comment.data) => false, + Child::Comment(comment) if !self.is_preserved_comment(&comment.data) => false, // Always remove whitespaces from html and head elements (except nested elements), // it should be safe Child::Text(_) @@ -960,5 +960,7 @@ pub fn minify(document: &mut Document, options: &MinifyOptions) { collapse_boolean_attributes: options.collapse_boolean_attributes, minify_css: options.minify_css, + + preserve_comments: options.preserve_comments.clone(), }); } diff --git a/crates/swc_html_minifier/src/option.rs b/crates/swc_html_minifier/src/option.rs index 1d8e57209d1..6553c2ba820 100644 --- a/crates/swc_html_minifier/src/option.rs +++ b/crates/swc_html_minifier/src/option.rs @@ -1,4 +1,5 @@ use serde::{Deserialize, Serialize}; +use swc_cached::regex::CachedRegex; #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -18,6 +19,8 @@ pub struct MinifyOptions { pub collapse_boolean_attributes: bool, #[serde(default = "true_by_default")] pub minify_css: bool, + #[serde(default = "default_preserve_comments")] + pub preserve_comments: Option>, } /// Implement default using serde. @@ -39,3 +42,20 @@ pub enum CollapseWhitespaces { const fn true_by_default() -> bool { true } + +fn default_preserve_comments() -> Option> { + Some(vec![ + // License comments + CachedRegex::new("@preserve").unwrap(), + CachedRegex::new("@copyright").unwrap(), + CachedRegex::new("@lic").unwrap(), + CachedRegex::new("@cc_on").unwrap(), + // Allow to keep custom comments + CachedRegex::new("^!").unwrap(), + // Server-side comments + CachedRegex::new("^\\s*#").unwrap(), + // Conditional IE comments + CachedRegex::new("^\\[if\\s[^\\]+]").unwrap(), + CachedRegex::new("\\[endif]").unwrap(), + ]) +} diff --git a/crates/swc_html_minifier/tests/fixture/comment/basic/input.html b/crates/swc_html_minifier/tests/fixture/comment/basic/input.html new file mode 100644 index 00000000000..b17f46c3007 --- /dev/null +++ b/crates/swc_html_minifier/tests/fixture/comment/basic/input.html @@ -0,0 +1,82 @@ + + + + + + + Document + + + + + + + + + + +

This is a paragraph.

+ + +
baz
+ + + + + + + + + + + + +

+ + + + + + + + + + + According to the conditional comment this is not IE 5-9
+ +

+ + \ No newline at end of file diff --git a/crates/swc_html_minifier/tests/fixture/comment/basic/output.min.html b/crates/swc_html_minifier/tests/fixture/comment/basic/output.min.html new file mode 100644 index 00000000000..2a1b517c878 --- /dev/null +++ b/crates/swc_html_minifier/tests/fixture/comment/basic/output.min.html @@ -0,0 +1,63 @@ +Document + + +

This is a paragraph.

+ + +
baz
+ + + + + + + + + + + +

+ + + + + + + + + + + According to the conditional comment this is not IE 5-9
+ +

+ diff --git a/crates/swc_html_minifier/tests/fixture/comment/preserve-comments/config.json b/crates/swc_html_minifier/tests/fixture/comment/preserve-comments/config.json new file mode 100644 index 00000000000..6da8f95cc43 --- /dev/null +++ b/crates/swc_html_minifier/tests/fixture/comment/preserve-comments/config.json @@ -0,0 +1,3 @@ +{ + "preserveComments": ["^!", "^\\s+ko", "\/ko\\s+$"] +} \ No newline at end of file diff --git a/crates/swc_html_minifier/tests/fixture/comment/input.html b/crates/swc_html_minifier/tests/fixture/comment/preserve-comments/input.html similarity index 93% rename from crates/swc_html_minifier/tests/fixture/comment/input.html rename to crates/swc_html_minifier/tests/fixture/comment/preserve-comments/input.html index bba8a974fe1..b89c83c7c8a 100644 --- a/crates/swc_html_minifier/tests/fixture/comment/input.html +++ b/crates/swc_html_minifier/tests/fixture/comment/preserve-comments/input.html @@ -39,5 +39,7 @@ alert(10) /* ]]> */ + +
  • test
  • \ No newline at end of file diff --git a/crates/swc_html_minifier/tests/fixture/comment/output.min.html b/crates/swc_html_minifier/tests/fixture/comment/preserve-comments/output.min.html similarity index 54% rename from crates/swc_html_minifier/tests/fixture/comment/output.min.html rename to crates/swc_html_minifier/tests/fixture/comment/preserve-comments/output.min.html index 74c59b9fd35..d5a4054ed5d 100644 --- a/crates/swc_html_minifier/tests/fixture/comment/output.min.html +++ b/crates/swc_html_minifier/tests/fixture/comment/preserve-comments/output.min.html @@ -1,10 +1,4 @@ -Document +Document

    This is a paragraph.

    @@ -21,4 +15,6 @@ alert(10) /* ]]> */ + +
  • test