htmlnano 0.2.5 → 0.2.9
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 +81 -2
- package/README.md +268 -15
- package/lib/helpers.js +16 -36
- package/lib/htmlnano.js +33 -69
- package/lib/modules/collapseAttributeWhitespace.js +21 -19
- package/lib/modules/collapseBooleanAttributes.js +36 -48
- package/lib/modules/collapseWhitespace.js +58 -32
- package/lib/modules/custom.js +12 -12
- package/lib/modules/deduplicateAttributeValues.js +34 -36
- package/lib/modules/mergeScripts.js +46 -66
- package/lib/modules/mergeStyles.js +33 -32
- package/lib/modules/minifyConditionalComments.js +58 -0
- package/lib/modules/minifyCss.js +59 -41
- package/lib/modules/minifyJs.js +79 -64
- package/lib/modules/minifyJson.js +23 -17
- package/lib/modules/minifySvg.js +20 -28
- package/lib/modules/minifyUrls.js +116 -0
- package/lib/modules/removeAttributeQuotes.js +19 -0
- package/lib/modules/removeComments.js +52 -34
- package/lib/modules/removeEmptyAttributes.js +19 -21
- package/lib/modules/removeOptionalTags.js +220 -0
- package/lib/modules/removeRedundantAttributes.js +89 -66
- package/lib/modules/removeUnusedCss.js +94 -116
- package/lib/modules/sortAttributes.js +115 -0
- package/lib/modules/sortAttributesWithLists.js +138 -0
- package/lib/presets/ampSafe.js +16 -13
- package/lib/presets/max.js +23 -17
- package/lib/presets/safe.js +38 -25
- package/package.json +28 -19
- package/test.js +30 -7
- package/lib/presets/hard.js +0 -26
|
@@ -1,147 +1,125 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
|
|
4
|
+
value: true
|
|
5
5
|
});
|
|
6
|
-
|
|
7
|
-
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
|
|
8
|
-
|
|
9
6
|
exports.default = removeUnusedCss;
|
|
10
7
|
|
|
11
|
-
var _helpers = require(
|
|
12
|
-
|
|
13
|
-
var _uncss = require('uncss');
|
|
14
|
-
|
|
15
|
-
var _uncss2 = _interopRequireDefault(_uncss);
|
|
8
|
+
var _helpers = require("../helpers");
|
|
16
9
|
|
|
17
|
-
var
|
|
10
|
+
var _uncss = _interopRequireDefault(require("uncss"));
|
|
18
11
|
|
|
19
|
-
var
|
|
20
|
-
|
|
21
|
-
var _posthtmlRender = require('posthtml-render');
|
|
22
|
-
|
|
23
|
-
var _posthtmlRender2 = _interopRequireDefault(_posthtmlRender);
|
|
12
|
+
var _purgecss = _interopRequireDefault(require("purgecss"));
|
|
24
13
|
|
|
25
14
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
26
15
|
|
|
27
|
-
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
|
|
28
|
-
|
|
29
16
|
// These options must be set and shouldn't be overriden to ensure uncss doesn't look at linked stylesheets.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
17
|
+
const uncssOptions = {
|
|
18
|
+
ignoreSheets: [/\s*/],
|
|
19
|
+
stylesheets: []
|
|
33
20
|
};
|
|
34
21
|
|
|
35
22
|
function processStyleNodeUnCSS(html, styleNode, uncssOptions) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
styleNode.content = [css];
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function runUncss(html, css, userOptions) {
|
|
50
|
-
if ((typeof userOptions === 'undefined' ? 'undefined' : _typeof(userOptions)) !== 'object') {
|
|
51
|
-
userOptions = {};
|
|
23
|
+
const css = (0, _helpers.extractCssFromStyleNode)(styleNode);
|
|
24
|
+
return runUncss(html, css, uncssOptions).then(css => {
|
|
25
|
+
// uncss may have left some style tags empty
|
|
26
|
+
if (css.trim().length === 0) {
|
|
27
|
+
styleNode.tag = false;
|
|
28
|
+
styleNode.content = [];
|
|
29
|
+
return;
|
|
52
30
|
}
|
|
53
31
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
options.raw = css;
|
|
57
|
-
(0, _uncss2.default)(html, options, function (error, output) {
|
|
58
|
-
if (error) {
|
|
59
|
-
reject(error);
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
resolve(output);
|
|
63
|
-
});
|
|
64
|
-
});
|
|
32
|
+
styleNode.content = [css];
|
|
33
|
+
});
|
|
65
34
|
}
|
|
66
35
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
36
|
+
function runUncss(html, css, userOptions) {
|
|
37
|
+
if (typeof userOptions !== 'object') {
|
|
38
|
+
userOptions = {};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const options = { ...userOptions,
|
|
42
|
+
...uncssOptions
|
|
43
|
+
};
|
|
44
|
+
return new Promise((resolve, reject) => {
|
|
45
|
+
options.raw = css;
|
|
46
|
+
(0, _uncss.default)(html, options, (error, output) => {
|
|
47
|
+
if (error) {
|
|
48
|
+
reject(error);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
resolve(output);
|
|
78
53
|
});
|
|
54
|
+
});
|
|
55
|
+
}
|
|
79
56
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
57
|
+
const purgeFromHtml = function (tree) {
|
|
58
|
+
// content is not used as we can directly used the parsed HTML,
|
|
59
|
+
// making the process faster
|
|
60
|
+
const selectors = [];
|
|
61
|
+
tree.walk(node => {
|
|
62
|
+
const classes = node.attrs && node.attrs.class && node.attrs.class.split(' ') || [];
|
|
63
|
+
const ids = node.attrs && node.attrs.id && node.attrs.id.split(' ') || [];
|
|
64
|
+
selectors.push(...classes, ...ids);
|
|
65
|
+
node.tag && selectors.push(node.tag);
|
|
66
|
+
return node;
|
|
67
|
+
});
|
|
68
|
+
return () => selectors;
|
|
83
69
|
};
|
|
84
70
|
|
|
85
71
|
function processStyleNodePurgeCSS(tree, styleNode, purgecssOptions) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
styleNode.content = [css];
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function runPurgecss(tree, css, userOptions) {
|
|
98
|
-
if ((typeof userOptions === 'undefined' ? 'undefined' : _typeof(userOptions)) !== 'object') {
|
|
99
|
-
userOptions = {};
|
|
72
|
+
const css = (0, _helpers.extractCssFromStyleNode)(styleNode);
|
|
73
|
+
return runPurgecss(tree, css, purgecssOptions).then(css => {
|
|
74
|
+
if (css.trim().length === 0) {
|
|
75
|
+
styleNode.tag = false;
|
|
76
|
+
styleNode.content = [];
|
|
77
|
+
return;
|
|
100
78
|
}
|
|
101
79
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
raw: tree,
|
|
105
|
-
extension: 'html'
|
|
106
|
-
}],
|
|
107
|
-
css: [{
|
|
108
|
-
raw: css,
|
|
109
|
-
extension: 'css'
|
|
110
|
-
}],
|
|
111
|
-
extractors: [{
|
|
112
|
-
extractor: purgeFromHtml(tree),
|
|
113
|
-
extensions: ['html']
|
|
114
|
-
}]
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
return new Promise(function (resolve, reject) {
|
|
118
|
-
try {
|
|
119
|
-
var purgeCss = new _purgecss2.default(options);
|
|
120
|
-
var purgecssResult = purgeCss.purge()[0];
|
|
121
|
-
resolve(purgecssResult.css);
|
|
122
|
-
} catch (err) {
|
|
123
|
-
reject(err);
|
|
124
|
-
}
|
|
125
|
-
});
|
|
80
|
+
styleNode.content = [css];
|
|
81
|
+
});
|
|
126
82
|
}
|
|
127
83
|
|
|
84
|
+
function runPurgecss(tree, css, userOptions) {
|
|
85
|
+
if (typeof userOptions !== 'object') {
|
|
86
|
+
userOptions = {};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const options = { ...userOptions,
|
|
90
|
+
content: [{
|
|
91
|
+
raw: tree,
|
|
92
|
+
extension: 'html'
|
|
93
|
+
}],
|
|
94
|
+
css: [{
|
|
95
|
+
raw: css,
|
|
96
|
+
extension: 'css'
|
|
97
|
+
}],
|
|
98
|
+
extractors: [{
|
|
99
|
+
extractor: purgeFromHtml(tree),
|
|
100
|
+
extensions: ['html']
|
|
101
|
+
}]
|
|
102
|
+
};
|
|
103
|
+
return new _purgecss.default().purge(options).then(result => {
|
|
104
|
+
return result[0].css;
|
|
105
|
+
});
|
|
106
|
+
}
|
|
128
107
|
/** Remove unused CSS */
|
|
108
|
+
|
|
109
|
+
|
|
129
110
|
function removeUnusedCss(tree, options, userOptions) {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
141
|
-
return node;
|
|
142
|
-
});
|
|
111
|
+
const promises = [];
|
|
112
|
+
const html = userOptions.tool !== 'purgeCSS' && tree.render(tree);
|
|
113
|
+
tree.walk(node => {
|
|
114
|
+
if ((0, _helpers.isStyleNode)(node)) {
|
|
115
|
+
if (userOptions.tool === 'purgeCSS') {
|
|
116
|
+
promises.push(processStyleNodePurgeCSS(tree, node, userOptions));
|
|
117
|
+
} else {
|
|
118
|
+
promises.push(processStyleNodeUnCSS(html, node, userOptions));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
143
121
|
|
|
144
|
-
return
|
|
145
|
-
|
|
146
|
-
|
|
122
|
+
return node;
|
|
123
|
+
});
|
|
124
|
+
return Promise.all(promises).then(() => tree);
|
|
147
125
|
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = sortAttributes;
|
|
7
|
+
|
|
8
|
+
var _timsort = require("timsort");
|
|
9
|
+
|
|
10
|
+
const validOptions = new Set(['frequency', 'alphabetical']);
|
|
11
|
+
|
|
12
|
+
const processModuleOptions = options => {
|
|
13
|
+
if (options === true) return 'alphabetical';
|
|
14
|
+
return validOptions.has(options) ? options : false;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
class AttributeTokenChain {
|
|
18
|
+
constructor() {
|
|
19
|
+
this.freqData = new Map(); // <attr, frequency>[]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
addFromNodeAttrs(nodeAttrs) {
|
|
23
|
+
Object.keys(nodeAttrs).forEach(attrName => {
|
|
24
|
+
const attrNameLower = attrName.toLowerCase();
|
|
25
|
+
|
|
26
|
+
if (this.freqData.has(attrNameLower)) {
|
|
27
|
+
this.freqData.set(attrNameLower, this.freqData.get(attrNameLower) + 1);
|
|
28
|
+
} else {
|
|
29
|
+
this.freqData.set(attrNameLower, 1);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
createSortOrder() {
|
|
35
|
+
let _sortOrder = [...this.freqData.entries()];
|
|
36
|
+
(0, _timsort.sort)(_sortOrder, (a, b) => b[1] - a[1]);
|
|
37
|
+
this.sortOrder = _sortOrder.map(i => i[0]);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
sortFromNodeAttrs(nodeAttrs) {
|
|
41
|
+
const newAttrs = {}; // Convert node.attrs attrName into lower case.
|
|
42
|
+
|
|
43
|
+
const loweredNodeAttrs = {};
|
|
44
|
+
Object.entries(nodeAttrs).forEach(([attrName, attrValue]) => {
|
|
45
|
+
loweredNodeAttrs[attrName.toLowerCase()] = attrValue;
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
if (!this.sortOrder) {
|
|
49
|
+
this.createSortOrder();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
this.sortOrder.forEach(attrNameLower => {
|
|
53
|
+
// The attrName inside "sortOrder" has been lowered
|
|
54
|
+
if (loweredNodeAttrs[attrNameLower]) {
|
|
55
|
+
newAttrs[attrNameLower] = loweredNodeAttrs[attrNameLower];
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
return newAttrs;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
}
|
|
62
|
+
/** Sort attibutes */
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
function sortAttributes(tree, options, moduleOptions) {
|
|
66
|
+
const sortType = processModuleOptions(moduleOptions);
|
|
67
|
+
|
|
68
|
+
if (sortType === 'alphabetical') {
|
|
69
|
+
return sortAttributesInAlphabeticalOrder(tree);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (sortType === 'frequency') {
|
|
73
|
+
return sortAttributesByFrequency(tree);
|
|
74
|
+
} // Invalid configuration
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
return tree;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function sortAttributesInAlphabeticalOrder(tree) {
|
|
81
|
+
tree.walk(node => {
|
|
82
|
+
if (!node.attrs) {
|
|
83
|
+
return node;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const newAttrs = {};
|
|
87
|
+
Object.keys(node.attrs).sort((a, b) => typeof a.localeCompare === 'function' ? a.localeCompare(b) : a - b).forEach(attr => newAttrs[attr] = node.attrs[attr]);
|
|
88
|
+
node.attrs = newAttrs;
|
|
89
|
+
return node;
|
|
90
|
+
});
|
|
91
|
+
return tree;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function sortAttributesByFrequency(tree) {
|
|
95
|
+
const tokenchain = new AttributeTokenChain(); // Traverse through tree to get frequency
|
|
96
|
+
|
|
97
|
+
tree.walk(node => {
|
|
98
|
+
if (!node.attrs) {
|
|
99
|
+
return node;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
tokenchain.addFromNodeAttrs(node.attrs);
|
|
103
|
+
return node;
|
|
104
|
+
}); // Traverse through tree again, this time sort the attributes
|
|
105
|
+
|
|
106
|
+
tree.walk(node => {
|
|
107
|
+
if (!node.attrs) {
|
|
108
|
+
return node;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
node.attrs = tokenchain.sortFromNodeAttrs(node.attrs);
|
|
112
|
+
return node;
|
|
113
|
+
});
|
|
114
|
+
return tree;
|
|
115
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = collapseAttributeWhitespace;
|
|
7
|
+
|
|
8
|
+
var _timsort = require("timsort");
|
|
9
|
+
|
|
10
|
+
var _collapseAttributeWhitespace = require("./collapseAttributeWhitespace");
|
|
11
|
+
|
|
12
|
+
// class, rel, ping
|
|
13
|
+
const validOptions = new Set(['frequency', 'alphabetical']);
|
|
14
|
+
|
|
15
|
+
const processModuleOptions = options => {
|
|
16
|
+
if (options === true) return 'alphabetical';
|
|
17
|
+
return validOptions.has(options) ? options : false;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
class AttributeTokenChain {
|
|
21
|
+
constructor() {
|
|
22
|
+
this.freqData = new Map(); // <attrValue, frequency>[]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
addFromNodeAttrsArray(attrValuesArray) {
|
|
26
|
+
attrValuesArray.forEach(attrValue => {
|
|
27
|
+
if (this.freqData.has(attrValue)) {
|
|
28
|
+
this.freqData.set(attrValue, this.freqData.get(attrValue) + 1);
|
|
29
|
+
} else {
|
|
30
|
+
this.freqData.set(attrValue, 1);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
createSortOrder() {
|
|
36
|
+
let _sortOrder = [...this.freqData.entries()];
|
|
37
|
+
(0, _timsort.sort)(_sortOrder, (a, b) => b[1] - a[1]);
|
|
38
|
+
this.sortOrder = _sortOrder.map(i => i[0]);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
sortFromNodeAttrsArray(attrValuesArray) {
|
|
42
|
+
const resultArray = [];
|
|
43
|
+
|
|
44
|
+
if (!this.sortOrder) {
|
|
45
|
+
this.createSortOrder();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
this.sortOrder.forEach(k => {
|
|
49
|
+
if (attrValuesArray.includes(k)) {
|
|
50
|
+
resultArray.push(k);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
return resultArray;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
}
|
|
57
|
+
/** Sort values inside list-like attributes (e.g. class, rel) */
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
function collapseAttributeWhitespace(tree, options, moduleOptions) {
|
|
61
|
+
const sortType = processModuleOptions(moduleOptions);
|
|
62
|
+
|
|
63
|
+
if (sortType === 'alphabetical') {
|
|
64
|
+
return sortAttributesWithListsInAlphabeticalOrder(tree);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (sortType === 'frequency') {
|
|
68
|
+
return sortAttributesWithListsByFrequency(tree);
|
|
69
|
+
} // Invalid configuration
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
return tree;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function sortAttributesWithListsInAlphabeticalOrder(tree) {
|
|
76
|
+
tree.walk(node => {
|
|
77
|
+
if (!node.attrs) {
|
|
78
|
+
return node;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
Object.keys(node.attrs).forEach(attrName => {
|
|
82
|
+
const attrNameLower = attrName.toLowerCase();
|
|
83
|
+
|
|
84
|
+
if (!_collapseAttributeWhitespace.attributesWithLists.has(attrNameLower)) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const attrValues = node.attrs[attrName].split(/\s/);
|
|
89
|
+
node.attrs[attrName] = attrValues.sort((a, b) => {
|
|
90
|
+
return typeof a.localeCompare === 'function' ? a.localeCompare(b) : a - b;
|
|
91
|
+
}).join(' ');
|
|
92
|
+
});
|
|
93
|
+
return node;
|
|
94
|
+
});
|
|
95
|
+
return tree;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function sortAttributesWithListsByFrequency(tree) {
|
|
99
|
+
const tokenChainObj = {}; // <attrNameLower: AttributeTokenChain>[]
|
|
100
|
+
// Traverse through tree to get frequency
|
|
101
|
+
|
|
102
|
+
tree.walk(node => {
|
|
103
|
+
if (!node.attrs) {
|
|
104
|
+
return node;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
Object.entries(node.attrs).forEach(([attrName, attrValues]) => {
|
|
108
|
+
const attrNameLower = attrName.toLowerCase();
|
|
109
|
+
|
|
110
|
+
if (!_collapseAttributeWhitespace.attributesWithLists.has(attrNameLower)) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
tokenChainObj[attrNameLower] = tokenChainObj[attrNameLower] || new AttributeTokenChain();
|
|
115
|
+
tokenChainObj[attrNameLower].addFromNodeAttrsArray(attrValues.split(/\s/));
|
|
116
|
+
});
|
|
117
|
+
return node;
|
|
118
|
+
}); // Traverse through tree again, this time sort the attribute values
|
|
119
|
+
|
|
120
|
+
tree.walk(node => {
|
|
121
|
+
if (!node.attrs) {
|
|
122
|
+
return node;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
Object.entries(node.attrs).forEach(([attrName, attrValues]) => {
|
|
126
|
+
const attrNameLower = attrName.toLowerCase();
|
|
127
|
+
|
|
128
|
+
if (!_collapseAttributeWhitespace.attributesWithLists.has(attrNameLower)) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (tokenChainObj[attrNameLower]) {
|
|
133
|
+
node.attrs[attrName] = tokenChainObj[attrNameLower].sortFromNodeAttrsArray(attrValues.split(/\s/)).join(' ');
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
return node;
|
|
137
|
+
});
|
|
138
|
+
}
|
package/lib/presets/ampSafe.js
CHANGED
|
@@ -1,23 +1,26 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
|
|
4
|
+
value: true
|
|
5
5
|
});
|
|
6
|
+
exports.default = void 0;
|
|
6
7
|
|
|
7
|
-
var _safe = require(
|
|
8
|
-
|
|
9
|
-
var _safe2 = _interopRequireDefault(_safe);
|
|
8
|
+
var _safe = _interopRequireDefault(require("./safe"));
|
|
10
9
|
|
|
11
10
|
function _interopRequireDefault(obj) {
|
|
12
|
-
|
|
11
|
+
return obj && obj.__esModule ? obj : {
|
|
12
|
+
default: obj
|
|
13
|
+
};
|
|
13
14
|
}
|
|
14
|
-
|
|
15
15
|
/**
|
|
16
16
|
* A safe preset for AMP pages (https://www.ampproject.org)
|
|
17
17
|
*/
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
var _default = { ..._safe.default,
|
|
21
|
+
collapseBooleanAttributes: {
|
|
22
|
+
amphtml: true
|
|
23
|
+
},
|
|
24
|
+
minifyJs: false
|
|
25
|
+
};
|
|
26
|
+
exports.default = _default;
|
package/lib/presets/max.js
CHANGED
|
@@ -1,27 +1,33 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
|
|
4
|
+
value: true
|
|
5
5
|
});
|
|
6
|
+
exports.default = void 0;
|
|
6
7
|
|
|
7
|
-
var _safe = require(
|
|
8
|
-
|
|
9
|
-
var _safe2 = _interopRequireDefault(_safe);
|
|
8
|
+
var _safe = _interopRequireDefault(require("./safe"));
|
|
10
9
|
|
|
11
10
|
function _interopRequireDefault(obj) {
|
|
12
|
-
|
|
11
|
+
return obj && obj.__esModule ? obj : {
|
|
12
|
+
default: obj
|
|
13
|
+
};
|
|
13
14
|
}
|
|
14
|
-
|
|
15
15
|
/**
|
|
16
16
|
* Maximal minification (might break some pages)
|
|
17
17
|
*/
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
var _default = { ..._safe.default,
|
|
21
|
+
collapseWhitespace: 'all',
|
|
22
|
+
removeComments: 'all',
|
|
23
|
+
removeAttributeQuotes: true,
|
|
24
|
+
removeRedundantAttributes: true,
|
|
25
|
+
removeUnusedCss: {},
|
|
26
|
+
minifyCss: {
|
|
27
|
+
preset: 'default'
|
|
28
|
+
},
|
|
29
|
+
minifySvg: {},
|
|
30
|
+
minifyConditionalComments: true,
|
|
31
|
+
removeOptionalTags: true
|
|
32
|
+
};
|
|
33
|
+
exports.default = _default;
|
package/lib/presets/safe.js
CHANGED
|
@@ -1,31 +1,44 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
|
|
4
|
+
value: true
|
|
5
5
|
});
|
|
6
|
+
exports.default = void 0;
|
|
6
7
|
/**
|
|
7
8
|
* Minify HTML in a safe way without breaking anything.
|
|
8
9
|
*/
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
10
|
+
|
|
11
|
+
var _default = {
|
|
12
|
+
sortAttributes: false,
|
|
13
|
+
collapseAttributeWhitespace: true,
|
|
14
|
+
collapseBooleanAttributes: {
|
|
15
|
+
amphtml: false
|
|
16
|
+
},
|
|
17
|
+
collapseWhitespace: 'conservative',
|
|
18
|
+
custom: [],
|
|
19
|
+
deduplicateAttributeValues: true,
|
|
20
|
+
mergeScripts: true,
|
|
21
|
+
mergeStyles: true,
|
|
22
|
+
removeUnusedCss: false,
|
|
23
|
+
minifyCss: {
|
|
24
|
+
preset: 'default'
|
|
25
|
+
},
|
|
26
|
+
minifyJs: {},
|
|
27
|
+
minifyJson: {},
|
|
28
|
+
minifySvg: {
|
|
29
|
+
plugins: [{
|
|
30
|
+
collapseGroups: false
|
|
31
|
+
}, {
|
|
32
|
+
convertShapeToPath: false
|
|
33
|
+
}]
|
|
34
|
+
},
|
|
35
|
+
minifyConditionalComments: false,
|
|
36
|
+
removeEmptyAttributes: true,
|
|
37
|
+
removeRedundantAttributes: false,
|
|
38
|
+
removeComments: 'safe',
|
|
39
|
+
removeAttributeQuotes: false,
|
|
40
|
+
sortAttributesWithLists: 'alphabetical',
|
|
41
|
+
minifyUrls: false,
|
|
42
|
+
removeOptionalTags: false
|
|
43
|
+
};
|
|
44
|
+
exports.default = _default;
|