feat(html/minifier): Compress whitespaces (#4463)

This commit is contained in:
Alexander Akait 2022-04-28 05:30:53 +03:00 committed by GitHub
parent 8c520919fd
commit 0ae43502f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 392 additions and 9 deletions

View File

@ -47,6 +47,22 @@ static BOOLEAN_ATTRIBUTES: &[&str] = &[
"visible",
];
// TODO improve list - event handlers + remove multiple whitespace from class +
// test for custom elements
static ALLOW_TO_TRIM_ATTRIBUTES: &[&str] = &[
"id",
"class",
"style",
"tabindex",
"maxlength",
"size",
"rows",
"cols",
"span",
"rowspan",
"colspan",
];
struct Minifier {}
impl Minifier {
@ -54,6 +70,10 @@ impl Minifier {
BOOLEAN_ATTRIBUTES.contains(&name)
}
fn allow_to_trim(&self, name: &str) -> bool {
ALLOW_TO_TRIM_ATTRIBUTES.contains(&name)
}
fn is_default_attribute_value(
&self,
namespace: Namespace,
@ -178,6 +198,11 @@ impl VisitMut for Minifier {
{
false
}
_ if matches!(&*attribute.name, "id" | "class" | "style")
&& (&*attribute.value.as_ref().unwrap()).trim().is_empty() =>
{
false
}
_ => true,
}
});
@ -186,12 +211,23 @@ impl VisitMut for Minifier {
fn visit_mut_attribute(&mut self, n: &mut Attribute) {
n.visit_mut_children_with(self);
match &n.name {
name if n.value.is_some() && self.is_boolean_attribute(name) => {
n.value = None;
}
_ => {}
if n.value.is_none() {
return;
}
if self.is_boolean_attribute(&n.name) {
n.value = None;
return;
}
let mut value: &str = &*(n.value.as_ref().unwrap().clone());
if self.allow_to_trim(&n.name) {
value = value.trim();
}
n.value = Some(value.into());
}
}

View File

@ -7,6 +7,7 @@
<p><button autofocus value="next">Button</button></p>
<p><button autofocus="autofocus" value="next">Button</button></p>
<p><button autofocus=" autofocus " value="next">Button</button></p>
<p><button autofocus="true" value="next">Button</button></p>
<p><button autofocus="false" value="next">Button</button></p>

View File

@ -7,6 +7,7 @@
<p><button autofocus value=next>Button</button></p>
<p><button autofocus value=next>Button</button></p>
<p><button autofocus value=next>Button</button></p>
<p><button autofocus value=next>Button</button></p>
<img draggable=false>
<img draggable=true>

View File

@ -0,0 +1,25 @@
<!doctype html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<p class=" foo bar ">foo bar baz</p>
<p class=" foo ">foo bar baz</p>
<p class="
foo
">foo bar baz</p>
<p class="
foo
class1 class-23 ">foo bar baz</p>
</body>
</html>

View File

@ -0,0 +1,15 @@
<!doctype html><html lang=en><head>
<title>Document</title>
</head>
<body>
<p class="foo bar">foo bar baz</p>
<p class=foo>foo bar baz</p>
<p class=foo>foo bar baz</p>
<p class="foo
class1 class-23">foo bar baz</p>
</body></html>

View File

@ -0,0 +1,19 @@
<!doctype html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<input
class="form-control"
type="text"
style=""
id="{{vm.formInputName}}"
name="{{vm.formInputName}}"
placeholder="YYYY-MM-DD" date-range-picker
data-ng-model="vm.value"
data-ng-model-options="{ debounce: 1000 }"
data-ng-pattern="vm.options.format"
data-options="vm.datepickerOptions">
</body>
</html>

View File

@ -0,0 +1,7 @@
<!doctype html><html lang=en><head>
<title>Document</title>
</head>
<body>
<input class=form-control id={{vm.formInputName}} name={{vm.formInputName}} placeholder=YYYY-MM-DD date-range-picker data-ng-model=vm.value data-ng-model-options="{ debounce: 1000 }" data-ng-pattern=vm.options.format data-options=vm.datepickerOptions>
</body></html>

View File

@ -0,0 +1,18 @@
<!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>
<div
data-test="one"
data-test="two"
></div>
<img src="test.png" alt="one" alt="two">
</body>
</html>

View File

@ -0,0 +1,12 @@
<!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>
<div data-test=one data-test=two></div>
<img src=test.png alt=one alt=two>
</body></html>

View File

@ -0,0 +1,25 @@
<!doctype html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<p id="" class="" STYLE=" " title="\n" lang="" dir="">x</p>
<p
onclick=""
ondblclick=" "
onmousedown=""
ONMOUSEUP=""
onmouseover=" "
onmousemove=""
onmouseout=""
onkeypress=
"
"
onkeydown=
""
onkeyup
="">x</p>
</body>
</html>

View File

@ -0,0 +1,9 @@
<!doctype html><html lang=en><head>
<title>Document</title>
</head>
<body>
<p title=\n lang="" dir="">x</p>
<p onclick="" ondblclick=" " onmousedown="" onmouseup="" onmouseover=" " onmousemove="" onmouseout="" onkeypress="
" onkeydown="" onkeyup="">x</p>
</body></html>

View File

@ -12,6 +12,8 @@
<form action="handler.php" method="get">
<input type="text" name="str">
<input type="submit" value="send">
<input type=" TEXT " value="foo">
<input type="checkbox">
</form>
</body>
</html>

View File

@ -10,6 +10,8 @@
<form action=handler.php>
<input name=str>
<input type=submit value=send>
<input value=foo>
<input type=checkbox>
</form>

View File

@ -16,5 +16,8 @@
test"></div>
<div data-test=" test ' test ' test"></div>
<div data-test=' test " test " test'></div>
<div data='{ "test": "test" }'></div>
<div data="{ 'test': 'test' }"></div>
<div data="{&#34;test&#34;:&#34;\\&#34;test\\&#34;&#34;}"></div>'
</body>
</html>

View File

@ -13,5 +13,8 @@
test"></div>
<div data-test=" test ' test ' test"></div>
<div data-test=' test " test " test'></div>
<div data='{ "test": "test" }'></div>
<div data="{ 'test': 'test' }"></div>
<div data='{"test":"\\"test\\""}'></div>'
</body></html>

View File

@ -7,3 +7,4 @@
<script type="module">
console.log();
</script>
<script>window.jQuery || document.write('<script src="jquery.js"><\/script>')</script>

View File

@ -7,4 +7,4 @@
<script type=module>
console.log();
</script>
</head><body></body></html>
<script>window.jQuery || document.write('&lt;script src="jquery.js"&gt;&lt;\/script&gt;')</script></head><body></body></html>

View File

@ -0,0 +1,32 @@
<!doctype html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<p title="bar">foo</p>
<p
title
=
"bar"
>foo</p
>
<img src="test"/>
<img src="test"
/>
<img
src="test"
>
<p title = "bar">foo</p>
<p title = "bar">foo</p>
<p title = 'bar'>foo</p>
<p title = bar>foo</p>
</body>
</html>

View File

@ -0,0 +1,15 @@
<!doctype html><html lang=en><head>
<title>Document</title>
</head>
<body>
<p title=bar>foo</p>
<p title=bar>foo</p>
<img src=test>
<img src=test>
<img src=test>
<p title=bar>foo</p>
<p title=bar>foo</p>
<p title=bar>foo</p>
<p title=bar>foo</p>
</body></html>

View File

@ -28,6 +28,7 @@
</style>
</head>
<body>
<p style=" color: red; background-color: rgb(100, 75, 200); "></p>
<p style=" "></p>
</body>
</html>

View File

@ -26,6 +26,7 @@
</style>
</head>
<body>
<p style="color: red; background-color: rgb(100, 75, 200);"></p>
<p></p>
</body></html>

View File

@ -0,0 +1 @@
<a href="#" tabindex=" 1 ">x</a><button tabindex=" 2 ">y</button>

View File

@ -0,0 +1 @@
<html><head></head><body><a href=# tabindex=1>x</a><button tabindex=2>y</button></body></html>

View File

@ -24,6 +24,20 @@
<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>
</body>
</html>

View File

@ -21,6 +21,18 @@
<p>This is a paragraph.</p>
<div>baz</div>
<script>&lt;!-- alert(1) --&gt;</script>
<script>&lt;!--
alert(1);
--&gt;</script>
<style>&lt;!-- p { color: red } --&gt;</style>
<script>/*&lt;![CDATA[*/alert(8)/*]]&gt;*/</script>
<script> /*
&lt;![CDATA[ */
alert(10)
/* ]]&gt; */
</script>
</body></html>

View File

@ -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>
<DIV DATA-TEST="Test">TEST</DIV>
<P>blah<SPAN>blah 2<SPAN>blah 3</SPAN></SPAN></P>
<P>foo</p>
<DIV>boo</DIV>
<DIV title="moo">boo</DiV>
<DIV TITLE="blah">boo</DIV>
<DIV tItLe="blah">boo</DIV>
<DiV tItLe="blah">boo</DIV>
</BODY>
</HTML>

View File

@ -0,0 +1,17 @@
<!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>
<div data-test=Test>TEST</div>
<p>blah<span>blah 2<span>blah 3</span></span></p>
<p>foo</p>
<div>boo</div>
<div title=moo>boo</div>
<div title=blah>boo</div>
<div title=blah>boo</div>
<div title=blah>boo</div>
</body></html>

View File

@ -0,0 +1,11 @@
<!doctype html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<a href="test.html"><div>hey</div></a>
<a href>ok</a>
<a onclick></a>
</body>
</html>

View File

@ -0,0 +1,9 @@
<!doctype html><html lang=en><head>
<title>Document</title>
</head>
<body>
<a href=test.html><div>hey</div></a>
<a href>ok</a>
<a onclick></a>
</body></html>

View File

@ -0,0 +1,10 @@
<!doctype html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
test<br>test
test<br/>test
</body>
</html>

View File

@ -0,0 +1,8 @@
<!doctype html><html lang=en><head>
<title>Document</title>
</head>
<body>
test<br>test
test<br>test
</body></html>

View File

@ -0,0 +1,14 @@
<!doctype html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<begriffs.pagination ng-init="perPage=20" collection="logs" url="\'/api/logs?user=-1\'" per-page="perPage" per-page-presets="[10,20,50,100]" template-url="/assets/paginate-anything.html"></begriffs.pagination>
<some-tag-1></some-tag-1><some-tag-2></some-tag-2>
[\']["]
<CUSTOM-TAG></CUSTOM-TAG><div>Hello :)</div>
<tag v-ref:vm_pv :imgs=" objpicsurl_ "></tag>
<span><phrasing-element></phrasing-element></span>
</body>
</html>

View File

@ -0,0 +1,12 @@
<!doctype html><html lang=en><head>
<title>Document</title>
</head>
<body>
<begriffs.pagination ng-init="perPage=20" collection=logs url="\'/api/logs?user=-1\'" per-page=perPage per-page-presets=[10,20,50,100] template-url=/assets/paginate-anything.html></begriffs.pagination>
<some-tag-1></some-tag-1><some-tag-2></some-tag-2>
[\']["]
<custom-tag></custom-tag><div>Hello :)</div>
<tag v-ref:vm_pv :imgs=" objpicsurl_ "></tag>
<span><phrasing-element></phrasing-element></span>
</body></html>

View File

@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<p>For more information, read <a href=https://stackoverflow.com/questions/17408815/fieldset-resizes-wrong-appears-to-have-unremovable-min-width-min-content/17863685#17863685>this Stack Overflow answer</a>.</p>
<p>a<div>b</div>
<p>a<ul><li>item</li></ul>
<p>a</p><ol><li>item</li></ol>
</body>
</html>

View File

@ -0,0 +1,10 @@
<!doctype html><html lang=en><head>
<title>Document</title>
</head>
<body>
<p>For more information, read <a href=https://stackoverflow.com/questions/17408815/fieldset-resizes-wrong-appears-to-have-unremovable-min-width-min-content/17863685#17863685>this Stack Overflow answer</a>.</p>
<p>a</p><div>b</div>
<p>a</p><ul><li>item</li></ul>
<p>a</p><ol><li>item</li></ol>
</body></html>

View File

@ -29,5 +29,7 @@
<div>The cent sign: &cent;</div>
<div>The cent sign: &#162;</div>
:) <a href="http://example.com">link</a>
</body>
</html>

View File

@ -27,5 +27,7 @@
<div>The cent sign: ¢</div>
<div>The cent sign: ¢</div>
:) <a href=http://example.com>link</a>
</body></html>