html-minifier 3.5.12 → 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 +12 -12
- package/package.json +3 -4
- package/src/htmlminifier.js +160 -150
- package/src/htmlparser.js +44 -9
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
|
-
| [
|
|
27
|
-
| [
|
|
28
|
-
| [New York Times](https://www.nytimes.com/) |
|
|
29
|
-
| [Stack Overflow](https://stackoverflow.com/) |
|
|
30
|
-
| [BBC](https://www.bbc.co.uk/) | 271 | **220** | 264 | 267 | 252 |
|
|
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 |
|
|
31
30
|
| [Bootstrap CSS](https://getbootstrap.com/docs/3.3/css/) | 272 | **260** | 269 | 229 | 269 |
|
|
32
|
-
| [
|
|
33
|
-
| [
|
|
34
|
-
| [
|
|
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
|
|
|
@@ -58,7 +58,7 @@ Most of the options are disabled by default.
|
|
|
58
58
|
| `includeAutoGeneratedTags` | Insert tags generated by HTML parser | `true` |
|
|
59
59
|
| `keepClosingSlash` | Keep the trailing slash on singleton elements | `false` |
|
|
60
60
|
| `maxLineLength` | Specify a maximum line length. Compressed output will be split by newlines at valid HTML split-points |
|
|
61
|
-
| `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)`) |
|
|
61
|
+
| `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, type)`) |
|
|
62
62
|
| `minifyJS` | Minify JavaScript in script elements and event attributes (uses [UglifyJS](https://github.com/mishoo/UglifyJS2)) | `false` (could be `true`, `Object`, `Function(text, inline)`) |
|
|
63
63
|
| `minifyURLs` | Minify URLs in various attributes (uses [relateurl](https://github.com/stevenvachon/relateurl)) | `false` (could be `String`, `Object`, `Function(text)`) |
|
|
64
64
|
| `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": "3.5.
|
|
4
|
+
"version": "3.5.16",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
7
7
|
"compress",
|
|
@@ -58,14 +58,13 @@
|
|
|
58
58
|
"clean-css": "4.1.x",
|
|
59
59
|
"commander": "2.15.x",
|
|
60
60
|
"he": "1.1.x",
|
|
61
|
-
"ncname": "1.0.x",
|
|
62
61
|
"param-case": "2.1.x",
|
|
63
62
|
"relateurl": "0.2.x",
|
|
64
63
|
"uglify-js": "3.3.x"
|
|
65
64
|
},
|
|
66
65
|
"devDependencies": {
|
|
67
66
|
"grunt": "1.0.x",
|
|
68
|
-
"grunt-browserify": "5.
|
|
67
|
+
"grunt-browserify": "5.3.x",
|
|
69
68
|
"grunt-contrib-uglify": "3.3.x",
|
|
70
69
|
"gruntify-eslint": "4.0.x",
|
|
71
70
|
"phantomjs-prebuilt": "2.1.x",
|
|
@@ -73,7 +72,7 @@
|
|
|
73
72
|
},
|
|
74
73
|
"benchmarkDependencies": {
|
|
75
74
|
"brotli": "1.3.x",
|
|
76
|
-
"chalk": "2.
|
|
75
|
+
"chalk": "2.4.x",
|
|
77
76
|
"cli-table": "0.3.x",
|
|
78
77
|
"lzma": "2.3.x",
|
|
79
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) {
|
|
@@ -67,9 +64,9 @@ function collapseWhitespace(str, options, trimLeft, trimRight, collapseAll) {
|
|
|
67
64
|
|
|
68
65
|
var createMapFromString = utils.createMapFromString;
|
|
69
66
|
// non-empty tags that will maintain whitespace around them
|
|
70
|
-
var inlineTags = createMapFromString('a,abbr,acronym,b,bdi,bdo,big,button,cite,code,del,dfn,em,font,i,ins,kbd,label,mark,math,nobr,object,q,rt,
|
|
67
|
+
var inlineTags = createMapFromString('a,abbr,acronym,b,bdi,bdo,big,button,cite,code,del,dfn,em,font,i,ins,kbd,label,mark,math,nobr,object,q,rp,rt,rtc,ruby,s,samp,select,small,span,strike,strong,sub,sup,svg,textarea,time,tt,u,var');
|
|
71
68
|
// non-empty tags that will maintain whitespace within them
|
|
72
|
-
var inlineTextTags = createMapFromString('a,abbr,acronym,b,big,del,em,font,i,ins,kbd,mark,nobr,s,samp,small,span,strike,strong,sub,sup,time,tt,u,var');
|
|
69
|
+
var inlineTextTags = createMapFromString('a,abbr,acronym,b,big,del,em,font,i,ins,kbd,mark,nobr,rp,s,samp,small,span,strike,strong,sub,sup,time,tt,u,var');
|
|
73
70
|
// self-closing tags that will maintain whitespace around them
|
|
74
71
|
var selfClosingInlineTags = createMapFromString('comment,img,input,wbr');
|
|
75
72
|
|
|
@@ -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
|
}
|
|
@@ -285,7 +282,7 @@ function cleanAttributeValue(tag, attrName, attrValue, options, attrs) {
|
|
|
285
282
|
if (/;$/.test(attrValue) && !/&#?[0-9a-zA-Z]+;$/.test(attrValue)) {
|
|
286
283
|
attrValue = attrValue.replace(/\s*;$/, ';');
|
|
287
284
|
}
|
|
288
|
-
attrValue =
|
|
285
|
+
attrValue = options.minifyCSS(attrValue, 'inline');
|
|
289
286
|
}
|
|
290
287
|
return attrValue;
|
|
291
288
|
}
|
|
@@ -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') {
|
|
@@ -322,7 +319,7 @@ function cleanAttributeValue(tag, attrName, attrValue, options, attrs) {
|
|
|
322
319
|
}
|
|
323
320
|
else if (isMediaQuery(tag, attrs, attrName)) {
|
|
324
321
|
attrValue = trimWhitespace(attrValue);
|
|
325
|
-
return
|
|
322
|
+
return options.minifyCSS(attrValue, 'media');
|
|
326
323
|
}
|
|
327
324
|
return attrValue;
|
|
328
325
|
}
|
|
@@ -395,7 +392,7 @@ var topLevelTags = createMapFromString('html,head,body');
|
|
|
395
392
|
var compactTags = createMapFromString('html,body');
|
|
396
393
|
var looseTags = createMapFromString('head,colgroup,caption');
|
|
397
394
|
var trailingTags = createMapFromString('dt,thead');
|
|
398
|
-
var htmlTags = createMapFromString('a,abbr,acronym,address,applet,area,article,aside,audio,b,base,basefont,bdi,bdo,bgsound,big,blink,blockquote,body,br,button,canvas,caption,center,cite,code,col,colgroup,command,content,data,datalist,dd,del,details,dfn,dialog,dir,div,dl,dt,element,em,embed,fieldset,figcaption,figure,font,footer,form,frame,frameset,h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,i,iframe,image,img,input,ins,isindex,kbd,keygen,label,legend,li,link,listing,main,map,mark,marquee,menu,menuitem,meta,meter,multicol,nav,nobr,noembed,noframes,noscript,object,ol,optgroup,option,output,p,param,picture,plaintext,pre,progress,q,rp,rt,rtc,ruby,s,samp,script,section,select,shadow,small,source,spacer,span,strike,strong,style,sub,summary,sup,table,tbody,td,template,textarea,tfoot,th,thead,time,title,tr,track,tt,u,ul,var,video,wbr,xmp');
|
|
395
|
+
var htmlTags = createMapFromString('a,abbr,acronym,address,applet,area,article,aside,audio,b,base,basefont,bdi,bdo,bgsound,big,blink,blockquote,body,br,button,canvas,caption,center,cite,code,col,colgroup,command,content,data,datalist,dd,del,details,dfn,dialog,dir,div,dl,dt,element,em,embed,fieldset,figcaption,figure,font,footer,form,frame,frameset,h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,i,iframe,image,img,input,ins,isindex,kbd,keygen,label,legend,li,link,listing,main,map,mark,marquee,menu,menuitem,meta,meter,multicol,nav,nobr,noembed,noframes,noscript,object,ol,optgroup,option,output,p,param,picture,plaintext,pre,progress,q,rb,rp,rt,rtc,ruby,s,samp,script,section,select,shadow,small,source,spacer,span,strike,strong,style,sub,summary,sup,table,tbody,td,template,textarea,tfoot,th,thead,time,title,tr,track,tt,u,ul,var,video,wbr,xmp');
|
|
399
396
|
|
|
400
397
|
function canRemoveParentTag(optionalStartTag, tag) {
|
|
401
398
|
switch (optionalStartTag) {
|
|
@@ -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)) {
|
|
@@ -613,100 +612,115 @@ function identity(value) {
|
|
|
613
612
|
return value;
|
|
614
613
|
}
|
|
615
614
|
|
|
616
|
-
function processOptions(
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
if (!options.canCollapseWhitespace) {
|
|
628
|
-
options.canCollapseWhitespace = canCollapseWhitespace;
|
|
629
|
-
}
|
|
630
|
-
if (!options.canTrimWhitespace) {
|
|
631
|
-
options.canTrimWhitespace = canTrimWhitespace;
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
if (!('ignoreCustomComments' in options)) {
|
|
635
|
-
options.ignoreCustomComments = [/^!/];
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
if (!('ignoreCustomFragments' in options)) {
|
|
639
|
-
options.ignoreCustomFragments = [
|
|
615
|
+
function processOptions(values) {
|
|
616
|
+
var options = {
|
|
617
|
+
name: function(name) {
|
|
618
|
+
return name.toLowerCase();
|
|
619
|
+
},
|
|
620
|
+
canCollapseWhitespace: canCollapseWhitespace,
|
|
621
|
+
canTrimWhitespace: canTrimWhitespace,
|
|
622
|
+
html5: true,
|
|
623
|
+
ignoreCustomComments: [/^!/],
|
|
624
|
+
ignoreCustomFragments: [
|
|
640
625
|
/<%[\s\S]*?%>/,
|
|
641
626
|
/<\?[\s\S]*?\?>/
|
|
642
|
-
]
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
627
|
+
],
|
|
628
|
+
includeAutoGeneratedTags: true,
|
|
629
|
+
log: identity,
|
|
630
|
+
minifyCSS: identity,
|
|
631
|
+
minifyJS: identity,
|
|
632
|
+
minifyURLs: identity
|
|
633
|
+
};
|
|
634
|
+
Object.keys(values).forEach(function(key) {
|
|
635
|
+
var value = values[key];
|
|
636
|
+
if (key === 'caseSensitive') {
|
|
637
|
+
if (value) {
|
|
638
|
+
options.name = identity;
|
|
639
|
+
}
|
|
652
640
|
}
|
|
653
|
-
else if (
|
|
654
|
-
|
|
641
|
+
else if (key === 'log') {
|
|
642
|
+
if (typeof value === 'function') {
|
|
643
|
+
options.log = value;
|
|
644
|
+
}
|
|
655
645
|
}
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
return
|
|
646
|
+
else if (key === 'minifyCSS' && typeof value !== 'function') {
|
|
647
|
+
if (!value) {
|
|
648
|
+
return;
|
|
659
649
|
}
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
return text;
|
|
650
|
+
if (typeof value !== 'object') {
|
|
651
|
+
value = {};
|
|
663
652
|
}
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
653
|
+
options.minifyCSS = function(text, type) {
|
|
654
|
+
text = text.replace(/(url\s*\(\s*)("|'|)(.*?)\2(\s*\))/ig, function(match, prefix, quote, url, suffix) {
|
|
655
|
+
return prefix + quote + options.minifyURLs(url) + quote + suffix;
|
|
656
|
+
});
|
|
657
|
+
try {
|
|
658
|
+
if (type === 'inline') {
|
|
659
|
+
text = wrapInlineCSS(text);
|
|
660
|
+
}
|
|
661
|
+
else if (type === 'media') {
|
|
662
|
+
text = wrapMediaQuery(text);
|
|
663
|
+
}
|
|
664
|
+
text = new CleanCSS(value).minify(text).styles;
|
|
665
|
+
if (type === 'inline') {
|
|
666
|
+
text = unwrapInlineCSS(text);
|
|
667
|
+
}
|
|
668
|
+
else if (type === 'media') {
|
|
669
|
+
text = unwrapMediaQuery(text);
|
|
670
|
+
}
|
|
671
|
+
return text;
|
|
672
|
+
}
|
|
673
|
+
catch (err) {
|
|
674
|
+
options.log(err);
|
|
675
|
+
return text;
|
|
676
|
+
}
|
|
677
|
+
};
|
|
674
678
|
}
|
|
675
|
-
(
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
var code = start ? text.slice(start[0].length).replace(/\n\s*-->\s*$/, '') : text;
|
|
679
|
-
minifyJS.parse.bare_returns = inline;
|
|
680
|
-
var result = UglifyJS.minify(code, minifyJS);
|
|
681
|
-
if (result.error) {
|
|
682
|
-
options.log(result.error);
|
|
683
|
-
return text;
|
|
679
|
+
else if (key === 'minifyJS' && typeof value !== 'function') {
|
|
680
|
+
if (!value) {
|
|
681
|
+
return;
|
|
684
682
|
}
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
683
|
+
if (typeof value !== 'object') {
|
|
684
|
+
value = {};
|
|
685
|
+
}
|
|
686
|
+
(value.parse || (value.parse = {})).bare_returns = false;
|
|
687
|
+
options.minifyJS = function(text, inline) {
|
|
688
|
+
var start = text.match(/^\s*<!--.*/);
|
|
689
|
+
var code = start ? text.slice(start[0].length).replace(/\n\s*-->\s*$/, '') : text;
|
|
690
|
+
value.parse.bare_returns = inline;
|
|
691
|
+
var result = UglifyJS.minify(code, value);
|
|
692
|
+
if (result.error) {
|
|
693
|
+
options.log(result.error);
|
|
694
|
+
return text;
|
|
695
|
+
}
|
|
696
|
+
return result.code.replace(/;$/, '');
|
|
697
|
+
};
|
|
696
698
|
}
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
return
|
|
700
|
-
});
|
|
701
|
-
try {
|
|
702
|
-
return new CleanCSS(minifyCSS).minify(text).styles;
|
|
699
|
+
else if (key === 'minifyURLs' && typeof value !== 'function') {
|
|
700
|
+
if (!value) {
|
|
701
|
+
return;
|
|
703
702
|
}
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
return text;
|
|
703
|
+
if (typeof value === 'string') {
|
|
704
|
+
value = { site: value };
|
|
707
705
|
}
|
|
708
|
-
|
|
709
|
-
|
|
706
|
+
else if (typeof value !== 'object') {
|
|
707
|
+
value = {};
|
|
708
|
+
}
|
|
709
|
+
options.minifyURLs = function(text) {
|
|
710
|
+
try {
|
|
711
|
+
return RelateUrl.relate(text, value);
|
|
712
|
+
}
|
|
713
|
+
catch (err) {
|
|
714
|
+
options.log(err);
|
|
715
|
+
return text;
|
|
716
|
+
}
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
else {
|
|
720
|
+
options[key] = value;
|
|
721
|
+
}
|
|
722
|
+
});
|
|
723
|
+
return options;
|
|
710
724
|
}
|
|
711
725
|
|
|
712
726
|
function uniqueId(value) {
|
|
@@ -725,7 +739,7 @@ function createSortFns(value, options, uidIgnore, uidAttr) {
|
|
|
725
739
|
|
|
726
740
|
function attrNames(attrs) {
|
|
727
741
|
return attrs.map(function(attr) {
|
|
728
|
-
return options.
|
|
742
|
+
return options.name(attr.name);
|
|
729
743
|
});
|
|
730
744
|
}
|
|
731
745
|
|
|
@@ -749,7 +763,7 @@ function createSortFns(value, options, uidIgnore, uidAttr) {
|
|
|
749
763
|
}
|
|
750
764
|
for (var i = 0, len = attrs.length; i < len; i++) {
|
|
751
765
|
var attr = attrs[i];
|
|
752
|
-
if (classChain &&
|
|
766
|
+
if (classChain && attr.value && options.name(attr.name) === 'class') {
|
|
753
767
|
classChain.add(trimWhitespace(attr.value).split(/[ \t\n\f\r]+/).filter(shouldSkipUIDs));
|
|
754
768
|
}
|
|
755
769
|
else if (options.processScripts && attr.name.toLowerCase() === 'type') {
|
|
@@ -771,7 +785,7 @@ function createSortFns(value, options, uidIgnore, uidAttr) {
|
|
|
771
785
|
}
|
|
772
786
|
|
|
773
787
|
var log = options.log;
|
|
774
|
-
options.log =
|
|
788
|
+
options.log = identity;
|
|
775
789
|
options.sortAttributes = false;
|
|
776
790
|
options.sortClassName = false;
|
|
777
791
|
scan(minify(value, options));
|
|
@@ -804,9 +818,6 @@ function createSortFns(value, options, uidIgnore, uidAttr) {
|
|
|
804
818
|
}
|
|
805
819
|
|
|
806
820
|
function minify(value, options, partialMarkup) {
|
|
807
|
-
options = options || {};
|
|
808
|
-
var optionsStack = [];
|
|
809
|
-
processOptions(options);
|
|
810
821
|
if (options.collapseWhitespace) {
|
|
811
822
|
value = collapseWhitespace(value, options, true, true);
|
|
812
823
|
}
|
|
@@ -821,7 +832,6 @@ function minify(value, options, partialMarkup) {
|
|
|
821
832
|
stackNoCollapseWhitespace = [],
|
|
822
833
|
optionalStartTag = '',
|
|
823
834
|
optionalEndTag = '',
|
|
824
|
-
t = Date.now(),
|
|
825
835
|
ignoredMarkupChunks = [],
|
|
826
836
|
ignoredCustomMarkupChunks = [],
|
|
827
837
|
uidIgnore,
|
|
@@ -837,22 +847,25 @@ function minify(value, options, partialMarkup) {
|
|
|
837
847
|
uidIgnore = uniqueId(value);
|
|
838
848
|
var pattern = new RegExp('^' + uidIgnore + '([0-9]+)$');
|
|
839
849
|
if (options.ignoreCustomComments) {
|
|
840
|
-
options.ignoreCustomComments.
|
|
850
|
+
options.ignoreCustomComments = options.ignoreCustomComments.slice();
|
|
841
851
|
}
|
|
842
852
|
else {
|
|
843
|
-
options.ignoreCustomComments = [
|
|
853
|
+
options.ignoreCustomComments = [];
|
|
844
854
|
}
|
|
855
|
+
options.ignoreCustomComments.push(pattern);
|
|
845
856
|
}
|
|
846
857
|
var token = '<!--' + uidIgnore + ignoredMarkupChunks.length + '-->';
|
|
847
858
|
ignoredMarkupChunks.push(group1);
|
|
848
859
|
return token;
|
|
849
860
|
});
|
|
850
861
|
|
|
851
|
-
function escapeFragments(
|
|
852
|
-
return
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
862
|
+
function escapeFragments(fn) {
|
|
863
|
+
return function(text, type) {
|
|
864
|
+
return fn(text.replace(uidPattern, function(match, prefix, index) {
|
|
865
|
+
var chunks = ignoredCustomMarkupChunks[+index];
|
|
866
|
+
return chunks[1] + uidAttr + index + chunks[2];
|
|
867
|
+
}), type);
|
|
868
|
+
};
|
|
856
869
|
}
|
|
857
870
|
|
|
858
871
|
var customFragments = options.ignoreCustomFragments.map(function(re) {
|
|
@@ -865,17 +878,11 @@ function minify(value, options, partialMarkup) {
|
|
|
865
878
|
if (!uidAttr) {
|
|
866
879
|
uidAttr = uniqueId(value);
|
|
867
880
|
uidPattern = new RegExp('(\\s*)' + uidAttr + '([0-9]+)(\\s*)', 'g');
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
options.minifyCSS = function(text) {
|
|
871
|
-
return minifyCSS(escapeFragments(text));
|
|
872
|
-
};
|
|
881
|
+
if (options.minifyCSS) {
|
|
882
|
+
options.minifyCSS = escapeFragments(options.minifyCSS);
|
|
873
883
|
}
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
options.minifyJS = function(text, inline) {
|
|
877
|
-
return minifyJS(escapeFragments(text), inline);
|
|
878
|
-
};
|
|
884
|
+
if (options.minifyJS) {
|
|
885
|
+
options.minifyJS = escapeFragments(options.minifyJS);
|
|
879
886
|
}
|
|
880
887
|
}
|
|
881
888
|
var token = uidAttr + ignoredCustomMarkupChunks.length;
|
|
@@ -946,21 +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
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
for (var key in options) {
|
|
955
|
-
nextOptions[key] = options[key];
|
|
956
|
-
}
|
|
957
|
-
nextOptions.keepClosingSlash = true;
|
|
958
|
-
nextOptions.caseSensitive = true;
|
|
959
|
-
options = nextOptions;
|
|
956
|
+
if (tag.toLowerCase() === 'svg') {
|
|
957
|
+
options = Object.create(options);
|
|
958
|
+
options.caseSensitive = true;
|
|
959
|
+
options.keepClosingSlash = true;
|
|
960
|
+
options.name = identity;
|
|
960
961
|
}
|
|
961
|
-
|
|
962
|
-
tag = options.caseSensitive ? tag : lowerTag;
|
|
963
|
-
|
|
962
|
+
tag = options.name(tag);
|
|
964
963
|
currentTag = tag;
|
|
965
964
|
charsPrevTag = tag;
|
|
966
965
|
if (!inlineTextTags(tag)) {
|
|
@@ -1040,11 +1039,10 @@ function minify(value, options, partialMarkup) {
|
|
|
1040
1039
|
}
|
|
1041
1040
|
},
|
|
1042
1041
|
end: function(tag, attrs, autoGenerated) {
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
options = optionsStack.pop();
|
|
1042
|
+
if (tag.toLowerCase() === 'svg') {
|
|
1043
|
+
options = Object.getPrototypeOf(options);
|
|
1046
1044
|
}
|
|
1047
|
-
tag = options.
|
|
1045
|
+
tag = options.name(tag);
|
|
1048
1046
|
|
|
1049
1047
|
// check if current tag is in a whitespace stack
|
|
1050
1048
|
if (options.collapseWhitespace) {
|
|
@@ -1269,7 +1267,6 @@ function minify(value, options, partialMarkup) {
|
|
|
1269
1267
|
});
|
|
1270
1268
|
}
|
|
1271
1269
|
|
|
1272
|
-
options.log('minified in: ' + (Date.now() - t) + 'ms');
|
|
1273
1270
|
return str;
|
|
1274
1271
|
}
|
|
1275
1272
|
|
|
@@ -1277,20 +1274,29 @@ function joinResultSegments(results, options) {
|
|
|
1277
1274
|
var str;
|
|
1278
1275
|
var maxLineLength = options.maxLineLength;
|
|
1279
1276
|
if (maxLineLength) {
|
|
1280
|
-
var
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
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();
|
|
1287
1283
|
}
|
|
1288
1284
|
else {
|
|
1289
|
-
|
|
1290
|
-
|
|
1285
|
+
line += results[0].slice(0, end);
|
|
1286
|
+
results[0] = results[0].slice(end + 1);
|
|
1291
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);
|
|
1292
1299
|
}
|
|
1293
|
-
lines.push(line);
|
|
1294
1300
|
|
|
1295
1301
|
str = lines.join('\n');
|
|
1296
1302
|
}
|
|
@@ -1301,5 +1307,9 @@ function joinResultSegments(results, options) {
|
|
|
1301
1307
|
}
|
|
1302
1308
|
|
|
1303
1309
|
exports.minify = function(value, options) {
|
|
1304
|
-
|
|
1310
|
+
var start = Date.now();
|
|
1311
|
+
options = processOptions(options || {});
|
|
1312
|
+
var result = minify(value, options);
|
|
1313
|
+
options.log('minified in: ' + (Date.now() - start) + 'ms');
|
|
1314
|
+
return result;
|
|
1305
1315
|
};
|
package/src/htmlparser.js
CHANGED
|
@@ -49,7 +49,12 @@ var singleAttrIdentifier = /([^\s"'<>/=]+)/,
|
|
|
49
49
|
],
|
|
50
50
|
// https://www.w3.org/TR/1999/REC-xml-names-19990114/#NT-QName
|
|
51
51
|
qnameCapture = (function() {
|
|
52
|
-
|
|
52
|
+
// based on https://www.npmjs.com/package/ncname
|
|
53
|
+
var combiningChar = '\\u0300-\\u0345\\u0360\\u0361\\u0483-\\u0486\\u0591-\\u05A1\\u05A3-\\u05B9\\u05BB-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u064B-\\u0652\\u0670\\u06D6-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0901-\\u0903\\u093C\\u093E-\\u094D\\u0951-\\u0954\\u0962\\u0963\\u0981-\\u0983\\u09BC\\u09BE-\\u09C4\\u09C7\\u09C8\\u09CB-\\u09CD\\u09D7\\u09E2\\u09E3\\u0A02\\u0A3C\\u0A3E-\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A70\\u0A71\\u0A81-\\u0A83\\u0ABC\\u0ABE-\\u0AC5\\u0AC7-\\u0AC9\\u0ACB-\\u0ACD\\u0B01-\\u0B03\\u0B3C\\u0B3E-\\u0B43\\u0B47\\u0B48\\u0B4B-\\u0B4D\\u0B56\\u0B57\\u0B82\\u0B83\\u0BBE-\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCD\\u0BD7\\u0C01-\\u0C03\\u0C3E-\\u0C44\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C82\\u0C83\\u0CBE-\\u0CC4\\u0CC6-\\u0CC8\\u0CCA-\\u0CCD\\u0CD5\\u0CD6\\u0D02\\u0D03\\u0D3E-\\u0D43\\u0D46-\\u0D48\\u0D4A-\\u0D4D\\u0D57\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F3E\\u0F3F\\u0F71-\\u0F84\\u0F86-\\u0F8B\\u0F90-\\u0F95\\u0F97\\u0F99-\\u0FAD\\u0FB1-\\u0FB7\\u0FB9\\u20D0-\\u20DC\\u20E1\\u302A-\\u302F\\u3099\\u309A';
|
|
54
|
+
var digit = '0-9\\u0660-\\u0669\\u06F0-\\u06F9\\u0966-\\u096F\\u09E6-\\u09EF\\u0A66-\\u0A6F\\u0AE6-\\u0AEF\\u0B66-\\u0B6F\\u0BE7-\\u0BEF\\u0C66-\\u0C6F\\u0CE6-\\u0CEF\\u0D66-\\u0D6F\\u0E50-\\u0E59\\u0ED0-\\u0ED9\\u0F20-\\u0F29';
|
|
55
|
+
var extender = '\\xB7\\u02D0\\u02D1\\u0387\\u0640\\u0E46\\u0EC6\\u3005\\u3031-\\u3035\\u309D\\u309E\\u30FC-\\u30FE';
|
|
56
|
+
var letter = 'A-Za-z\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\u0131\\u0134-\\u013E\\u0141-\\u0148\\u014A-\\u017E\\u0180-\\u01C3\\u01CD-\\u01F0\\u01F4\\u01F5\\u01FA-\\u0217\\u0250-\\u02A8\\u02BB-\\u02C1\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03CE\\u03D0-\\u03D6\\u03DA\\u03DC\\u03DE\\u03E0\\u03E2-\\u03F3\\u0401-\\u040C\\u040E-\\u044F\\u0451-\\u045C\\u045E-\\u0481\\u0490-\\u04C4\\u04C7\\u04C8\\u04CB\\u04CC\\u04D0-\\u04EB\\u04EE-\\u04F5\\u04F8\\u04F9\\u0531-\\u0556\\u0559\\u0561-\\u0586\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0621-\\u063A\\u0641-\\u064A\\u0671-\\u06B7\\u06BA-\\u06BE\\u06C0-\\u06CE\\u06D0-\\u06D3\\u06D5\\u06E5\\u06E6\\u0905-\\u0939\\u093D\\u0958-\\u0961\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8B\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AE0\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B36-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB5\\u0BB7-\\u0BB9\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CDE\\u0CE0\\u0CE1\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D28\\u0D2A-\\u0D39\\u0D60\\u0D61\\u0E01-\\u0E2E\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E45\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD\\u0EAE\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0F40-\\u0F47\\u0F49-\\u0F69\\u10A0-\\u10C5\\u10D0-\\u10F6\\u1100\\u1102\\u1103\\u1105-\\u1107\\u1109\\u110B\\u110C\\u110E-\\u1112\\u113C\\u113E\\u1140\\u114C\\u114E\\u1150\\u1154\\u1155\\u1159\\u115F-\\u1161\\u1163\\u1165\\u1167\\u1169\\u116D\\u116E\\u1172\\u1173\\u1175\\u119E\\u11A8\\u11AB\\u11AE\\u11AF\\u11B7\\u11B8\\u11BA\\u11BC-\\u11C2\\u11EB\\u11F0\\u11F9\\u1E00-\\u1E9B\\u1EA0-\\u1EF9\\u1F00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2126\\u212A\\u212B\\u212E\\u2180-\\u2182\\u3007\\u3021-\\u3029\\u3041-\\u3094\\u30A1-\\u30FA\\u3105-\\u312C\\u4E00-\\u9FA5\\uAC00-\\uD7A3';
|
|
57
|
+
var ncname = '[' + letter + '_][' + letter + digit + '\\.\\-_' + combiningChar + extender + ']*';
|
|
53
58
|
return '((?:' + ncname + '\\:)?' + ncname + ')';
|
|
54
59
|
})(),
|
|
55
60
|
startTagOpen = new RegExp('^<' + qnameCapture),
|
|
@@ -262,12 +267,36 @@ function HTMLParser(html, handler) {
|
|
|
262
267
|
}
|
|
263
268
|
}
|
|
264
269
|
|
|
270
|
+
function closeIfFound(tagName) {
|
|
271
|
+
if (findTag(tagName) >= 0) {
|
|
272
|
+
parseEndTag('', tagName);
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
265
277
|
function handleStartTag(match) {
|
|
266
278
|
var tagName = match.tagName;
|
|
267
279
|
var unarySlash = match.unarySlash;
|
|
268
280
|
|
|
269
|
-
if (handler.html5
|
|
270
|
-
|
|
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
|
+
}
|
|
271
300
|
}
|
|
272
301
|
|
|
273
302
|
if (!handler.html5 && !inline(tagName)) {
|
|
@@ -348,17 +377,23 @@ function HTMLParser(html, handler) {
|
|
|
348
377
|
}
|
|
349
378
|
}
|
|
350
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
|
+
|
|
351
391
|
function parseEndTag(tag, tagName) {
|
|
352
392
|
var pos;
|
|
353
393
|
|
|
354
394
|
// Find the closest opened tag of the same type
|
|
355
395
|
if (tagName) {
|
|
356
|
-
|
|
357
|
-
for (pos = stack.length - 1; pos >= 0; pos--) {
|
|
358
|
-
if (stack[pos].tag.toLowerCase() === needle) {
|
|
359
|
-
break;
|
|
360
|
-
}
|
|
361
|
-
}
|
|
396
|
+
pos = findTag(tagName);
|
|
362
397
|
}
|
|
363
398
|
// If no tag name is provided, clean shop
|
|
364
399
|
else {
|