feat(html/minifier): Add preserve_comments option (#4959)

This commit is contained in:
Alexander Akait 2022-06-16 07:26:53 +03:00 committed by GitHub
parent 4b340e2c1b
commit 2e52c18a6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 183 additions and 13 deletions

1
Cargo.lock generated
View File

@ -3965,6 +3965,7 @@ dependencies = [
"serde",
"serde_json",
"swc_atoms",
"swc_cached",
"swc_common",
"swc_css_codegen",
"swc_css_minifier",

View File

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

View File

@ -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<Vec<CachedRegex>>,
}
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(),
});
}

View File

@ -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<Vec<CachedRegex>>,
}
/// Implement default using serde.
@ -39,3 +42,20 @@ pub enum CollapseWhitespaces {
const fn true_by_default() -> bool {
true
}
fn default_preserve_comments() -> Option<Vec<CachedRegex>> {
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(),
])
}

View File

@ -0,0 +1,82 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<!--[if !IE]>-->
<link href="non-ie.css" rel="stylesheet">
<!--<![endif]-->
<!--[if IE]>
<link type="text/css" rel="stylesheet" href="/stylesheets/no-ie.css">
<![endif]-->
<!--[if IE 8]>
<link href="ie8only.css" rel="stylesheet">
<![endif]-->
<!-- [if IE 8]>
<link href="ie8only.css" rel="stylesheet">
<![endif] -->
</head>
<body>
<p>This is a paragraph.</p>
<!-- Test -->
<!-- foo --><div>baz</div><!-- bar
moo -->
<script><!-- alert(1) --></script>
<script><!--
alert(1);
--></script>
<style type="text/css"><!-- p { color: red } --></style>
<script>/*<![CDATA[*/alert(8)/*]]>*/</script>
<script type="text/javascript"> /*
<![CDATA[ */
alert(10)
/* ]]> */
</script>
<!-- @preserve foo -->
<!-- @copyright foo -->
<!-- @lic foo -->
<!-- @cc_on foo -->
<!--! my custom comment -->
<!--#include virtual="/cgi-bin/counter.pl" -->
<p class="accent">
<!--[if IE]>
According to the conditional comment this is IE<br />
<![endif]-->
<!--[if IE 6]>
According to the conditional comment this is IE 6<br />
<![endif]-->
<!--[if IE 7]>
According to the conditional comment this is IE 7<br />
<![endif]-->
<!--[if IE 8]>
According to the conditional comment this is IE 8<br />
<![endif]-->
<!--[if IE 9]>
According to the conditional comment this is IE 9<br />
<![endif]-->
<!--[if gte IE 8]>
According to the conditional comment this is IE 8 or higher<br />
<![endif]-->
<!--[if lt IE 9]>
According to the conditional comment this is IE lower than 9<br />
<![endif]-->
<!--[if lte IE 7]>
According to the conditional comment this is IE lower or equal to 7<br />
<![endif]-->
<!--[if gt IE 6]>
According to the conditional comment this is IE greater than 6<br />
<![endif]-->
<!--[if !IE]> -->
According to the conditional comment this is not IE 5-9<br />
<!-- <![endif]-->
</p>
</body>
</html>

View File

@ -0,0 +1,63 @@
<!doctype html><html lang=en><meta charset=UTF-8><meta name=viewport content="width=device-width,user-scalable=no,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0"><meta http-equiv=X-UA-Compatible content="ie=edge"><title>Document</title><!--[if !IE]>--><link href=non-ie.css rel=stylesheet><!--<![endif]--><!--[if IE]>
<link type="text/css" rel="stylesheet" href="/stylesheets/no-ie.css">
<![endif]--><!--[if IE 8]>
<link href="ie8only.css" rel="stylesheet">
<![endif]--><!-- [if IE 8]>
<link href="ie8only.css" rel="stylesheet">
<![endif] --><body>
<p>This is a paragraph.</p>
<div>baz</div>
<script><!-- alert(1) --></script>
<script><!--
alert(1);
--></script>
<style>p{color:red}</style><script>/*<![CDATA[*/alert(8)/*]]>*/</script>
<script> /*
<![CDATA[ */
alert(10)
/* ]]> */
</script>
<!-- @preserve foo -->
<!-- @copyright foo -->
<!-- @lic foo -->
<!-- @cc_on foo -->
<!--! my custom comment -->
<!--#include virtual="/cgi-bin/counter.pl" -->
<p class=accent>
<!--[if IE]>
According to the conditional comment this is IE<br />
<![endif]-->
<!--[if IE 6]>
According to the conditional comment this is IE 6<br />
<![endif]-->
<!--[if IE 7]>
According to the conditional comment this is IE 7<br />
<![endif]-->
<!--[if IE 8]>
According to the conditional comment this is IE 8<br />
<![endif]-->
<!--[if IE 9]>
According to the conditional comment this is IE 9<br />
<![endif]-->
<!--[if gte IE 8]>
According to the conditional comment this is IE 8 or higher<br />
<![endif]-->
<!--[if lt IE 9]>
According to the conditional comment this is IE lower than 9<br />
<![endif]-->
<!--[if lte IE 7]>
According to the conditional comment this is IE lower or equal to 7<br />
<![endif]-->
<!--[if gt IE 6]>
According to the conditional comment this is IE greater than 6<br />
<![endif]-->
<!--[if !IE]> -->
According to the conditional comment this is not IE 5-9<br>
<!-- <![endif]-->
</p>

View File

@ -0,0 +1,3 @@
{
"preserveComments": ["^!", "^\\s+ko", "\/ko\\s+$"]
}

View File

@ -39,5 +39,7 @@
alert(10)
/* ]]> */
</script>
<!--! test -->
<!-- ko if: someExpressionGoesHere --><li>test</li><!-- /ko -->
</body>
</html>

View File

@ -1,10 +1,4 @@
<!doctype html><html lang=en><meta charset=UTF-8><meta name=viewport content="width=device-width,user-scalable=no,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0"><meta http-equiv=X-UA-Compatible content="ie=edge"><title>Document</title><!--[if !IE]>--><link href=non-ie.css rel=stylesheet><!--<![endif]--><!--[if IE]>
<link type="text/css" rel="stylesheet" href="/stylesheets/no-ie.css">
<![endif]--><!--[if IE 8]>
<link href="ie8only.css" rel="stylesheet">
<![endif]--><!-- [if IE 8]>
<link href="ie8only.css" rel="stylesheet">
<![endif] --><body>
<!doctype html><html lang=en><meta charset=UTF-8><meta name=viewport content="width=device-width,user-scalable=no,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0"><meta http-equiv=X-UA-Compatible content="ie=edge"><title>Document</title><link href=non-ie.css rel=stylesheet><body>
<p>This is a paragraph.</p>
@ -21,4 +15,6 @@
alert(10)
/* ]]> */
</script>
<!--! test -->
<!-- ko if: someExpressionGoesHere --><li>test</li><!-- /ko -->