mirror of
https://github.com/swc-project/swc.git
synced 2024-11-28 02:29:04 +03:00
feat(html/minifier): Compress default values of attributes (#4427)
This commit is contained in:
parent
c7aa0fe86b
commit
4c699f2554
@ -47,16 +47,6 @@ static BOOLEAN_ATTRIBUTES: &[&str] = &[
|
|||||||
"visible",
|
"visible",
|
||||||
];
|
];
|
||||||
|
|
||||||
static EXECUTABLE_SCRIPTS_MIME_TYPES: &[&str] = &[
|
|
||||||
"text/javascript",
|
|
||||||
"text/ecmascript",
|
|
||||||
"text/jscript",
|
|
||||||
"application/javascript",
|
|
||||||
"application/x-javascript",
|
|
||||||
"application/ecmascript",
|
|
||||||
"module",
|
|
||||||
];
|
|
||||||
|
|
||||||
struct Minifier {}
|
struct Minifier {}
|
||||||
|
|
||||||
impl Minifier {
|
impl Minifier {
|
||||||
@ -64,6 +54,99 @@ impl Minifier {
|
|||||||
BOOLEAN_ATTRIBUTES.contains(&name)
|
BOOLEAN_ATTRIBUTES.contains(&name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_default_attribute_value(
|
||||||
|
&self,
|
||||||
|
namespace: Namespace,
|
||||||
|
tag_name: &str,
|
||||||
|
attribute_name: &str,
|
||||||
|
attribute_value: &str,
|
||||||
|
) -> bool {
|
||||||
|
matches!(
|
||||||
|
(
|
||||||
|
namespace,
|
||||||
|
tag_name,
|
||||||
|
attribute_name,
|
||||||
|
attribute_value.to_ascii_lowercase().trim()
|
||||||
|
),
|
||||||
|
(Namespace::HTML, "iframe", "height", "150")
|
||||||
|
| (Namespace::HTML, "iframe", "width", "300")
|
||||||
|
| (Namespace::HTML, "iframe", "frameborder", "1")
|
||||||
|
| (Namespace::HTML, "iframe", "loading", "eager")
|
||||||
|
| (Namespace::HTML, "iframe", "fetchpriority", "auto")
|
||||||
|
| (
|
||||||
|
Namespace::HTML,
|
||||||
|
"iframe",
|
||||||
|
"referrerpolicy",
|
||||||
|
"strict-origin-when-cross-origin"
|
||||||
|
)
|
||||||
|
| (
|
||||||
|
Namespace::HTML,
|
||||||
|
"a",
|
||||||
|
"referrerpolicy",
|
||||||
|
"strict-origin-when-cross-origin"
|
||||||
|
)
|
||||||
|
| (Namespace::HTML, "a", "target", "_self")
|
||||||
|
| (Namespace::HTML, "area", "target", "_self")
|
||||||
|
| (Namespace::HTML, "area", "shape", "rect")
|
||||||
|
| (
|
||||||
|
Namespace::HTML,
|
||||||
|
"area",
|
||||||
|
"referrerpolicy",
|
||||||
|
"strict-origin-when-cross-origin"
|
||||||
|
)
|
||||||
|
| (Namespace::HTML, "form", "method", "get")
|
||||||
|
| (Namespace::HTML, "form", "target", "_self")
|
||||||
|
| (Namespace::HTML, "input", "type", "text")
|
||||||
|
| (Namespace::HTML, "input", "size", "20")
|
||||||
|
| (Namespace::HTML, "track", "kind", "subtitles")
|
||||||
|
| (Namespace::HTML, "textarea", "cols", "20")
|
||||||
|
| (Namespace::HTML, "textarea", "rows", "2")
|
||||||
|
| (Namespace::HTML, "textarea", "wrap", "sort")
|
||||||
|
| (Namespace::HTML, "progress", "max", "1")
|
||||||
|
| (Namespace::HTML, "meter", "min", "0")
|
||||||
|
| (Namespace::HTML, "img", "decoding", "auto")
|
||||||
|
| (Namespace::HTML, "img", "fetchpriority", "auto")
|
||||||
|
| (Namespace::HTML, "img", "loading", "eager")
|
||||||
|
| (
|
||||||
|
Namespace::HTML,
|
||||||
|
"img",
|
||||||
|
"referrerpolicy",
|
||||||
|
"strict-origin-when-cross-origin"
|
||||||
|
)
|
||||||
|
| (Namespace::HTML, "link", "type", "text/css")
|
||||||
|
| (Namespace::HTML, "link", "fetchpriority", "auto")
|
||||||
|
| (
|
||||||
|
Namespace::HTML,
|
||||||
|
"link",
|
||||||
|
"referrerpolicy",
|
||||||
|
"strict-origin-when-cross-origin"
|
||||||
|
)
|
||||||
|
| (Namespace::HTML, "style", "type", "text/css")
|
||||||
|
| (Namespace::HTML, "script", "type", "text/javascript")
|
||||||
|
| (Namespace::HTML, "script", "type", "text/ecmascript")
|
||||||
|
| (Namespace::HTML, "script", "type", "text/jscript")
|
||||||
|
| (Namespace::HTML, "script", "type", "application/javascript")
|
||||||
|
| (
|
||||||
|
Namespace::HTML,
|
||||||
|
"script",
|
||||||
|
"type",
|
||||||
|
"application/x-javascript"
|
||||||
|
)
|
||||||
|
| (Namespace::HTML, "script", "type", "application/ecmascript")
|
||||||
|
| (Namespace::HTML, "script", "fetchpriority", "auto")
|
||||||
|
| (
|
||||||
|
Namespace::HTML,
|
||||||
|
"script",
|
||||||
|
"referrerpolicy",
|
||||||
|
"strict-origin-when-cross-origin"
|
||||||
|
)
|
||||||
|
| (Namespace::HTML, "ol", "type", "1")
|
||||||
|
| (Namespace::HTML, "base", "target", "_self")
|
||||||
|
| (Namespace::HTML, "canvas", "height", "150")
|
||||||
|
| (Namespace::HTML, "canvas", "width", "300")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn is_conditional_comment(&self, data: &str) -> bool {
|
fn is_conditional_comment(&self, data: &str) -> bool {
|
||||||
let trimmed = data.trim();
|
let trimmed = data.trim();
|
||||||
|
|
||||||
@ -80,40 +163,23 @@ impl VisitMut for Minifier {
|
|||||||
n.visit_mut_children_with(self);
|
n.visit_mut_children_with(self);
|
||||||
|
|
||||||
n.children.retain(|child| !matches!(child, Child::Comment(comment) if !self.is_conditional_comment(&comment.data)));
|
n.children.retain(|child| !matches!(child, Child::Comment(comment) if !self.is_conditional_comment(&comment.data)));
|
||||||
n.attributes.retain(|attribute| match &*attribute.name {
|
n.attributes.retain(|attribute| {
|
||||||
"type"
|
if attribute.value.is_none() {
|
||||||
if n.namespace == Namespace::HTML
|
return true;
|
||||||
&& matches!(n.tag_name.as_ref(), "script")
|
|
||||||
&& (attribute.value.is_some()
|
|
||||||
&& attribute
|
|
||||||
.value
|
|
||||||
.as_ref()
|
|
||||||
.map(|v| {
|
|
||||||
EXECUTABLE_SCRIPTS_MIME_TYPES
|
|
||||||
.iter()
|
|
||||||
.any(|mime| v.eq_str_ignore_ascii_case(mime))
|
|
||||||
})
|
|
||||||
.unwrap_or_default()) =>
|
|
||||||
{
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
"type"
|
|
||||||
if n.namespace == Namespace::HTML
|
match &*attribute.name {
|
||||||
&& matches!(n.tag_name.as_ref(), "style" | "link")
|
_ if self.is_default_attribute_value(
|
||||||
&& (attribute.value.is_some()
|
n.namespace,
|
||||||
&& matches!(
|
&n.tag_name,
|
||||||
attribute
|
&attribute.name,
|
||||||
.value
|
attribute.value.as_ref().unwrap(),
|
||||||
.as_ref()
|
) =>
|
||||||
.unwrap()
|
{
|
||||||
.to_ascii_lowercase()
|
false
|
||||||
.trim(),
|
}
|
||||||
"text/css"
|
_ => true,
|
||||||
)) =>
|
|
||||||
{
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
_ => true,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
<!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>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<iframe id="test" src="test.html" frameborder="1" height="150" width="300" loading="eager" fetchpriority="auto" referrerpolicy="strict-origin-when-cross-origin"></iframe>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,10 @@
|
|||||||
|
<!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>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<iframe id=test src=test.html></iframe>
|
||||||
|
|
||||||
|
</body></html>
|
@ -0,0 +1,9 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>Document</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<img src="test.png" alt="test" decoding="auto" loading="eager" referrerpolicy="strict-origin-when-cross-origin">
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,7 @@
|
|||||||
|
<!doctype html><html lang=en><head>
|
||||||
|
<title>Document</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<img src=test.png alt=test>
|
||||||
|
|
||||||
|
</body></html>
|
@ -0,0 +1,12 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>Document</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<input name="a" type="text">
|
||||||
|
<input name="b" type="TEXT">
|
||||||
|
<input name="c" type=" TEXT ">
|
||||||
|
<input name="d" size=" 20 ">
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,10 @@
|
|||||||
|
<!doctype html><html lang=en><head>
|
||||||
|
<title>Document</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<input name=a>
|
||||||
|
<input name=b>
|
||||||
|
<input name=c>
|
||||||
|
<input name=d>
|
||||||
|
|
||||||
|
</body></html>
|
@ -0,0 +1,14 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>Document</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<meter id="fuel"
|
||||||
|
min="0" max="100"
|
||||||
|
low="33" high="66" optimum="80"
|
||||||
|
value="50">
|
||||||
|
at 50/100
|
||||||
|
</meter>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,9 @@
|
|||||||
|
<!doctype html><html lang=en><head>
|
||||||
|
<title>Document</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<meter id=fuel max=100 low=33 high=66 optimum=80 value=50>
|
||||||
|
at 50/100
|
||||||
|
</meter>
|
||||||
|
|
||||||
|
</body></html>
|
@ -0,0 +1,15 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>Document</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<ol type="1">
|
||||||
|
<li>Mix flour, baking powder, sugar, and salt.</li>
|
||||||
|
<li>In another bowl, mix eggs, milk, and oil.</li>
|
||||||
|
<li>Stir both mixtures together.</li>
|
||||||
|
<li>Fill muffin tray 3/4 full.</li>
|
||||||
|
<li>Bake for 20 minutes.</li>
|
||||||
|
</ol>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,13 @@
|
|||||||
|
<!doctype html><html lang=en><head>
|
||||||
|
<title>Document</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<ol>
|
||||||
|
<li>Mix flour, baking powder, sugar, and salt.</li>
|
||||||
|
<li>In another bowl, mix eggs, milk, and oil.</li>
|
||||||
|
<li>Stir both mixtures together.</li>
|
||||||
|
<li>Fill muffin tray 3/4 full.</li>
|
||||||
|
<li>Bake for 20 minutes.</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
</body></html>
|
@ -0,0 +1,9 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>Document</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<progress max="1"></progress>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,7 @@
|
|||||||
|
<!doctype html><html lang=en><head>
|
||||||
|
<title>Document</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<progress></progress>
|
||||||
|
|
||||||
|
</body></html>
|
@ -4,7 +4,7 @@
|
|||||||
<script>
|
<script>
|
||||||
console.log();
|
console.log();
|
||||||
</script>
|
</script>
|
||||||
<script>
|
<script type=module>
|
||||||
console.log();
|
console.log();
|
||||||
</script>
|
</script>
|
||||||
</head><body></body></html>
|
</head><body></body></html>
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>Document</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<textarea name="test" id="test" cols="20" rows="2"></textarea>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,7 @@
|
|||||||
|
<!doctype html><html lang=en><head>
|
||||||
|
<title>Document</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<textarea name=test id=test></textarea>
|
||||||
|
</>
|
||||||
|
</></body></html>
|
@ -0,0 +1,31 @@
|
|||||||
|
<!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>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<video controls
|
||||||
|
src="/media/cc0-videos/friday.mp4">
|
||||||
|
<track default
|
||||||
|
kind="captions"
|
||||||
|
srclang="en"
|
||||||
|
src="/media/examples/friday.vtt" />
|
||||||
|
Sorry, your browser doesn't support embedded videos.
|
||||||
|
</video>
|
||||||
|
|
||||||
|
<video controls
|
||||||
|
src="/media/cc0-videos/friday.mp4">
|
||||||
|
<track default
|
||||||
|
kind="subtitles"
|
||||||
|
srclang="en"
|
||||||
|
src="/media/examples/friday.vtt" />
|
||||||
|
Sorry, your browser doesn't support embedded videos.
|
||||||
|
</video>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,20 @@
|
|||||||
|
<!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>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<video controls src=/media/cc0-videos/friday.mp4>
|
||||||
|
<track default kind=captions srclang=en src=/media/examples/friday.vtt>
|
||||||
|
Sorry, your browser doesn't support embedded videos.
|
||||||
|
</video>
|
||||||
|
|
||||||
|
<video controls src=/media/cc0-videos/friday.mp4>
|
||||||
|
<track default srclang=en src=/media/examples/friday.vtt>
|
||||||
|
Sorry, your browser doesn't support embedded videos.
|
||||||
|
</video>
|
||||||
|
|
||||||
|
|
||||||
|
</body></html>
|
Loading…
Reference in New Issue
Block a user