html-minifier 3.5.15 → 3.5.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -11
- package/package.json +2 -2
- package/src/htmlminifier.js +43 -31
- package/src/htmlparser.js +38 -8
package/README.md
CHANGED
|
@@ -22,19 +22,19 @@ How does HTMLMinifier compare to other solutions — [HTML Minifier from Will Pe
|
|
|
22
22
|
|
|
23
23
|
| Site | Original size *(KB)* | HTMLMinifier | minimize | Will Peavy | htmlcompressor.com |
|
|
24
24
|
| ---------------------------------------------------------------------------- |:--------------------:| ------------:| --------:| ----------:| ------------------:|
|
|
25
|
-
| [Google](https://www.google.com/) |
|
|
26
|
-
| [Twitter](https://twitter.com/) |
|
|
27
|
-
| [HTMLMinifier](https://github.com/kangax/html-minifier) |
|
|
28
|
-
| [New York Times](https://www.nytimes.com/) |
|
|
29
|
-
| [Stack Overflow](https://stackoverflow.com/) |
|
|
25
|
+
| [Google](https://www.google.com/) | 50 | **45** | 49 | 51 | 49 |
|
|
26
|
+
| [Twitter](https://twitter.com/) | 128 | **94** | 121 | 140 | 121 |
|
|
27
|
+
| [HTMLMinifier](https://github.com/kangax/html-minifier) | 144 | **112** | 120 | 125 | 120 |
|
|
28
|
+
| [New York Times](https://www.nytimes.com/) | 212 | **145** | 164 | 159 | 148 |
|
|
29
|
+
| [Stack Overflow](https://stackoverflow.com/) | 249 | **194** | 203 | 212 | 201 |
|
|
30
30
|
| [Bootstrap CSS](https://getbootstrap.com/docs/3.3/css/) | 272 | **260** | 269 | 229 | 269 |
|
|
31
|
-
| [BBC](https://www.bbc.co.uk/) |
|
|
32
|
-
| [Amazon](https://www.amazon.co.uk/) |
|
|
33
|
-
| [Wikipedia](https://en.wikipedia.org/wiki/President_of_the_United_States) | 474 | **442** | 458 |
|
|
34
|
-
| [NBC](https://www.nbc.com/) |
|
|
31
|
+
| [BBC](https://www.bbc.co.uk/) | 295 | **237** | 287 | 290 | 272 |
|
|
32
|
+
| [Amazon](https://www.amazon.co.uk/) | 391 | **336** | 377 | 389 | n/a |
|
|
33
|
+
| [Wikipedia](https://en.wikipedia.org/wiki/President_of_the_United_States) | 474 | **442** | 458 | 474 | 458 |
|
|
34
|
+
| [NBC](https://www.nbc.com/) | 689 | **647** | 685 | 687 | n/a |
|
|
35
35
|
| [Eloquent Javascript](https://eloquentjavascript.net/1st_edition/print.html) | 870 | **815** | 840 | 864 | n/a |
|
|
36
|
-
| [ES6 table](https://kangax.github.io/compat-table/es6/) |
|
|
37
|
-
| [ES6 draft](https://tc39.github.io/ecma262/) |
|
|
36
|
+
| [ES6 table](https://kangax.github.io/compat-table/es6/) | 5014 | **4273** | 4745 | n/a | n/a |
|
|
37
|
+
| [ES6 draft](https://tc39.github.io/ecma262/) | 6101 | **5437** | 5599 | n/a | n/a |
|
|
38
38
|
|
|
39
39
|
## Options Quick Reference
|
|
40
40
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "html-minifier",
|
|
3
3
|
"description": "Highly configurable, well-tested, JavaScript-based HTML minifier.",
|
|
4
|
-
"version": "3.5.
|
|
4
|
+
"version": "3.5.16",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
7
7
|
"compress",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
},
|
|
73
73
|
"benchmarkDependencies": {
|
|
74
74
|
"brotli": "1.3.x",
|
|
75
|
-
"chalk": "2.
|
|
75
|
+
"chalk": "2.4.x",
|
|
76
76
|
"cli-table": "0.3.x",
|
|
77
77
|
"lzma": "2.3.x",
|
|
78
78
|
"minimize": "2.2.x",
|
package/src/htmlminifier.js
CHANGED
|
@@ -9,10 +9,7 @@ var UglifyJS = require('uglify-js');
|
|
|
9
9
|
var utils = require('./utils');
|
|
10
10
|
|
|
11
11
|
function trimWhitespace(str) {
|
|
12
|
-
|
|
13
|
-
return str;
|
|
14
|
-
}
|
|
15
|
-
return str.replace(/^[ \n\r\t\f]+/, '').replace(/[ \n\r\t\f]+$/, '');
|
|
12
|
+
return str && str.replace(/^[ \n\r\t\f]+/, '').replace(/[ \n\r\t\f]+$/, '');
|
|
16
13
|
}
|
|
17
14
|
|
|
18
15
|
function collapseWhitespaceAll(str) {
|
|
@@ -258,7 +255,7 @@ function isSrcset(attrName, tag) {
|
|
|
258
255
|
}
|
|
259
256
|
|
|
260
257
|
function cleanAttributeValue(tag, attrName, attrValue, options, attrs) {
|
|
261
|
-
if (
|
|
258
|
+
if (isEventAttribute(attrName, options)) {
|
|
262
259
|
attrValue = trimWhitespace(attrValue).replace(/^javascript:\s*/i, '');
|
|
263
260
|
return options.minifyJS(attrValue, true);
|
|
264
261
|
}
|
|
@@ -314,7 +311,7 @@ function cleanAttributeValue(tag, attrName, attrValue, options, attrs) {
|
|
|
314
311
|
return (+numString).toString();
|
|
315
312
|
});
|
|
316
313
|
}
|
|
317
|
-
else if (
|
|
314
|
+
else if (options.customAttrCollapse && options.customAttrCollapse.test(attrName)) {
|
|
318
315
|
attrValue = attrValue.replace(/\n+|\r+|\s{2,}/g, '');
|
|
319
316
|
}
|
|
320
317
|
else if (tag === 'script' && attrName === 'type') {
|
|
@@ -522,7 +519,7 @@ function canTrimWhitespace(tag) {
|
|
|
522
519
|
}
|
|
523
520
|
|
|
524
521
|
function normalizeAttr(attr, attrs, tag, options) {
|
|
525
|
-
var attrName = options.
|
|
522
|
+
var attrName = options.name(attr.name),
|
|
526
523
|
attrValue = attr.value;
|
|
527
524
|
|
|
528
525
|
if (options.decodeEntities && attrValue) {
|
|
@@ -538,7 +535,9 @@ function normalizeAttr(attr, attrs, tag, options) {
|
|
|
538
535
|
return;
|
|
539
536
|
}
|
|
540
537
|
|
|
541
|
-
|
|
538
|
+
if (attrValue) {
|
|
539
|
+
attrValue = cleanAttributeValue(tag, attrName, attrValue, options, attrs);
|
|
540
|
+
}
|
|
542
541
|
|
|
543
542
|
if (options.removeEmptyAttributes &&
|
|
544
543
|
canDeleteEmptyAttribute(tag, attrName, attrValue, options)) {
|
|
@@ -615,6 +614,9 @@ function identity(value) {
|
|
|
615
614
|
|
|
616
615
|
function processOptions(values) {
|
|
617
616
|
var options = {
|
|
617
|
+
name: function(name) {
|
|
618
|
+
return name.toLowerCase();
|
|
619
|
+
},
|
|
618
620
|
canCollapseWhitespace: canCollapseWhitespace,
|
|
619
621
|
canTrimWhitespace: canTrimWhitespace,
|
|
620
622
|
html5: true,
|
|
@@ -631,7 +633,12 @@ function processOptions(values) {
|
|
|
631
633
|
};
|
|
632
634
|
Object.keys(values).forEach(function(key) {
|
|
633
635
|
var value = values[key];
|
|
634
|
-
if (key === '
|
|
636
|
+
if (key === 'caseSensitive') {
|
|
637
|
+
if (value) {
|
|
638
|
+
options.name = identity;
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
else if (key === 'log') {
|
|
635
642
|
if (typeof value === 'function') {
|
|
636
643
|
options.log = value;
|
|
637
644
|
}
|
|
@@ -732,7 +739,7 @@ function createSortFns(value, options, uidIgnore, uidAttr) {
|
|
|
732
739
|
|
|
733
740
|
function attrNames(attrs) {
|
|
734
741
|
return attrs.map(function(attr) {
|
|
735
|
-
return options.
|
|
742
|
+
return options.name(attr.name);
|
|
736
743
|
});
|
|
737
744
|
}
|
|
738
745
|
|
|
@@ -756,7 +763,7 @@ function createSortFns(value, options, uidIgnore, uidAttr) {
|
|
|
756
763
|
}
|
|
757
764
|
for (var i = 0, len = attrs.length; i < len; i++) {
|
|
758
765
|
var attr = attrs[i];
|
|
759
|
-
if (classChain &&
|
|
766
|
+
if (classChain && attr.value && options.name(attr.name) === 'class') {
|
|
760
767
|
classChain.add(trimWhitespace(attr.value).split(/[ \t\n\f\r]+/).filter(shouldSkipUIDs));
|
|
761
768
|
}
|
|
762
769
|
else if (options.processScripts && attr.name.toLowerCase() === 'type') {
|
|
@@ -946,16 +953,13 @@ function minify(value, options, partialMarkup) {
|
|
|
946
953
|
html5: options.html5,
|
|
947
954
|
|
|
948
955
|
start: function(tag, attrs, unary, unarySlash, autoGenerated) {
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
if (lowerTag === 'svg') {
|
|
956
|
+
if (tag.toLowerCase() === 'svg') {
|
|
952
957
|
options = Object.create(options);
|
|
953
|
-
options.keepClosingSlash = true;
|
|
954
958
|
options.caseSensitive = true;
|
|
959
|
+
options.keepClosingSlash = true;
|
|
960
|
+
options.name = identity;
|
|
955
961
|
}
|
|
956
|
-
|
|
957
|
-
tag = options.caseSensitive ? tag : lowerTag;
|
|
958
|
-
|
|
962
|
+
tag = options.name(tag);
|
|
959
963
|
currentTag = tag;
|
|
960
964
|
charsPrevTag = tag;
|
|
961
965
|
if (!inlineTextTags(tag)) {
|
|
@@ -1035,11 +1039,10 @@ function minify(value, options, partialMarkup) {
|
|
|
1035
1039
|
}
|
|
1036
1040
|
},
|
|
1037
1041
|
end: function(tag, attrs, autoGenerated) {
|
|
1038
|
-
|
|
1039
|
-
if (lowerTag === 'svg') {
|
|
1042
|
+
if (tag.toLowerCase() === 'svg') {
|
|
1040
1043
|
options = Object.getPrototypeOf(options);
|
|
1041
1044
|
}
|
|
1042
|
-
tag = options.
|
|
1045
|
+
tag = options.name(tag);
|
|
1043
1046
|
|
|
1044
1047
|
// check if current tag is in a whitespace stack
|
|
1045
1048
|
if (options.collapseWhitespace) {
|
|
@@ -1271,20 +1274,29 @@ function joinResultSegments(results, options) {
|
|
|
1271
1274
|
var str;
|
|
1272
1275
|
var maxLineLength = options.maxLineLength;
|
|
1273
1276
|
if (maxLineLength) {
|
|
1274
|
-
var
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
line += token;
|
|
1277
|
+
var line = '', lines = [];
|
|
1278
|
+
while (results.length) {
|
|
1279
|
+
var len = line.length;
|
|
1280
|
+
var end = results[0].indexOf('\n');
|
|
1281
|
+
if (end < 0) {
|
|
1282
|
+
line += results.shift();
|
|
1281
1283
|
}
|
|
1282
1284
|
else {
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
+
line += results[0].slice(0, end);
|
|
1286
|
+
results[0] = results[0].slice(end + 1);
|
|
1285
1287
|
}
|
|
1288
|
+
if (len > 0 && line.length >= maxLineLength) {
|
|
1289
|
+
lines.push(line.slice(0, len));
|
|
1290
|
+
line = line.slice(len);
|
|
1291
|
+
}
|
|
1292
|
+
else if (end >= 0) {
|
|
1293
|
+
lines.push(line);
|
|
1294
|
+
line = '';
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
if (line) {
|
|
1298
|
+
lines.push(line);
|
|
1286
1299
|
}
|
|
1287
|
-
lines.push(line);
|
|
1288
1300
|
|
|
1289
1301
|
str = lines.join('\n');
|
|
1290
1302
|
}
|
package/src/htmlparser.js
CHANGED
|
@@ -267,12 +267,36 @@ function HTMLParser(html, handler) {
|
|
|
267
267
|
}
|
|
268
268
|
}
|
|
269
269
|
|
|
270
|
+
function closeIfFound(tagName) {
|
|
271
|
+
if (findTag(tagName) >= 0) {
|
|
272
|
+
parseEndTag('', tagName);
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
270
277
|
function handleStartTag(match) {
|
|
271
278
|
var tagName = match.tagName;
|
|
272
279
|
var unarySlash = match.unarySlash;
|
|
273
280
|
|
|
274
|
-
if (handler.html5
|
|
275
|
-
|
|
281
|
+
if (handler.html5) {
|
|
282
|
+
if (lastTag === 'p' && nonPhrasing(tagName)) {
|
|
283
|
+
parseEndTag('', lastTag);
|
|
284
|
+
}
|
|
285
|
+
else if (tagName === 'tbody') {
|
|
286
|
+
closeIfFound('thead');
|
|
287
|
+
}
|
|
288
|
+
else if (tagName === 'tfoot') {
|
|
289
|
+
if (!closeIfFound('tbody')) {
|
|
290
|
+
closeIfFound('thead');
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
if (tagName === 'col' && findTag('colgroup') < 0) {
|
|
294
|
+
lastTag = 'colgroup';
|
|
295
|
+
stack.push({ tag: lastTag, attrs: [] });
|
|
296
|
+
if (handler.start) {
|
|
297
|
+
handler.start(lastTag, [], false, '');
|
|
298
|
+
}
|
|
299
|
+
}
|
|
276
300
|
}
|
|
277
301
|
|
|
278
302
|
if (!handler.html5 && !inline(tagName)) {
|
|
@@ -353,17 +377,23 @@ function HTMLParser(html, handler) {
|
|
|
353
377
|
}
|
|
354
378
|
}
|
|
355
379
|
|
|
380
|
+
function findTag(tagName) {
|
|
381
|
+
var pos;
|
|
382
|
+
var needle = tagName.toLowerCase();
|
|
383
|
+
for (pos = stack.length - 1; pos >= 0; pos--) {
|
|
384
|
+
if (stack[pos].tag.toLowerCase() === needle) {
|
|
385
|
+
break;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
return pos;
|
|
389
|
+
}
|
|
390
|
+
|
|
356
391
|
function parseEndTag(tag, tagName) {
|
|
357
392
|
var pos;
|
|
358
393
|
|
|
359
394
|
// Find the closest opened tag of the same type
|
|
360
395
|
if (tagName) {
|
|
361
|
-
|
|
362
|
-
for (pos = stack.length - 1; pos >= 0; pos--) {
|
|
363
|
-
if (stack[pos].tag.toLowerCase() === needle) {
|
|
364
|
-
break;
|
|
365
|
-
}
|
|
366
|
-
}
|
|
396
|
+
pos = findTag(tagName);
|
|
367
397
|
}
|
|
368
398
|
// If no tag name is provided, clean shop
|
|
369
399
|
else {
|