html-minifier 3.5.21 → 4.0.0
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 +13 -12
- package/cli.js +1 -0
- package/package.json +21 -21
- package/sample-cli-config-file.conf +1 -0
- package/src/htmlminifier.js +23 -8
- package/src/htmlparser.js +5 -1
package/README.md
CHANGED
|
@@ -20,19 +20,19 @@ How does HTMLMinifier compare to other solutions — [HTML Minifier from Will Pe
|
|
|
20
20
|
|
|
21
21
|
| Site | Original size *(KB)* | HTMLMinifier | minimize | Will Peavy | htmlcompressor.com |
|
|
22
22
|
| ---------------------------------------------------------------------------- |:--------------------:| ------------:| --------:| ----------:| ------------------:|
|
|
23
|
-
| [Google](https://www.google.com/) |
|
|
24
|
-
| [HTMLMinifier](https://github.com/kangax/html-minifier) |
|
|
25
|
-
| [Twitter](https://twitter.com/) |
|
|
26
|
-
| [Stack Overflow](https://stackoverflow.com/) |
|
|
27
|
-
| [Bootstrap CSS](https://getbootstrap.com/docs/3.3/css/) | 271 | **260** | 269 |
|
|
28
|
-
| [BBC](https://www.bbc.co.uk/) |
|
|
29
|
-
| [Amazon](https://www.amazon.co.uk/) |
|
|
30
|
-
| [
|
|
31
|
-
| [
|
|
32
|
-
| [
|
|
23
|
+
| [Google](https://www.google.com/) | 46 | **42** | 46 | 48 | 46 |
|
|
24
|
+
| [HTMLMinifier](https://github.com/kangax/html-minifier) | 125 | **98** | 111 | 117 | 111 |
|
|
25
|
+
| [Twitter](https://twitter.com/) | 207 | **165** | 200 | 224 | 200 |
|
|
26
|
+
| [Stack Overflow](https://stackoverflow.com/) | 253 | **195** | 207 | 215 | 204 |
|
|
27
|
+
| [Bootstrap CSS](https://getbootstrap.com/docs/3.3/css/) | 271 | **260** | 269 | 228 | 269 |
|
|
28
|
+
| [BBC](https://www.bbc.co.uk/) | 298 | **239** | 290 | 291 | 280 |
|
|
29
|
+
| [Amazon](https://www.amazon.co.uk/) | 422 | **316** | 412 | 425 | n/a |
|
|
30
|
+
| [NBC](https://www.nbc.com/) | 553 | **530** | 552 | 553 | 534 |
|
|
31
|
+
| [Wikipedia](https://en.wikipedia.org/wiki/President_of_the_United_States) | 565 | **461** | 548 | 569 | 548 |
|
|
32
|
+
| [New York Times](https://www.nytimes.com/) | 678 | **606** | 675 | 670 | n/a |
|
|
33
33
|
| [Eloquent Javascript](https://eloquentjavascript.net/1st_edition/print.html) | 870 | **815** | 840 | 864 | n/a |
|
|
34
|
-
| [ES6 table](https://kangax.github.io/compat-table/es6/) |
|
|
35
|
-
| [ES draft](https://tc39.github.io/ecma262/) |
|
|
34
|
+
| [ES6 table](https://kangax.github.io/compat-table/es6/) | 5911 | **5051** | 5595 | n/a | n/a |
|
|
35
|
+
| [ES draft](https://tc39.github.io/ecma262/) | 6126 | **5495** | 5664 | n/a | n/a |
|
|
36
36
|
|
|
37
37
|
## Options Quick Reference
|
|
38
38
|
|
|
@@ -45,6 +45,7 @@ Most of the options are disabled by default.
|
|
|
45
45
|
| `collapseInlineTagWhitespace` | Don't leave any spaces between `display:inline;` elements when collapsing. Must be used in conjunction with `collapseWhitespace=true` | `false` |
|
|
46
46
|
| `collapseWhitespace` | [Collapse white space that contributes to text nodes in a document tree](http://perfectionkills.com/experimenting-with-html-minifier/#collapse_whitespace) | `false` |
|
|
47
47
|
| `conservativeCollapse` | Always collapse to 1 space (never remove it entirely). Must be used in conjunction with `collapseWhitespace=true` | `false` |
|
|
48
|
+
| `continueOnParseError` | [Handle parse errors](https://html.spec.whatwg.org/multipage/parsing.html#parse-errors) instead of aborting. | `false` |
|
|
48
49
|
| `customAttrAssign` | Arrays of regex'es that allow to support custom attribute assign expressions (e.g. `'<div flex?="{{mode != cover}}"></div>'`) | `[ ]` |
|
|
49
50
|
| `customAttrCollapse` | Regex that specifies custom attribute to strip newlines from (e.g. `/ng-class/`) | |
|
|
50
51
|
| `customAttrSurround` | Arrays of regex'es that allow to support custom attribute surround expressions (e.g. `<input {{#if value}}checked="checked"{{/if}}>`) | `[ ]` |
|
package/cli.js
CHANGED
|
@@ -103,6 +103,7 @@ var mainOptions = {
|
|
|
103
103
|
collapseInlineTagWhitespace: 'Collapse white space around inline tag',
|
|
104
104
|
collapseWhitespace: 'Collapse white space that contributes to text nodes in a document tree.',
|
|
105
105
|
conservativeCollapse: 'Always collapse to 1 space (never remove it entirely)',
|
|
106
|
+
continueOnParseError: 'Handle parse errors instead of aborting',
|
|
106
107
|
customAttrAssign: ['Arrays of regex\'es that allow to support custom attribute assign expressions (e.g. \'<div flex?="{{mode != cover}}"></div>\')', parseJSONRegExpArray],
|
|
107
108
|
customAttrCollapse: ['Regex that specifies custom attribute to strip newlines from (e.g. /ng-class/)', parseRegExp],
|
|
108
109
|
customAttrSurround: ['Arrays of regex\'es that allow to support custom attribute surround expressions (e.g. <input {{#if value}}checked="checked"{{/if}}>)', parseJSONRegExpArray],
|
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": "
|
|
4
|
+
"version": "4.0.0",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
7
7
|
"compress",
|
|
@@ -47,36 +47,36 @@
|
|
|
47
47
|
"url": "https://github.com/kangax/html-minifier/issues"
|
|
48
48
|
},
|
|
49
49
|
"engines": {
|
|
50
|
-
"node": ">=
|
|
50
|
+
"node": ">=6"
|
|
51
51
|
},
|
|
52
52
|
"scripts": {
|
|
53
53
|
"dist": "grunt dist",
|
|
54
54
|
"test": "grunt test"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"camel-case": "3.0.
|
|
58
|
-
"clean-css": "4.2.
|
|
59
|
-
"commander": "2.
|
|
60
|
-
"he": "1.2.
|
|
61
|
-
"param-case": "2.1.
|
|
62
|
-
"relateurl": "0.2.
|
|
63
|
-
"uglify-js": "3.
|
|
57
|
+
"camel-case": "^3.0.0",
|
|
58
|
+
"clean-css": "^4.2.1",
|
|
59
|
+
"commander": "^2.19.0",
|
|
60
|
+
"he": "^1.2.0",
|
|
61
|
+
"param-case": "^2.1.1",
|
|
62
|
+
"relateurl": "^0.2.7",
|
|
63
|
+
"uglify-js": "^3.5.1"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"grunt": "1.0.
|
|
67
|
-
"grunt-browserify": "5.3.
|
|
68
|
-
"grunt-contrib-uglify": "
|
|
69
|
-
"
|
|
70
|
-
"phantomjs-prebuilt": "2.1.
|
|
71
|
-
"qunit": "2.
|
|
66
|
+
"grunt": "^1.0.4",
|
|
67
|
+
"grunt-browserify": "^5.3.0",
|
|
68
|
+
"grunt-contrib-uglify": "^4.0.1",
|
|
69
|
+
"grunt-eslint": "^21.0.0",
|
|
70
|
+
"phantomjs-prebuilt": "^2.1.16",
|
|
71
|
+
"qunit": "^2.9.2"
|
|
72
72
|
},
|
|
73
73
|
"benchmarkDependencies": {
|
|
74
|
-
"brotli": "1.3.
|
|
75
|
-
"chalk": "2.4.
|
|
76
|
-
"cli-table": "0.3.
|
|
77
|
-
"lzma": "2.3.
|
|
78
|
-
"minimize": "2.2.
|
|
79
|
-
"progress": "2.0.
|
|
74
|
+
"brotli": "^1.3.2",
|
|
75
|
+
"chalk": "^2.4.2",
|
|
76
|
+
"cli-table": "^0.3.1",
|
|
77
|
+
"lzma": "^2.3.2",
|
|
78
|
+
"minimize": "^2.2.0",
|
|
79
|
+
"progress": "^2.0.3"
|
|
80
80
|
},
|
|
81
81
|
"files": [
|
|
82
82
|
"src/*.js",
|
package/src/htmlminifier.js
CHANGED
|
@@ -311,6 +311,9 @@ function cleanAttributeValue(tag, attrName, attrValue, options, attrs) {
|
|
|
311
311
|
return (+numString).toString();
|
|
312
312
|
});
|
|
313
313
|
}
|
|
314
|
+
else if (isContentSecurityPolicy(tag, attrs) && attrName.toLowerCase() === 'content') {
|
|
315
|
+
return collapseWhitespaceAll(attrValue);
|
|
316
|
+
}
|
|
314
317
|
else if (options.customAttrCollapse && options.customAttrCollapse.test(attrName)) {
|
|
315
318
|
attrValue = attrValue.replace(/\n+|\r+|\s{2,}/g, '');
|
|
316
319
|
}
|
|
@@ -335,6 +338,17 @@ function isMetaViewport(tag, attrs) {
|
|
|
335
338
|
}
|
|
336
339
|
}
|
|
337
340
|
|
|
341
|
+
function isContentSecurityPolicy(tag, attrs) {
|
|
342
|
+
if (tag !== 'meta') {
|
|
343
|
+
return false;
|
|
344
|
+
}
|
|
345
|
+
for (var i = 0, len = attrs.length; i < len; i++) {
|
|
346
|
+
if (attrs[i].name.toLowerCase() === 'http-equiv' && attrs[i].value.toLowerCase() === 'content-security-policy') {
|
|
347
|
+
return true;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
338
352
|
function ignoreCSS(id) {
|
|
339
353
|
return '/* clean-css ignore:start */' + id + '/* clean-css ignore:end */';
|
|
340
354
|
}
|
|
@@ -864,19 +878,19 @@ function minify(value, options, partialMarkup) {
|
|
|
864
878
|
value = value.replace(reCustomIgnore, function(match) {
|
|
865
879
|
if (!uidAttr) {
|
|
866
880
|
uidAttr = uniqueId(value);
|
|
867
|
-
uidPattern = new RegExp('(\\s*)' + uidAttr + '([0-9]+)(\\s*)', 'g');
|
|
881
|
+
uidPattern = new RegExp('(\\s*)' + uidAttr + '([0-9]+)' + uidAttr + '(\\s*)', 'g');
|
|
868
882
|
if (options.minifyCSS) {
|
|
869
883
|
options.minifyCSS = (function(fn) {
|
|
870
884
|
return function(text, type) {
|
|
871
885
|
text = text.replace(uidPattern, function(match, prefix, index) {
|
|
872
886
|
var chunks = ignoredCustomMarkupChunks[+index];
|
|
873
|
-
return chunks[1] + uidAttr + index + chunks[2];
|
|
887
|
+
return chunks[1] + uidAttr + index + uidAttr + chunks[2];
|
|
874
888
|
});
|
|
875
889
|
var ids = [];
|
|
876
890
|
new CleanCSS().minify(wrapCSS(text, type)).warnings.forEach(function(warning) {
|
|
877
891
|
var match = uidPattern.exec(warning);
|
|
878
892
|
if (match) {
|
|
879
|
-
var id = uidAttr + match[2];
|
|
893
|
+
var id = uidAttr + match[2] + uidAttr;
|
|
880
894
|
text = text.replace(id, ignoreCSS(id));
|
|
881
895
|
ids.push(id);
|
|
882
896
|
}
|
|
@@ -894,13 +908,13 @@ function minify(value, options, partialMarkup) {
|
|
|
894
908
|
return function(text, type) {
|
|
895
909
|
return fn(text.replace(uidPattern, function(match, prefix, index) {
|
|
896
910
|
var chunks = ignoredCustomMarkupChunks[+index];
|
|
897
|
-
return chunks[1] + uidAttr + index + chunks[2];
|
|
911
|
+
return chunks[1] + uidAttr + index + uidAttr + chunks[2];
|
|
898
912
|
}), type);
|
|
899
913
|
};
|
|
900
914
|
})(options.minifyJS);
|
|
901
915
|
}
|
|
902
916
|
}
|
|
903
|
-
var token = uidAttr + ignoredCustomMarkupChunks.length;
|
|
917
|
+
var token = uidAttr + ignoredCustomMarkupChunks.length + uidAttr;
|
|
904
918
|
ignoredCustomMarkupChunks.push(/^(\s*)[\s\S]*?(\s*)$/.exec(match));
|
|
905
919
|
return '\t' + token + '\t';
|
|
906
920
|
});
|
|
@@ -965,6 +979,9 @@ function minify(value, options, partialMarkup) {
|
|
|
965
979
|
|
|
966
980
|
new HTMLParser(value, {
|
|
967
981
|
partialMarkup: partialMarkup,
|
|
982
|
+
continueOnParseError: options.continueOnParseError,
|
|
983
|
+
customAttrAssign: options.customAttrAssign,
|
|
984
|
+
customAttrSurround: options.customAttrSurround,
|
|
968
985
|
html5: options.html5,
|
|
969
986
|
|
|
970
987
|
start: function(tag, attrs, unary, unarySlash, autoGenerated) {
|
|
@@ -1241,9 +1258,7 @@ function minify(value, options, partialMarkup) {
|
|
|
1241
1258
|
buffer.push(options.useShortDoctype ? '<!doctype' +
|
|
1242
1259
|
(options.removeTagWhitespace ? '' : ' ') + 'html>' :
|
|
1243
1260
|
collapseWhitespaceAll(doctype));
|
|
1244
|
-
}
|
|
1245
|
-
customAttrAssign: options.customAttrAssign,
|
|
1246
|
-
customAttrSurround: options.customAttrSurround
|
|
1261
|
+
}
|
|
1247
1262
|
});
|
|
1248
1263
|
|
|
1249
1264
|
if (options.removeOptionalTags) {
|
package/src/htmlparser.js
CHANGED
|
@@ -182,6 +182,11 @@ function HTMLParser(html, handler) {
|
|
|
182
182
|
prevTag = startTagMatch.tagName.toLowerCase();
|
|
183
183
|
continue;
|
|
184
184
|
}
|
|
185
|
+
|
|
186
|
+
// Treat `<` as text
|
|
187
|
+
if (handler.continueOnParseError) {
|
|
188
|
+
textEnd = html.indexOf('<', 1);
|
|
189
|
+
}
|
|
185
190
|
}
|
|
186
191
|
|
|
187
192
|
var text;
|
|
@@ -213,7 +218,6 @@ function HTMLParser(html, handler) {
|
|
|
213
218
|
handler.chars(text, prevTag, nextTag);
|
|
214
219
|
}
|
|
215
220
|
prevTag = '';
|
|
216
|
-
|
|
217
221
|
}
|
|
218
222
|
else {
|
|
219
223
|
var stackedTag = lastTag.toLowerCase();
|