html-minifier 2.1.6 → 2.1.7
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 -13
- package/package.json +2 -2
- package/src/htmlminifier.js +55 -23
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ See [corresponding blog post](http://perfectionkills.com/experimenting-with-html
|
|
|
12
12
|
|
|
13
13
|
[Test suite is available online](http://kangax.github.io/html-minifier/tests/).
|
|
14
14
|
|
|
15
|
-
Also see corresponding [Ruby wrapper](https://github.com/stereobooster/html_minifier), and for Node.js, [Grunt plugin](https://github.com/gruntjs/grunt-contrib-htmlmin), [Gulp module](https://github.com/jonschlinkert/gulp-htmlmin),
|
|
15
|
+
Also see corresponding [Ruby wrapper](https://github.com/stereobooster/html_minifier), and for Node.js, [Grunt plugin](https://github.com/gruntjs/grunt-contrib-htmlmin), [Gulp module](https://github.com/jonschlinkert/gulp-htmlmin), [Koa middleware wrapper](https://github.com/koajs/html-minifier) and [Express middleware wrapper](https://github.com/melonmanchan/express-minify-html).
|
|
16
16
|
|
|
17
17
|
For lint-like capabilities take a look at [HTMLLint](https://github.com/kangax/html-lint).
|
|
18
18
|
|
|
@@ -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/) | 48 | **46** | 48 | 50 |
|
|
26
|
-
| [
|
|
27
|
-
| [
|
|
28
|
-
| [BBC](http://www.bbc.co.uk/) |
|
|
29
|
-
| [New York Times](http://www.nytimes.com/) |
|
|
30
|
-
| [Stack Overflow](http://stackoverflow.com/) |
|
|
25
|
+
| [Google](https://www.google.com/) | 48 | **46** | 48 | 50 | 48 |
|
|
26
|
+
| [CNN](http://www.cnn.com/) | 115 | **105** | 111 | 113 | 109 |
|
|
27
|
+
| [HTMLMinifier](https://github.com/kangax/html-minifier) | 117 | **79** | 99 | 103 | 99 |
|
|
28
|
+
| [BBC](http://www.bbc.co.uk/) | 179 | **147** | 172 | 177 | 168 |
|
|
29
|
+
| [New York Times](http://www.nytimes.com/) | 186 | **127** | 136 | 140 | 134 |
|
|
30
|
+
| [Stack Overflow](http://stackoverflow.com/) | 240 | **186** | 195 | 204 | 193 |
|
|
31
31
|
| [Bootstrap CSS](http://getbootstrap.com/css/) | 277 | **264** | 274 | 232 | 274 |
|
|
32
|
-
| [Amazon](http://www.amazon.co.uk/) |
|
|
33
|
-
| [Wikipedia](https://en.wikipedia.org/wiki/President_of_the_United_States) |
|
|
34
|
-
| [NBC](http://www.nbc.com/) | 508 | **
|
|
32
|
+
| [Amazon](http://www.amazon.co.uk/) | 431 | **377** | 412 | 424 | n/a |
|
|
33
|
+
| [Wikipedia](https://en.wikipedia.org/wiki/President_of_the_United_States) | 481 | **437** | 464 | 479 | n/a |
|
|
34
|
+
| [NBC](http://www.nbc.com/) | 508 | **486** | 506 | 508 | n/a |
|
|
35
35
|
| [Eloquent Javascript](http://eloquentjavascript.net/1st_edition/print.html) | 870 | **815** | 840 | 864 | n/a |
|
|
36
|
-
| [ES6 table](http://kangax.github.io/compat-table/es6/) |
|
|
37
|
-
| [ES6 draft](https://tc39.github.io/ecma262/) |
|
|
36
|
+
| [ES6 table](http://kangax.github.io/compat-table/es6/) | 3884 | **3272** | 3664 | 3839 | n/a |
|
|
37
|
+
| [ES6 draft](https://tc39.github.io/ecma262/) | 4797 | **4247** | 4377 | 4500 | n/a |
|
|
38
38
|
|
|
39
39
|
## Options Quick Reference
|
|
40
40
|
|
|
@@ -56,7 +56,7 @@ How does HTMLMinifier compare to other solutions — [HTML Minifier from Will Pe
|
|
|
56
56
|
| `includeAutoGeneratedTags` | Insert tags generated by HTML parser | `true` |
|
|
57
57
|
| `keepClosingSlash` | Keep the trailing slash on singleton elements | `false` |
|
|
58
58
|
| `maxLineLength` | Specify a maximum line length. Compressed output will be split by newlines at valid HTML split-points |
|
|
59
|
-
| `minifyCSS` | Minify CSS in style elements and style attributes (uses [clean-css](https://github.com/jakubpawlowicz/clean-css)) | `false` (could be `true`, `Object`, `Function(text
|
|
59
|
+
| `minifyCSS` | Minify CSS in style elements and style attributes (uses [clean-css](https://github.com/jakubpawlowicz/clean-css)) | `false` (could be `true`, `Object`, `Function(text)`) |
|
|
60
60
|
| `minifyJS` | Minify JavaScript in script elements and event attributes (uses [UglifyJS](https://github.com/mishoo/UglifyJS2)) | `false` (could be `true`, `Object`, `Function(text, inline)`) |
|
|
61
61
|
| `minifyURLs` | Minify URLs in various attributes (uses [relateurl](https://github.com/stevenvachon/relateurl)) | `false` (could be `String`, `Object`, `Function(text)`) |
|
|
62
62
|
| `preserveLineBreaks` | Always collapse to 1 line break (never remove it entirely) when whitespace between tags include a line break. Must be used in conjunction with `collapseWhitespace=true` | `false` |
|
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": "2.1.
|
|
4
|
+
"version": "2.1.7",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
7
7
|
"compress",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"grunt": "1.0.x",
|
|
67
67
|
"grunt-browserify": "5.0.x",
|
|
68
68
|
"grunt-contrib-uglify": "1.0.x",
|
|
69
|
-
"grunt-eslint": "
|
|
69
|
+
"grunt-eslint": "19.0.x",
|
|
70
70
|
"phantomjs-prebuilt": "2.1.x",
|
|
71
71
|
"qunitjs": "2.x"
|
|
72
72
|
},
|
package/src/htmlminifier.js
CHANGED
|
@@ -228,17 +228,21 @@ function isNumberTypeAttribute(attrName, tag) {
|
|
|
228
228
|
);
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
-
function
|
|
231
|
+
function isLinkType(tag, attrs, value) {
|
|
232
232
|
if (tag !== 'link') {
|
|
233
233
|
return false;
|
|
234
234
|
}
|
|
235
235
|
for (var i = 0, len = attrs.length; i < len; i++) {
|
|
236
|
-
if (attrs[i].name === 'rel' && attrs[i].value ===
|
|
236
|
+
if (attrs[i].name === 'rel' && attrs[i].value === value) {
|
|
237
237
|
return true;
|
|
238
238
|
}
|
|
239
239
|
}
|
|
240
240
|
}
|
|
241
241
|
|
|
242
|
+
function isMediaQuery(tag, attrs, attrName) {
|
|
243
|
+
return attrName === 'media' && (isLinkType(tag, attrs, 'stylesheet') || isStyleSheet(tag, attrs));
|
|
244
|
+
}
|
|
245
|
+
|
|
242
246
|
var srcsetTags = createMapFromString('img,source');
|
|
243
247
|
|
|
244
248
|
function isSrcset(attrName, tag) {
|
|
@@ -262,17 +266,20 @@ function cleanAttributeValue(tag, attrName, attrValue, options, attrs) {
|
|
|
262
266
|
}
|
|
263
267
|
else if (isUriTypeAttribute(attrName, tag)) {
|
|
264
268
|
attrValue = trimWhitespace(attrValue);
|
|
265
|
-
return
|
|
269
|
+
return isLinkType(tag, attrs, 'canonical') ? attrValue : options.minifyURLs(attrValue);
|
|
266
270
|
}
|
|
267
271
|
else if (isNumberTypeAttribute(attrName, tag)) {
|
|
268
272
|
return trimWhitespace(attrValue);
|
|
269
273
|
}
|
|
270
274
|
else if (attrName === 'style') {
|
|
271
275
|
attrValue = trimWhitespace(attrValue);
|
|
272
|
-
if (attrValue
|
|
273
|
-
attrValue
|
|
276
|
+
if (attrValue) {
|
|
277
|
+
if (/;$/.test(attrValue) && !/&#?[0-9a-zA-Z]+;$/.test(attrValue)) {
|
|
278
|
+
attrValue = attrValue.replace(/\s*;$/, '');
|
|
279
|
+
}
|
|
280
|
+
attrValue = unwrapInlineCSS(options.minifyCSS(wrapInlineCSS(attrValue)));
|
|
274
281
|
}
|
|
275
|
-
return
|
|
282
|
+
return attrValue;
|
|
276
283
|
}
|
|
277
284
|
else if (isSrcset(attrName, tag)) {
|
|
278
285
|
// https://html.spec.whatwg.org/multipage/embedded-content.html#attr-img-srcset
|
|
@@ -305,6 +312,10 @@ function cleanAttributeValue(tag, attrName, attrValue, options, attrs) {
|
|
|
305
312
|
else if (tag === 'script' && attrName === 'type') {
|
|
306
313
|
attrValue = trimWhitespace(attrValue.replace(/\s*;\s*/g, ';'));
|
|
307
314
|
}
|
|
315
|
+
else if (isMediaQuery(tag, attrs, attrName)) {
|
|
316
|
+
attrValue = trimWhitespace(attrValue);
|
|
317
|
+
return unwrapMediaQuery(options.minifyCSS(wrapMediaQuery(attrValue)));
|
|
318
|
+
}
|
|
308
319
|
return attrValue;
|
|
309
320
|
}
|
|
310
321
|
|
|
@@ -321,16 +332,22 @@ function isMetaViewport(tag, attrs) {
|
|
|
321
332
|
|
|
322
333
|
// Wrap CSS declarations for CleanCSS > 3.x
|
|
323
334
|
// See https://github.com/jakubpawlowicz/clean-css/issues/418
|
|
324
|
-
function
|
|
335
|
+
function wrapInlineCSS(text) {
|
|
325
336
|
return '*{' + text + '}';
|
|
326
337
|
}
|
|
327
338
|
|
|
328
|
-
function
|
|
329
|
-
var matches = text.match(/^\*\{([\s\S]*)\}$/
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
339
|
+
function unwrapInlineCSS(text) {
|
|
340
|
+
var matches = text.match(/^\*\{([\s\S]*)\}$/);
|
|
341
|
+
return matches ? matches[1] : text;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
function wrapMediaQuery(text) {
|
|
345
|
+
return '@media ' + text + '{a{top:0}}';
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
function unwrapMediaQuery(text) {
|
|
349
|
+
var matches = text.match(/^@media ([\s\S]*?)\s*{[\s\S]*}$/);
|
|
350
|
+
return matches ? matches[1] : text;
|
|
334
351
|
}
|
|
335
352
|
|
|
336
353
|
function cleanConditionalComment(comment, options) {
|
|
@@ -685,18 +702,14 @@ function processOptions(options) {
|
|
|
685
702
|
if (typeof minifyCSS.advanced === 'undefined') {
|
|
686
703
|
minifyCSS.advanced = false;
|
|
687
704
|
}
|
|
688
|
-
options.minifyCSS = function(text
|
|
705
|
+
options.minifyCSS = function(text) {
|
|
689
706
|
text = text.replace(/(url\s*\(\s*)("|'|)(.*?)\2(\s*\))/ig, function(match, prefix, quote, url, suffix) {
|
|
690
707
|
return prefix + quote + options.minifyURLs(url) + quote + suffix;
|
|
691
708
|
});
|
|
692
709
|
var start = text.match(/^\s*<!--/);
|
|
693
710
|
var style = start ? text.slice(start[0].length).replace(/-->\s*$/, '') : text;
|
|
694
711
|
try {
|
|
695
|
-
|
|
696
|
-
if (inline) {
|
|
697
|
-
return unwrapCSS(cleanCSS.minify(wrapCSS(style)).styles);
|
|
698
|
-
}
|
|
699
|
-
return cleanCSS.minify(style).styles;
|
|
712
|
+
return new CleanCSS(minifyCSS).minify(style).styles;
|
|
700
713
|
}
|
|
701
714
|
catch (err) {
|
|
702
715
|
options.log(err);
|
|
@@ -709,7 +722,7 @@ function processOptions(options) {
|
|
|
709
722
|
function uniqueId(value) {
|
|
710
723
|
var id;
|
|
711
724
|
do {
|
|
712
|
-
id = Math.random().toString(36).
|
|
725
|
+
id = Math.random().toString(36).replace(/^0\.[0-9]*/, '');
|
|
713
726
|
} while (~value.indexOf(id));
|
|
714
727
|
return id;
|
|
715
728
|
}
|
|
@@ -822,7 +835,8 @@ function minify(value, options, partialMarkup) {
|
|
|
822
835
|
ignoredMarkupChunks = [],
|
|
823
836
|
ignoredCustomMarkupChunks = [],
|
|
824
837
|
uidIgnore,
|
|
825
|
-
uidAttr
|
|
838
|
+
uidAttr,
|
|
839
|
+
uidPattern;
|
|
826
840
|
|
|
827
841
|
// temporarily replace ignored chunks with comments,
|
|
828
842
|
// so that we don't have to worry what's there.
|
|
@@ -846,6 +860,24 @@ function minify(value, options, partialMarkup) {
|
|
|
846
860
|
value = value.replace(reCustomIgnore, function(match) {
|
|
847
861
|
if (!uidAttr) {
|
|
848
862
|
uidAttr = uniqueId(value);
|
|
863
|
+
uidPattern = new RegExp('(\\s*)' + uidAttr + '([0-9]+)(\\s*)', 'g');
|
|
864
|
+
var minifyCSS = options.minifyCSS;
|
|
865
|
+
if (minifyCSS) {
|
|
866
|
+
options.minifyCSS = function(text) {
|
|
867
|
+
return minifyCSS(text).replace(uidPattern, function(match, prefix, index, suffix) {
|
|
868
|
+
return (prefix && '\t') + uidAttr + index + (suffix && '\t');
|
|
869
|
+
});
|
|
870
|
+
};
|
|
871
|
+
}
|
|
872
|
+
var minifyJS = options.minifyJS;
|
|
873
|
+
if (minifyJS) {
|
|
874
|
+
var pattern = new RegExp('(\\\\t|)' + uidAttr + '([0-9]+)(\\\\t|)', 'g');
|
|
875
|
+
options.minifyJS = function(text, inline) {
|
|
876
|
+
return minifyJS(text, inline).replace(pattern, function(match, prefix, index, suffix) {
|
|
877
|
+
return (prefix && '\t') + uidAttr + index + (suffix && '\t');
|
|
878
|
+
});
|
|
879
|
+
};
|
|
880
|
+
}
|
|
849
881
|
}
|
|
850
882
|
var token = uidAttr + ignoredCustomMarkupChunks.length;
|
|
851
883
|
ignoredCustomMarkupChunks.push(match);
|
|
@@ -1203,8 +1235,8 @@ function minify(value, options, partialMarkup) {
|
|
|
1203
1235
|
|
|
1204
1236
|
var str = joinResultSegments(buffer, options);
|
|
1205
1237
|
|
|
1206
|
-
if (
|
|
1207
|
-
str = str.replace(
|
|
1238
|
+
if (uidPattern) {
|
|
1239
|
+
str = str.replace(uidPattern, function(match, prefix, index, suffix) {
|
|
1208
1240
|
var chunk = ignoredCustomMarkupChunks[+index];
|
|
1209
1241
|
if (options.collapseWhitespace) {
|
|
1210
1242
|
if (prefix !== '\t') {
|