htmlnano 2.0.2 → 2.0.3
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/CHANGELOG.md +6 -0
- package/README.md +2 -2
- package/docs/docs/010-introduction.md +4 -4
- package/docs/docs/020-usage.md +63 -23
- package/docs/docs/030-config.md +1 -1
- package/docs/docs/050-modules.md +500 -483
- package/docs/package-lock.json +289 -95
- package/docs/versioned_docs/version-1.1.1/010-introduction.md +4 -4
- package/docs/versioned_docs/version-1.1.1/030-config.md +1 -1
- package/docs/versioned_docs/version-2.0.0/010-introduction.md +4 -4
- package/docs/versioned_docs/version-2.0.0/030-config.md +2 -2
- package/index.d.ts +93 -0
- package/lib/helpers.js +4 -11
- package/lib/htmlnano.js +11 -36
- package/lib/modules/collapseAttributeWhitespace.js +11 -12
- package/lib/modules/collapseBooleanAttributes.js +33 -9
- package/lib/modules/collapseWhitespace.js +17 -19
- package/lib/modules/custom.js +0 -3
- package/lib/modules/deduplicateAttributeValues.js +3 -5
- package/lib/modules/mergeScripts.js +0 -11
- package/lib/modules/mergeStyles.js +2 -8
- package/lib/modules/minifyConditionalComments.js +4 -15
- package/lib/modules/minifyCss.js +5 -16
- package/lib/modules/minifyJs.js +8 -28
- package/lib/modules/minifyJson.js +2 -3
- package/lib/modules/minifySvg.js +13 -5
- package/lib/modules/minifyUrls.js +18 -34
- package/lib/modules/normalizeAttributeValues.js +85 -2
- package/lib/modules/removeAttributeQuotes.js +0 -2
- package/lib/modules/removeComments.js +10 -28
- package/lib/modules/removeEmptyAttributes.js +6 -6
- package/lib/modules/removeOptionalTags.js +9 -46
- package/lib/modules/removeRedundantAttributes.js +20 -68
- package/lib/modules/removeUnusedCss.js +7 -18
- package/lib/modules/sortAttributes.js +10 -25
- package/lib/modules/sortAttributesWithLists.js +7 -29
- package/lib/presets/ampSafe.js +2 -5
- package/lib/presets/max.js +2 -5
- package/lib/presets/safe.js +32 -15
- package/package.json +9 -15
- package/test.js +0 -48
|
@@ -4,17 +4,15 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = removeUnusedCss;
|
|
7
|
-
|
|
8
7
|
var _helpers = require("../helpers");
|
|
9
|
-
|
|
10
8
|
const uncss = (0, _helpers.optionalRequire)('uncss');
|
|
11
|
-
const purgecss = (0, _helpers.optionalRequire)('purgecss');
|
|
9
|
+
const purgecss = (0, _helpers.optionalRequire)('purgecss');
|
|
12
10
|
|
|
11
|
+
// These options must be set and shouldn't be overriden to ensure uncss doesn't look at linked stylesheets.
|
|
13
12
|
const uncssOptions = {
|
|
14
13
|
ignoreSheets: [/\s*/],
|
|
15
14
|
stylesheets: []
|
|
16
15
|
};
|
|
17
|
-
|
|
18
16
|
function processStyleNodeUnCSS(html, styleNode, uncssOptions) {
|
|
19
17
|
const css = (0, _helpers.extractCssFromStyleNode)(styleNode);
|
|
20
18
|
return runUncss(html, css, uncssOptions).then(css => {
|
|
@@ -24,17 +22,15 @@ function processStyleNodeUnCSS(html, styleNode, uncssOptions) {
|
|
|
24
22
|
styleNode.content = [];
|
|
25
23
|
return;
|
|
26
24
|
}
|
|
27
|
-
|
|
28
25
|
styleNode.content = [css];
|
|
29
26
|
});
|
|
30
27
|
}
|
|
31
|
-
|
|
32
28
|
function runUncss(html, css, userOptions) {
|
|
33
29
|
if (typeof userOptions !== 'object') {
|
|
34
30
|
userOptions = {};
|
|
35
31
|
}
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
const options = {
|
|
33
|
+
...userOptions,
|
|
38
34
|
...uncssOptions
|
|
39
35
|
};
|
|
40
36
|
return new Promise((resolve, reject) => {
|
|
@@ -44,12 +40,10 @@ function runUncss(html, css, userOptions) {
|
|
|
44
40
|
reject(error);
|
|
45
41
|
return;
|
|
46
42
|
}
|
|
47
|
-
|
|
48
43
|
resolve(output);
|
|
49
44
|
});
|
|
50
45
|
});
|
|
51
46
|
}
|
|
52
|
-
|
|
53
47
|
const purgeFromHtml = function (tree) {
|
|
54
48
|
// content is not used as we can directly used the parsed HTML,
|
|
55
49
|
// making the process faster
|
|
@@ -63,7 +57,6 @@ const purgeFromHtml = function (tree) {
|
|
|
63
57
|
});
|
|
64
58
|
return () => selectors;
|
|
65
59
|
};
|
|
66
|
-
|
|
67
60
|
function processStyleNodePurgeCSS(tree, styleNode, purgecssOptions) {
|
|
68
61
|
const css = (0, _helpers.extractCssFromStyleNode)(styleNode);
|
|
69
62
|
return runPurgecss(tree, css, purgecssOptions).then(css => {
|
|
@@ -72,17 +65,15 @@ function processStyleNodePurgeCSS(tree, styleNode, purgecssOptions) {
|
|
|
72
65
|
styleNode.content = [];
|
|
73
66
|
return;
|
|
74
67
|
}
|
|
75
|
-
|
|
76
68
|
styleNode.content = [css];
|
|
77
69
|
});
|
|
78
70
|
}
|
|
79
|
-
|
|
80
71
|
function runPurgecss(tree, css, userOptions) {
|
|
81
72
|
if (typeof userOptions !== 'object') {
|
|
82
73
|
userOptions = {};
|
|
83
74
|
}
|
|
84
|
-
|
|
85
|
-
|
|
75
|
+
const options = {
|
|
76
|
+
...userOptions,
|
|
86
77
|
content: [{
|
|
87
78
|
raw: tree,
|
|
88
79
|
extension: 'html'
|
|
@@ -100,9 +91,8 @@ function runPurgecss(tree, css, userOptions) {
|
|
|
100
91
|
return result[0].css;
|
|
101
92
|
});
|
|
102
93
|
}
|
|
103
|
-
/** Remove unused CSS */
|
|
104
|
-
|
|
105
94
|
|
|
95
|
+
/** Remove unused CSS */
|
|
106
96
|
function removeUnusedCss(tree, options, userOptions) {
|
|
107
97
|
const promises = [];
|
|
108
98
|
const html = userOptions.tool !== 'purgeCSS' && tree.render(tree);
|
|
@@ -118,7 +108,6 @@ function removeUnusedCss(tree, options, userOptions) {
|
|
|
118
108
|
}
|
|
119
109
|
}
|
|
120
110
|
}
|
|
121
|
-
|
|
122
111
|
return node;
|
|
123
112
|
});
|
|
124
113
|
return Promise.all(promises).then(() => tree);
|
|
@@ -4,16 +4,12 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = sortAttributes;
|
|
7
|
-
|
|
8
7
|
var _timsort = require("timsort");
|
|
9
|
-
|
|
10
8
|
const validOptions = new Set(['frequency', 'alphabetical']);
|
|
11
|
-
|
|
12
9
|
const processModuleOptions = options => {
|
|
13
10
|
if (options === true) return 'alphabetical';
|
|
14
11
|
return validOptions.has(options) ? options : false;
|
|
15
12
|
};
|
|
16
|
-
|
|
17
13
|
class AttributeTokenChain {
|
|
18
14
|
constructor() {
|
|
19
15
|
this.freqData = new Map(); // <attr, frequency>[]
|
|
@@ -22,7 +18,6 @@ class AttributeTokenChain {
|
|
|
22
18
|
addFromNodeAttrs(nodeAttrs) {
|
|
23
19
|
Object.keys(nodeAttrs).forEach(attrName => {
|
|
24
20
|
const attrNameLower = attrName.toLowerCase();
|
|
25
|
-
|
|
26
21
|
if (this.freqData.has(attrNameLower)) {
|
|
27
22
|
this.freqData.set(attrNameLower, this.freqData.get(attrNameLower) + 1);
|
|
28
23
|
} else {
|
|
@@ -30,59 +25,50 @@ class AttributeTokenChain {
|
|
|
30
25
|
}
|
|
31
26
|
});
|
|
32
27
|
}
|
|
33
|
-
|
|
34
28
|
createSortOrder() {
|
|
35
29
|
let _sortOrder = [...this.freqData.entries()];
|
|
36
30
|
(0, _timsort.sort)(_sortOrder, (a, b) => b[1] - a[1]);
|
|
37
31
|
this.sortOrder = _sortOrder.map(i => i[0]);
|
|
38
32
|
}
|
|
39
|
-
|
|
40
33
|
sortFromNodeAttrs(nodeAttrs) {
|
|
41
|
-
const newAttrs = {};
|
|
34
|
+
const newAttrs = {};
|
|
42
35
|
|
|
36
|
+
// Convert node.attrs attrName into lower case.
|
|
43
37
|
const loweredNodeAttrs = {};
|
|
44
38
|
Object.entries(nodeAttrs).forEach(([attrName, attrValue]) => {
|
|
45
39
|
loweredNodeAttrs[attrName.toLowerCase()] = attrValue;
|
|
46
40
|
});
|
|
47
|
-
|
|
48
41
|
if (!this.sortOrder) {
|
|
49
42
|
this.createSortOrder();
|
|
50
43
|
}
|
|
51
|
-
|
|
52
44
|
this.sortOrder.forEach(attrNameLower => {
|
|
53
45
|
// The attrName inside "sortOrder" has been lowered
|
|
54
|
-
if (loweredNodeAttrs[attrNameLower]) {
|
|
46
|
+
if (loweredNodeAttrs[attrNameLower] != null) {
|
|
55
47
|
newAttrs[attrNameLower] = loweredNodeAttrs[attrNameLower];
|
|
56
48
|
}
|
|
57
49
|
});
|
|
58
50
|
return newAttrs;
|
|
59
51
|
}
|
|
60
|
-
|
|
61
52
|
}
|
|
62
|
-
/** Sort attibutes */
|
|
63
|
-
|
|
64
53
|
|
|
54
|
+
/** Sort attibutes */
|
|
65
55
|
function sortAttributes(tree, options, moduleOptions) {
|
|
66
56
|
const sortType = processModuleOptions(moduleOptions);
|
|
67
|
-
|
|
68
57
|
if (sortType === 'alphabetical') {
|
|
69
58
|
return sortAttributesInAlphabeticalOrder(tree);
|
|
70
59
|
}
|
|
71
|
-
|
|
72
60
|
if (sortType === 'frequency') {
|
|
73
61
|
return sortAttributesByFrequency(tree);
|
|
74
|
-
}
|
|
75
|
-
|
|
62
|
+
}
|
|
76
63
|
|
|
64
|
+
// Invalid configuration
|
|
77
65
|
return tree;
|
|
78
66
|
}
|
|
79
|
-
|
|
80
67
|
function sortAttributesInAlphabeticalOrder(tree) {
|
|
81
68
|
tree.walk(node => {
|
|
82
69
|
if (!node.attrs) {
|
|
83
70
|
return node;
|
|
84
71
|
}
|
|
85
|
-
|
|
86
72
|
const newAttrs = {};
|
|
87
73
|
Object.keys(node.attrs).sort((a, b) => typeof a.localeCompare === 'function' ? a.localeCompare(b) : a - b).forEach(attr => newAttrs[attr] = node.attrs[attr]);
|
|
88
74
|
node.attrs = newAttrs;
|
|
@@ -90,24 +76,23 @@ function sortAttributesInAlphabeticalOrder(tree) {
|
|
|
90
76
|
});
|
|
91
77
|
return tree;
|
|
92
78
|
}
|
|
93
|
-
|
|
94
79
|
function sortAttributesByFrequency(tree) {
|
|
95
|
-
const tokenchain = new AttributeTokenChain();
|
|
80
|
+
const tokenchain = new AttributeTokenChain();
|
|
96
81
|
|
|
82
|
+
// Traverse through tree to get frequency
|
|
97
83
|
tree.walk(node => {
|
|
98
84
|
if (!node.attrs) {
|
|
99
85
|
return node;
|
|
100
86
|
}
|
|
101
|
-
|
|
102
87
|
tokenchain.addFromNodeAttrs(node.attrs);
|
|
103
88
|
return node;
|
|
104
|
-
});
|
|
89
|
+
});
|
|
105
90
|
|
|
91
|
+
// Traverse through tree again, this time sort the attributes
|
|
106
92
|
tree.walk(node => {
|
|
107
93
|
if (!node.attrs) {
|
|
108
94
|
return node;
|
|
109
95
|
}
|
|
110
|
-
|
|
111
96
|
node.attrs = tokenchain.sortFromNodeAttrs(node.attrs);
|
|
112
97
|
return node;
|
|
113
98
|
});
|
|
@@ -4,19 +4,15 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = collapseAttributeWhitespace;
|
|
7
|
-
|
|
8
7
|
var _timsort = require("timsort");
|
|
9
|
-
|
|
10
8
|
var _collapseAttributeWhitespace = require("./collapseAttributeWhitespace");
|
|
11
|
-
|
|
12
9
|
// class, rel, ping
|
|
13
|
-
const validOptions = new Set(['frequency', 'alphabetical']);
|
|
14
10
|
|
|
11
|
+
const validOptions = new Set(['frequency', 'alphabetical']);
|
|
15
12
|
const processModuleOptions = options => {
|
|
16
13
|
if (options === true) return 'alphabetical';
|
|
17
14
|
return validOptions.has(options) ? options : false;
|
|
18
15
|
};
|
|
19
|
-
|
|
20
16
|
class AttributeTokenChain {
|
|
21
17
|
constructor() {
|
|
22
18
|
this.freqData = new Map(); // <attrValue, frequency>[]
|
|
@@ -31,20 +27,16 @@ class AttributeTokenChain {
|
|
|
31
27
|
}
|
|
32
28
|
});
|
|
33
29
|
}
|
|
34
|
-
|
|
35
30
|
createSortOrder() {
|
|
36
31
|
let _sortOrder = [...this.freqData.entries()];
|
|
37
32
|
(0, _timsort.sort)(_sortOrder, (a, b) => b[1] - a[1]);
|
|
38
33
|
this.sortOrder = _sortOrder.map(i => i[0]);
|
|
39
34
|
}
|
|
40
|
-
|
|
41
35
|
sortFromNodeAttrsArray(attrValuesArray) {
|
|
42
36
|
const resultArray = [];
|
|
43
|
-
|
|
44
37
|
if (!this.sortOrder) {
|
|
45
38
|
this.createSortOrder();
|
|
46
39
|
}
|
|
47
|
-
|
|
48
40
|
this.sortOrder.forEach(k => {
|
|
49
41
|
if (attrValuesArray.includes(k)) {
|
|
50
42
|
resultArray.push(k);
|
|
@@ -52,39 +44,31 @@ class AttributeTokenChain {
|
|
|
52
44
|
});
|
|
53
45
|
return resultArray;
|
|
54
46
|
}
|
|
55
|
-
|
|
56
47
|
}
|
|
57
|
-
/** Sort values inside list-like attributes (e.g. class, rel) */
|
|
58
|
-
|
|
59
48
|
|
|
49
|
+
/** Sort values inside list-like attributes (e.g. class, rel) */
|
|
60
50
|
function collapseAttributeWhitespace(tree, options, moduleOptions) {
|
|
61
51
|
const sortType = processModuleOptions(moduleOptions);
|
|
62
|
-
|
|
63
52
|
if (sortType === 'alphabetical') {
|
|
64
53
|
return sortAttributesWithListsInAlphabeticalOrder(tree);
|
|
65
54
|
}
|
|
66
|
-
|
|
67
55
|
if (sortType === 'frequency') {
|
|
68
56
|
return sortAttributesWithListsByFrequency(tree);
|
|
69
|
-
}
|
|
70
|
-
|
|
57
|
+
}
|
|
71
58
|
|
|
59
|
+
// Invalid configuration
|
|
72
60
|
return tree;
|
|
73
61
|
}
|
|
74
|
-
|
|
75
62
|
function sortAttributesWithListsInAlphabeticalOrder(tree) {
|
|
76
63
|
tree.walk(node => {
|
|
77
64
|
if (!node.attrs) {
|
|
78
65
|
return node;
|
|
79
66
|
}
|
|
80
|
-
|
|
81
67
|
Object.keys(node.attrs).forEach(attrName => {
|
|
82
68
|
const attrNameLower = attrName.toLowerCase();
|
|
83
|
-
|
|
84
69
|
if (!_collapseAttributeWhitespace.attributesWithLists.has(attrNameLower)) {
|
|
85
70
|
return;
|
|
86
71
|
}
|
|
87
|
-
|
|
88
72
|
const attrValues = node.attrs[attrName].split(/\s/);
|
|
89
73
|
node.attrs[attrName] = attrValues.sort((a, b) => {
|
|
90
74
|
return typeof a.localeCompare === 'function' ? a.localeCompare(b) : a - b;
|
|
@@ -94,41 +78,35 @@ function sortAttributesWithListsInAlphabeticalOrder(tree) {
|
|
|
94
78
|
});
|
|
95
79
|
return tree;
|
|
96
80
|
}
|
|
97
|
-
|
|
98
81
|
function sortAttributesWithListsByFrequency(tree) {
|
|
99
82
|
const tokenChainObj = {}; // <attrNameLower: AttributeTokenChain>[]
|
|
100
|
-
// Traverse through tree to get frequency
|
|
101
83
|
|
|
84
|
+
// Traverse through tree to get frequency
|
|
102
85
|
tree.walk(node => {
|
|
103
86
|
if (!node.attrs) {
|
|
104
87
|
return node;
|
|
105
88
|
}
|
|
106
|
-
|
|
107
89
|
Object.entries(node.attrs).forEach(([attrName, attrValues]) => {
|
|
108
90
|
const attrNameLower = attrName.toLowerCase();
|
|
109
|
-
|
|
110
91
|
if (!_collapseAttributeWhitespace.attributesWithLists.has(attrNameLower)) {
|
|
111
92
|
return;
|
|
112
93
|
}
|
|
113
|
-
|
|
114
94
|
tokenChainObj[attrNameLower] = tokenChainObj[attrNameLower] || new AttributeTokenChain();
|
|
115
95
|
tokenChainObj[attrNameLower].addFromNodeAttrsArray(attrValues.split(/\s/));
|
|
116
96
|
});
|
|
117
97
|
return node;
|
|
118
|
-
});
|
|
98
|
+
});
|
|
119
99
|
|
|
100
|
+
// Traverse through tree again, this time sort the attribute values
|
|
120
101
|
tree.walk(node => {
|
|
121
102
|
if (!node.attrs) {
|
|
122
103
|
return node;
|
|
123
104
|
}
|
|
124
|
-
|
|
125
105
|
Object.entries(node.attrs).forEach(([attrName, attrValues]) => {
|
|
126
106
|
const attrNameLower = attrName.toLowerCase();
|
|
127
|
-
|
|
128
107
|
if (!_collapseAttributeWhitespace.attributesWithLists.has(attrNameLower)) {
|
|
129
108
|
return;
|
|
130
109
|
}
|
|
131
|
-
|
|
132
110
|
if (tokenChainObj[attrNameLower]) {
|
|
133
111
|
node.attrs[attrName] = tokenChainObj[attrNameLower].sortFromNodeAttrsArray(attrValues.split(/\s/)).join(' ');
|
|
134
112
|
}
|
package/lib/presets/ampSafe.js
CHANGED
|
@@ -4,9 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
|
-
|
|
8
7
|
var _safe = _interopRequireDefault(require("./safe"));
|
|
9
|
-
|
|
10
8
|
function _interopRequireDefault(obj) {
|
|
11
9
|
return obj && obj.__esModule ? obj : {
|
|
12
10
|
default: obj
|
|
@@ -15,9 +13,8 @@ function _interopRequireDefault(obj) {
|
|
|
15
13
|
/**
|
|
16
14
|
* A safe preset for AMP pages (https://www.ampproject.org)
|
|
17
15
|
*/
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
var _default = { ..._safe.default,
|
|
16
|
+
var _default = {
|
|
17
|
+
..._safe.default,
|
|
21
18
|
collapseBooleanAttributes: {
|
|
22
19
|
amphtml: true
|
|
23
20
|
},
|
package/lib/presets/max.js
CHANGED
|
@@ -4,9 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
|
-
|
|
8
7
|
var _safe = _interopRequireDefault(require("./safe"));
|
|
9
|
-
|
|
10
8
|
function _interopRequireDefault(obj) {
|
|
11
9
|
return obj && obj.__esModule ? obj : {
|
|
12
10
|
default: obj
|
|
@@ -15,9 +13,8 @@ function _interopRequireDefault(obj) {
|
|
|
15
13
|
/**
|
|
16
14
|
* Maximal minification (might break some pages)
|
|
17
15
|
*/
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
var _default = { ..._safe.default,
|
|
16
|
+
var _default = {
|
|
17
|
+
..._safe.default,
|
|
21
18
|
collapseWhitespace: 'all',
|
|
22
19
|
removeComments: 'all',
|
|
23
20
|
removeAttributeQuotes: true,
|
package/lib/presets/safe.js
CHANGED
|
@@ -7,19 +7,40 @@ exports.default = void 0;
|
|
|
7
7
|
/**
|
|
8
8
|
* Minify HTML in a safe way without breaking anything.
|
|
9
9
|
*/
|
|
10
|
-
|
|
11
10
|
var _default = {
|
|
12
|
-
|
|
11
|
+
/* ----------------------------------------
|
|
12
|
+
* Attributes
|
|
13
|
+
* ---------------------------------------- */
|
|
14
|
+
// normalize the case of attribute names and values
|
|
15
|
+
// normalizeAttributeValues will also normalize property value with invalid value default
|
|
16
|
+
// See https://html.spec.whatwg.org/#invalid-value-default
|
|
17
|
+
normalizeAttributeValues: true,
|
|
18
|
+
removeEmptyAttributes: true,
|
|
13
19
|
collapseAttributeWhitespace: true,
|
|
20
|
+
// removeRedundantAttributes will remove attributes when missing value default matches the attribute's value
|
|
21
|
+
// See https://html.spec.whatwg.org/#missing-value-default
|
|
22
|
+
removeRedundantAttributes: false,
|
|
23
|
+
// collapseBooleanAttributes will also collapse those default state can be omitted
|
|
14
24
|
collapseBooleanAttributes: {
|
|
15
25
|
amphtml: false
|
|
16
26
|
},
|
|
17
|
-
collapseWhitespace: 'conservative',
|
|
18
|
-
custom: [],
|
|
19
27
|
deduplicateAttributeValues: true,
|
|
20
|
-
|
|
28
|
+
minifyUrls: false,
|
|
29
|
+
sortAttributes: false,
|
|
30
|
+
sortAttributesWithLists: 'alphabetical',
|
|
31
|
+
/* ----------------------------------------
|
|
32
|
+
* Minify HTML content
|
|
33
|
+
* ---------------------------------------- */
|
|
34
|
+
collapseWhitespace: 'conservative',
|
|
35
|
+
removeComments: 'safe',
|
|
36
|
+
minifyConditionalComments: false,
|
|
37
|
+
removeOptionalTags: false,
|
|
38
|
+
removeAttributeQuotes: false,
|
|
39
|
+
/* ----------------------------------------
|
|
40
|
+
* Minify inline <style>, <script> and <svg> tag
|
|
41
|
+
* ---------------------------------------- */
|
|
21
42
|
mergeStyles: false,
|
|
22
|
-
|
|
43
|
+
mergeScripts: false,
|
|
23
44
|
minifyCss: {
|
|
24
45
|
preset: 'default'
|
|
25
46
|
},
|
|
@@ -36,14 +57,10 @@ var _default = {
|
|
|
36
57
|
}
|
|
37
58
|
}]
|
|
38
59
|
},
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
removeAttributeQuotes: false,
|
|
45
|
-
sortAttributesWithLists: 'alphabetical',
|
|
46
|
-
minifyUrls: false,
|
|
47
|
-
removeOptionalTags: false
|
|
60
|
+
removeUnusedCss: false,
|
|
61
|
+
/* ----------------------------------------
|
|
62
|
+
* Miscellaneous
|
|
63
|
+
* ---------------------------------------- */
|
|
64
|
+
custom: []
|
|
48
65
|
};
|
|
49
66
|
exports.default = _default;
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "htmlnano",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.3",
|
|
4
4
|
"description": "Modular HTML minifier, built on top of the PostHTML",
|
|
5
5
|
"main": "index.js",
|
|
6
|
+
"types": "index.d.ts",
|
|
6
7
|
"author": "Kirill Maltsev <maltsevkirill@gmail.com>",
|
|
7
8
|
"license": "MIT",
|
|
8
9
|
"scripts": {
|
|
@@ -11,13 +12,7 @@
|
|
|
11
12
|
"pretest": "npm run lint && npm run compile",
|
|
12
13
|
"test": ":",
|
|
13
14
|
"posttest": "mocha --timeout 5000 --require @babel/register --recursive --check-leaks --globals addresses",
|
|
14
|
-
"prepare": "npm run compile"
|
|
15
|
-
"release:patch": "release-it patch -n"
|
|
16
|
-
},
|
|
17
|
-
"release-it": {
|
|
18
|
-
"hooks": {
|
|
19
|
-
"before:init": "npm test"
|
|
20
|
-
}
|
|
15
|
+
"prepare": "npm run compile"
|
|
21
16
|
},
|
|
22
17
|
"keywords": [
|
|
23
18
|
"posthtml",
|
|
@@ -49,16 +44,15 @@
|
|
|
49
44
|
"@babel/eslint-parser": "^7.17.0",
|
|
50
45
|
"@babel/preset-env": "^7.15.6",
|
|
51
46
|
"@babel/register": "^7.15.3",
|
|
52
|
-
"cssnano": "^5.
|
|
47
|
+
"cssnano": "^5.1.12",
|
|
53
48
|
"eslint": "^8.12.0",
|
|
54
49
|
"expect": "^27.2.0",
|
|
55
|
-
"mocha": "^
|
|
50
|
+
"mocha": "^10.1.0",
|
|
56
51
|
"postcss": "^8.3.11",
|
|
57
|
-
"purgecss": "^
|
|
52
|
+
"purgecss": "^5.0.0",
|
|
58
53
|
"relateurl": "^0.2.7",
|
|
59
|
-
"release-it": "^14.11.5",
|
|
60
54
|
"rimraf": "^3.0.2",
|
|
61
|
-
"srcset": "
|
|
55
|
+
"srcset": "4.0.0",
|
|
62
56
|
"svgo": "^2.8.0",
|
|
63
57
|
"terser": "^5.10.0",
|
|
64
58
|
"uncss": "^0.17.3"
|
|
@@ -66,9 +60,9 @@
|
|
|
66
60
|
"peerDependencies": {
|
|
67
61
|
"cssnano": "^5.0.11",
|
|
68
62
|
"postcss": "^8.3.11",
|
|
69
|
-
"purgecss": "^
|
|
63
|
+
"purgecss": "^5.0.0",
|
|
70
64
|
"relateurl": "^0.2.7",
|
|
71
|
-
"srcset": "
|
|
65
|
+
"srcset": "4.0.0",
|
|
72
66
|
"svgo": "^2.8.0",
|
|
73
67
|
"terser": "^5.10.0",
|
|
74
68
|
"uncss": "^0.17.3"
|
package/test.js
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
const htmlnano = require('.');
|
|
2
|
-
// const posthtml = require('posthtml');
|
|
3
|
-
const safePreset = require('./lib/presets/safe');
|
|
4
|
-
// const options = {
|
|
5
|
-
// minifySvg: false,
|
|
6
|
-
// minifyJs: false,
|
|
7
|
-
// };
|
|
8
|
-
// // posthtml, posthtml-render, and posthtml-parse options
|
|
9
|
-
// const postHtmlOptions = {
|
|
10
|
-
// sync: true, // https://github.com/posthtml/posthtml#usage
|
|
11
|
-
// lowerCaseTags: true, // https://github.com/posthtml/posthtml-parser#options
|
|
12
|
-
// quoteAllAttributes: false, // https://github.com/posthtml/posthtml-render#options
|
|
13
|
-
// };
|
|
14
|
-
|
|
15
|
-
// const html = `
|
|
16
|
-
// <!doctype html>
|
|
17
|
-
// <html lang="en">
|
|
18
|
-
// <head>
|
|
19
|
-
// <meta charset="utf-8">
|
|
20
|
-
// <title></title>
|
|
21
|
-
// <script class="fob">alert(1)</script>
|
|
22
|
-
// <script>alert(2)</script>
|
|
23
|
-
// </head>
|
|
24
|
-
// <body>
|
|
25
|
-
// <script>alert(3)</script>
|
|
26
|
-
// <script>alert(4)</script>
|
|
27
|
-
// </body>
|
|
28
|
-
// </html>
|
|
29
|
-
// `;
|
|
30
|
-
|
|
31
|
-
const options = {
|
|
32
|
-
minifySvg: safePreset.minifySvg,
|
|
33
|
-
};
|
|
34
|
-
const html = `
|
|
35
|
-
<input type="text" class="form-control" name="testInput" autofocus="" autocomplete="off" id="testId"><a id="testId" href="#" class="testClass"></a><img width="20" src="../images/image.png" height="40" alt="image" class="cls" id="id2">
|
|
36
|
-
`;
|
|
37
|
-
|
|
38
|
-
htmlnano
|
|
39
|
-
// "preset" arg might be skipped (see "Presets" section below for more info)
|
|
40
|
-
// "postHtmlOptions" arg might be skipped
|
|
41
|
-
.process(html)
|
|
42
|
-
.then(function (result) {
|
|
43
|
-
// result.html is minified
|
|
44
|
-
console.log(result.html);
|
|
45
|
-
})
|
|
46
|
-
.catch(function (err) {
|
|
47
|
-
console.error(err);
|
|
48
|
-
});
|