htmlnano 3.0.0 → 3.1.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 +18 -17
- package/dist/_modules/collapseAttributeWhitespace.d.mts +41 -5
- package/dist/_modules/collapseAttributeWhitespace.d.ts +41 -5
- package/dist/_modules/collapseAttributeWhitespace.js +69 -16
- package/dist/_modules/collapseAttributeWhitespace.mjs +67 -17
- package/dist/_modules/collapseBooleanAttributes.d.mts +36 -3
- package/dist/_modules/collapseBooleanAttributes.d.ts +36 -3
- package/dist/_modules/collapseBooleanAttributes.js +18 -11
- package/dist/_modules/collapseBooleanAttributes.mjs +18 -11
- package/dist/_modules/collapseWhitespace.d.mts +36 -3
- package/dist/_modules/collapseWhitespace.d.ts +36 -3
- package/dist/_modules/collapseWhitespace.js +25 -2
- package/dist/_modules/collapseWhitespace.mjs +25 -2
- package/dist/_modules/custom.d.mts +36 -3
- package/dist/_modules/custom.d.ts +36 -3
- package/dist/_modules/deduplicateAttributeValues.d.mts +36 -3
- package/dist/_modules/deduplicateAttributeValues.d.ts +36 -3
- package/dist/_modules/deduplicateAttributeValues.js +20 -5
- package/dist/_modules/deduplicateAttributeValues.mjs +21 -6
- package/dist/_modules/example.d.mts +36 -3
- package/dist/_modules/example.d.ts +36 -3
- package/dist/_modules/mergeScripts.d.mts +36 -3
- package/dist/_modules/mergeScripts.d.ts +36 -3
- package/dist/_modules/mergeScripts.js +99 -24
- package/dist/_modules/mergeScripts.mjs +99 -24
- package/dist/_modules/mergeStyles.d.mts +36 -3
- package/dist/_modules/mergeStyles.d.ts +36 -3
- package/dist/_modules/mergeStyles.js +56 -4
- package/dist/_modules/mergeStyles.mjs +56 -4
- package/dist/_modules/minifyAttributes.d.mts +95 -0
- package/dist/_modules/minifyAttributes.d.ts +95 -0
- package/dist/_modules/minifyAttributes.js +159 -0
- package/dist/_modules/minifyAttributes.mjs +157 -0
- package/dist/_modules/minifyConditionalComments.d.mts +36 -3
- package/dist/_modules/minifyConditionalComments.d.ts +36 -3
- package/dist/_modules/minifyConditionalComments.js +37 -19
- package/dist/_modules/minifyConditionalComments.mjs +37 -19
- package/dist/_modules/minifyCss.d.mts +36 -3
- package/dist/_modules/minifyCss.d.ts +36 -3
- package/dist/_modules/minifyCss.js +13 -27
- package/dist/_modules/minifyCss.mjs +14 -28
- package/dist/_modules/minifyHtmlTemplate.d.mts +91 -0
- package/dist/_modules/minifyHtmlTemplate.d.ts +91 -0
- package/dist/_modules/minifyHtmlTemplate.js +231 -0
- package/dist/_modules/minifyHtmlTemplate.mjs +228 -0
- package/dist/_modules/minifyJs.d.mts +36 -3
- package/dist/_modules/minifyJs.d.ts +36 -3
- package/dist/_modules/minifyJs.js +94 -5
- package/dist/_modules/minifyJs.mjs +95 -6
- package/dist/_modules/minifyJson.d.mts +36 -3
- package/dist/_modules/minifyJson.d.ts +36 -3
- package/dist/_modules/minifyJson.js +8 -11
- package/dist/_modules/minifyJson.mjs +8 -11
- package/dist/_modules/minifySvg.d.mts +36 -3
- package/dist/_modules/minifySvg.d.ts +36 -3
- package/dist/_modules/minifySvg.js +35 -4
- package/dist/_modules/minifySvg.mjs +35 -4
- package/dist/_modules/minifyUrls.d.mts +37 -4
- package/dist/_modules/minifyUrls.d.ts +37 -4
- package/dist/_modules/minifyUrls.js +52 -27
- package/dist/_modules/minifyUrls.mjs +52 -27
- package/dist/_modules/normalizeAttributeValues.d.mts +36 -3
- package/dist/_modules/normalizeAttributeValues.d.ts +36 -3
- package/dist/_modules/normalizeAttributeValues.js +10 -8
- package/dist/_modules/normalizeAttributeValues.mjs +10 -8
- package/dist/_modules/removeAttributeQuotes.d.mts +40 -4
- package/dist/_modules/removeAttributeQuotes.d.ts +40 -4
- package/dist/_modules/removeAttributeQuotes.js +9 -4
- package/dist/_modules/removeAttributeQuotes.mjs +9 -4
- package/dist/_modules/removeComments.d.mts +37 -4
- package/dist/_modules/removeComments.d.ts +37 -4
- package/dist/_modules/removeComments.js +44 -12
- package/dist/_modules/removeComments.mjs +44 -12
- package/dist/_modules/removeEmptyAttributes.d.mts +36 -3
- package/dist/_modules/removeEmptyAttributes.d.ts +36 -3
- package/dist/_modules/removeEmptyAttributes.js +37 -16
- package/dist/_modules/removeEmptyAttributes.mjs +37 -16
- package/dist/_modules/removeEmptyElements.d.mts +95 -0
- package/dist/_modules/removeEmptyElements.d.ts +95 -0
- package/dist/_modules/removeEmptyElements.js +90 -0
- package/dist/_modules/removeEmptyElements.mjs +88 -0
- package/dist/_modules/removeOptionalTags.d.mts +36 -3
- package/dist/_modules/removeOptionalTags.d.ts +36 -3
- package/dist/_modules/removeOptionalTags.js +39 -28
- package/dist/_modules/removeOptionalTags.mjs +39 -28
- package/dist/_modules/removeRedundantAttributes.d.mts +36 -3
- package/dist/_modules/removeRedundantAttributes.d.ts +36 -3
- package/dist/_modules/removeRedundantAttributes.js +43 -28
- package/dist/_modules/removeRedundantAttributes.mjs +43 -28
- package/dist/_modules/removeUnusedCss.d.mts +37 -3
- package/dist/_modules/removeUnusedCss.d.ts +37 -3
- package/dist/_modules/removeUnusedCss.js +38 -13
- package/dist/_modules/removeUnusedCss.mjs +39 -14
- package/dist/_modules/sortAttributes.d.mts +36 -3
- package/dist/_modules/sortAttributes.d.ts +36 -3
- package/dist/_modules/sortAttributes.js +23 -5
- package/dist/_modules/sortAttributes.mjs +23 -5
- package/dist/_modules/sortAttributesWithLists.d.mts +36 -3
- package/dist/_modules/sortAttributesWithLists.d.ts +36 -3
- package/dist/_modules/sortAttributesWithLists.js +30 -8
- package/dist/_modules/sortAttributesWithLists.mjs +31 -9
- package/dist/helpers.d.ts +8 -1
- package/dist/helpers.js +48 -0
- package/dist/helpers.mjs +45 -1
- package/dist/index.d.ts +37 -4
- package/dist/index.js +13 -0
- package/dist/index.mjs +13 -0
- package/dist/presets/ampSafe.d.ts +36 -3
- package/dist/presets/max.d.ts +36 -3
- package/dist/presets/max.js +4 -0
- package/dist/presets/max.mjs +4 -0
- package/dist/presets/safe.d.ts +36 -3
- package/dist/presets/safe.js +6 -0
- package/dist/presets/safe.mjs +6 -0
- package/package.json +21 -13
|
@@ -15,6 +15,9 @@ const processModuleOptions = (options)=>{
|
|
|
15
15
|
class AttributeTokenChain {
|
|
16
16
|
addFromNodeAttrsArray(attrValuesArray) {
|
|
17
17
|
attrValuesArray.forEach((attrValue)=>{
|
|
18
|
+
if (!attrValue) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
18
21
|
if (this.freqData.has(attrValue)) {
|
|
19
22
|
this.freqData.set(attrValue, this.freqData.get(attrValue) + 1);
|
|
20
23
|
} else {
|
|
@@ -26,16 +29,28 @@ class AttributeTokenChain {
|
|
|
26
29
|
const _sortOrder = [
|
|
27
30
|
...this.freqData.entries()
|
|
28
31
|
];
|
|
29
|
-
_sortOrder.sort((a, b)=>b[1] - a[1]);
|
|
32
|
+
_sortOrder.sort((a, b)=>b[1] - a[1] || a[0].localeCompare(b[0]));
|
|
30
33
|
this.sortOrder = _sortOrder.map((i)=>i[0]);
|
|
31
34
|
}
|
|
32
35
|
sortFromNodeAttrsArray(attrValuesArray) {
|
|
33
36
|
const resultArray = [];
|
|
37
|
+
const tokenCounts = new Map();
|
|
38
|
+
attrValuesArray.forEach((attrValue)=>{
|
|
39
|
+
var _tokenCounts_get;
|
|
40
|
+
if (!attrValue) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
tokenCounts.set(attrValue, ((_tokenCounts_get = tokenCounts.get(attrValue)) != null ? _tokenCounts_get : 0) + 1);
|
|
44
|
+
});
|
|
34
45
|
if (!this.sortOrder) {
|
|
35
46
|
this.createSortOrder();
|
|
36
47
|
}
|
|
37
48
|
this.sortOrder.forEach((k)=>{
|
|
38
|
-
|
|
49
|
+
const count = tokenCounts.get(k);
|
|
50
|
+
if (!count) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
for(let i = 0; i < count; i += 1){
|
|
39
54
|
resultArray.push(k);
|
|
40
55
|
}
|
|
41
56
|
});
|
|
@@ -59,17 +74,22 @@ class AttributeTokenChain {
|
|
|
59
74
|
return tree;
|
|
60
75
|
}
|
|
61
76
|
};
|
|
77
|
+
const splitListAttributeValues = (attrValue)=>attrValue.split(/\s+/).filter(Boolean);
|
|
62
78
|
function sortAttributesWithListsInAlphabeticalOrder(tree) {
|
|
63
79
|
tree.walk((node)=>{
|
|
64
80
|
if (!node.attrs) {
|
|
65
81
|
return node;
|
|
66
82
|
}
|
|
83
|
+
const tagName = node.tag ? node.tag.toLowerCase() : undefined;
|
|
67
84
|
Object.keys(node.attrs).forEach((attrName)=>{
|
|
68
85
|
const attrNameLower = attrName.toLowerCase();
|
|
69
|
-
if (!collapseAttributeWhitespace_js.
|
|
86
|
+
if (!collapseAttributeWhitespace_js.isListAttribute(attrNameLower, tagName)) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const attrValues = splitListAttributeValues(node.attrs[attrName]);
|
|
90
|
+
if (attrValues.length < 2) {
|
|
70
91
|
return;
|
|
71
92
|
}
|
|
72
|
-
const attrValues = node.attrs[attrName].split(/\s/);
|
|
73
93
|
node.attrs[attrName] = attrValues.sort((a, b)=>{
|
|
74
94
|
// @ts-expect-error -- deliberately use minus operator to sort things
|
|
75
95
|
return typeof a.localeCompare === 'function' ? a.localeCompare(b) : a - b;
|
|
@@ -86,13 +106,14 @@ function sortAttributesWithListsByFrequency(tree) {
|
|
|
86
106
|
if (!node.attrs) {
|
|
87
107
|
return node;
|
|
88
108
|
}
|
|
109
|
+
const tagName = node.tag ? node.tag.toLowerCase() : undefined;
|
|
89
110
|
Object.entries(node.attrs).forEach(([attrName, attrValues])=>{
|
|
90
111
|
const attrNameLower = attrName.toLowerCase();
|
|
91
|
-
if (!collapseAttributeWhitespace_js.
|
|
112
|
+
if (!collapseAttributeWhitespace_js.isListAttribute(attrNameLower, tagName)) {
|
|
92
113
|
return;
|
|
93
114
|
}
|
|
94
115
|
tokenChainObj[attrNameLower] = tokenChainObj[attrNameLower] || new AttributeTokenChain();
|
|
95
|
-
tokenChainObj[attrNameLower].addFromNodeAttrsArray(attrValues
|
|
116
|
+
tokenChainObj[attrNameLower].addFromNodeAttrsArray(splitListAttributeValues(attrValues));
|
|
96
117
|
});
|
|
97
118
|
return node;
|
|
98
119
|
});
|
|
@@ -101,13 +122,14 @@ function sortAttributesWithListsByFrequency(tree) {
|
|
|
101
122
|
if (!node.attrs) {
|
|
102
123
|
return node;
|
|
103
124
|
}
|
|
125
|
+
const tagName = node.tag ? node.tag.toLowerCase() : undefined;
|
|
104
126
|
Object.entries(node.attrs).forEach(([attrName, attrValues])=>{
|
|
105
127
|
const attrNameLower = attrName.toLowerCase();
|
|
106
|
-
if (!collapseAttributeWhitespace_js.
|
|
128
|
+
if (!collapseAttributeWhitespace_js.isListAttribute(attrNameLower, tagName)) {
|
|
107
129
|
return;
|
|
108
130
|
}
|
|
109
131
|
if (tokenChainObj[attrNameLower]) {
|
|
110
|
-
node.attrs[attrName] = tokenChainObj[attrNameLower].sortFromNodeAttrsArray(attrValues
|
|
132
|
+
node.attrs[attrName] = tokenChainObj[attrNameLower].sortFromNodeAttrsArray(splitListAttributeValues(attrValues)).join(' ');
|
|
111
133
|
}
|
|
112
134
|
});
|
|
113
135
|
return node;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isListAttribute } from './collapseAttributeWhitespace.mjs';
|
|
2
2
|
|
|
3
3
|
// class, rel, ping
|
|
4
4
|
const validOptions = new Set([
|
|
@@ -13,6 +13,9 @@ const processModuleOptions = (options)=>{
|
|
|
13
13
|
class AttributeTokenChain {
|
|
14
14
|
addFromNodeAttrsArray(attrValuesArray) {
|
|
15
15
|
attrValuesArray.forEach((attrValue)=>{
|
|
16
|
+
if (!attrValue) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
16
19
|
if (this.freqData.has(attrValue)) {
|
|
17
20
|
this.freqData.set(attrValue, this.freqData.get(attrValue) + 1);
|
|
18
21
|
} else {
|
|
@@ -24,16 +27,28 @@ class AttributeTokenChain {
|
|
|
24
27
|
const _sortOrder = [
|
|
25
28
|
...this.freqData.entries()
|
|
26
29
|
];
|
|
27
|
-
_sortOrder.sort((a, b)=>b[1] - a[1]);
|
|
30
|
+
_sortOrder.sort((a, b)=>b[1] - a[1] || a[0].localeCompare(b[0]));
|
|
28
31
|
this.sortOrder = _sortOrder.map((i)=>i[0]);
|
|
29
32
|
}
|
|
30
33
|
sortFromNodeAttrsArray(attrValuesArray) {
|
|
31
34
|
const resultArray = [];
|
|
35
|
+
const tokenCounts = new Map();
|
|
36
|
+
attrValuesArray.forEach((attrValue)=>{
|
|
37
|
+
var _tokenCounts_get;
|
|
38
|
+
if (!attrValue) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
tokenCounts.set(attrValue, ((_tokenCounts_get = tokenCounts.get(attrValue)) != null ? _tokenCounts_get : 0) + 1);
|
|
42
|
+
});
|
|
32
43
|
if (!this.sortOrder) {
|
|
33
44
|
this.createSortOrder();
|
|
34
45
|
}
|
|
35
46
|
this.sortOrder.forEach((k)=>{
|
|
36
|
-
|
|
47
|
+
const count = tokenCounts.get(k);
|
|
48
|
+
if (!count) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
for(let i = 0; i < count; i += 1){
|
|
37
52
|
resultArray.push(k);
|
|
38
53
|
}
|
|
39
54
|
});
|
|
@@ -57,17 +72,22 @@ class AttributeTokenChain {
|
|
|
57
72
|
return tree;
|
|
58
73
|
}
|
|
59
74
|
};
|
|
75
|
+
const splitListAttributeValues = (attrValue)=>attrValue.split(/\s+/).filter(Boolean);
|
|
60
76
|
function sortAttributesWithListsInAlphabeticalOrder(tree) {
|
|
61
77
|
tree.walk((node)=>{
|
|
62
78
|
if (!node.attrs) {
|
|
63
79
|
return node;
|
|
64
80
|
}
|
|
81
|
+
const tagName = node.tag ? node.tag.toLowerCase() : undefined;
|
|
65
82
|
Object.keys(node.attrs).forEach((attrName)=>{
|
|
66
83
|
const attrNameLower = attrName.toLowerCase();
|
|
67
|
-
if (!
|
|
84
|
+
if (!isListAttribute(attrNameLower, tagName)) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const attrValues = splitListAttributeValues(node.attrs[attrName]);
|
|
88
|
+
if (attrValues.length < 2) {
|
|
68
89
|
return;
|
|
69
90
|
}
|
|
70
|
-
const attrValues = node.attrs[attrName].split(/\s/);
|
|
71
91
|
node.attrs[attrName] = attrValues.sort((a, b)=>{
|
|
72
92
|
// @ts-expect-error -- deliberately use minus operator to sort things
|
|
73
93
|
return typeof a.localeCompare === 'function' ? a.localeCompare(b) : a - b;
|
|
@@ -84,13 +104,14 @@ function sortAttributesWithListsByFrequency(tree) {
|
|
|
84
104
|
if (!node.attrs) {
|
|
85
105
|
return node;
|
|
86
106
|
}
|
|
107
|
+
const tagName = node.tag ? node.tag.toLowerCase() : undefined;
|
|
87
108
|
Object.entries(node.attrs).forEach(([attrName, attrValues])=>{
|
|
88
109
|
const attrNameLower = attrName.toLowerCase();
|
|
89
|
-
if (!
|
|
110
|
+
if (!isListAttribute(attrNameLower, tagName)) {
|
|
90
111
|
return;
|
|
91
112
|
}
|
|
92
113
|
tokenChainObj[attrNameLower] = tokenChainObj[attrNameLower] || new AttributeTokenChain();
|
|
93
|
-
tokenChainObj[attrNameLower].addFromNodeAttrsArray(attrValues
|
|
114
|
+
tokenChainObj[attrNameLower].addFromNodeAttrsArray(splitListAttributeValues(attrValues));
|
|
94
115
|
});
|
|
95
116
|
return node;
|
|
96
117
|
});
|
|
@@ -99,13 +120,14 @@ function sortAttributesWithListsByFrequency(tree) {
|
|
|
99
120
|
if (!node.attrs) {
|
|
100
121
|
return node;
|
|
101
122
|
}
|
|
123
|
+
const tagName = node.tag ? node.tag.toLowerCase() : undefined;
|
|
102
124
|
Object.entries(node.attrs).forEach(([attrName, attrValues])=>{
|
|
103
125
|
const attrNameLower = attrName.toLowerCase();
|
|
104
|
-
if (!
|
|
126
|
+
if (!isListAttribute(attrNameLower, tagName)) {
|
|
105
127
|
return;
|
|
106
128
|
}
|
|
107
129
|
if (tokenChainObj[attrNameLower]) {
|
|
108
|
-
node.attrs[attrName] = tokenChainObj[attrNameLower].sortFromNodeAttrsArray(attrValues
|
|
130
|
+
node.attrs[attrName] = tokenChainObj[attrNameLower].sortFromNodeAttrsArray(splitListAttributeValues(attrValues)).join(' ');
|
|
109
131
|
}
|
|
110
132
|
});
|
|
111
133
|
return node;
|
package/dist/helpers.d.ts
CHANGED
|
@@ -7,10 +7,17 @@ declare function isComment(content: PostHTMLNodeLike | null): boolean;
|
|
|
7
7
|
declare function isConditionalComment(content: string): boolean;
|
|
8
8
|
declare function isStyleNode(node: PostHTML.Node): boolean | undefined;
|
|
9
9
|
declare function extractCssFromStyleNode(node: PostHTML.Node): string | undefined;
|
|
10
|
+
declare function stripCssCdata(css: string): {
|
|
11
|
+
strippedCss: string;
|
|
12
|
+
isCdataWrapped: boolean;
|
|
13
|
+
};
|
|
14
|
+
declare function wrapCssCdata(css: string, isCdataWrapped: boolean): string;
|
|
15
|
+
declare function isCssStyleType(node: PostHTML.Node): boolean;
|
|
16
|
+
declare function normalizeMimeType(value: string): string;
|
|
10
17
|
declare function isEventHandler(attributeName: string): boolean | "";
|
|
11
18
|
declare function extractTextContentFromNode(node: PostHTML.Node): string;
|
|
12
19
|
declare function optionalImport<Module = unknown, Default = Module>(moduleName: string): Promise<(Module & {
|
|
13
20
|
default?: Default;
|
|
14
21
|
}) | NonNullable<Default> | null>;
|
|
15
22
|
|
|
16
|
-
export { extractCssFromStyleNode, extractTextContentFromNode, isAmpBoilerplate, isComment, isConditionalComment, isEventHandler, isStyleNode, optionalImport };
|
|
23
|
+
export { extractCssFromStyleNode, extractTextContentFromNode, isAmpBoilerplate, isComment, isConditionalComment, isCssStyleType, isEventHandler, isStyleNode, normalizeMimeType, optionalImport, stripCssCdata, wrapCssCdata };
|
package/dist/helpers.js
CHANGED
|
@@ -5,6 +5,8 @@ const ampBoilerplateAttributes = [
|
|
|
5
5
|
'amp4ads-boilerplate',
|
|
6
6
|
'amp4email-boilerplate'
|
|
7
7
|
];
|
|
8
|
+
const cssCdataStart = '<![CDATA[';
|
|
9
|
+
const cssCdataEnd = ']]>';
|
|
8
10
|
function isAmpBoilerplate(node) {
|
|
9
11
|
if (!node.attrs) {
|
|
10
12
|
return false;
|
|
@@ -32,6 +34,48 @@ function isStyleNode(node) {
|
|
|
32
34
|
function extractCssFromStyleNode(node) {
|
|
33
35
|
return Array.isArray(node.content) ? node.content.join(' ') : node.content;
|
|
34
36
|
}
|
|
37
|
+
function stripCssCdata(css) {
|
|
38
|
+
const trimmed = css.trim();
|
|
39
|
+
if (!trimmed.startsWith(cssCdataStart) || !trimmed.endsWith(cssCdataEnd)) {
|
|
40
|
+
return {
|
|
41
|
+
strippedCss: css,
|
|
42
|
+
isCdataWrapped: false
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const strippedCss = trimmed.slice(cssCdataStart.length, trimmed.length - cssCdataEnd.length);
|
|
46
|
+
return {
|
|
47
|
+
strippedCss,
|
|
48
|
+
isCdataWrapped: true
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function wrapCssCdata(css, isCdataWrapped) {
|
|
52
|
+
if (!isCdataWrapped) {
|
|
53
|
+
return css;
|
|
54
|
+
}
|
|
55
|
+
return `${cssCdataStart}${css}${cssCdataEnd}`;
|
|
56
|
+
}
|
|
57
|
+
function isCssStyleType(node) {
|
|
58
|
+
if (!node.attrs || !('type' in node.attrs)) {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
const rawType = node.attrs.type;
|
|
62
|
+
if (rawType === '') {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
if (typeof rawType !== 'string') {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
const normalizedType = rawType.trim().toLowerCase();
|
|
69
|
+
return /^text\/css(?:$|\s*;)/.test(normalizedType);
|
|
70
|
+
}
|
|
71
|
+
function normalizeMimeType(value) {
|
|
72
|
+
const trimmed = value.trim();
|
|
73
|
+
if (!trimmed) {
|
|
74
|
+
return '';
|
|
75
|
+
}
|
|
76
|
+
const [mimeType] = trimmed.split(';');
|
|
77
|
+
return mimeType.trim().toLowerCase();
|
|
78
|
+
}
|
|
35
79
|
function isEventHandler(attributeName) {
|
|
36
80
|
return attributeName && attributeName.slice(0, 2).toLowerCase() === 'on' && attributeName.length >= 5;
|
|
37
81
|
}
|
|
@@ -67,6 +111,10 @@ exports.extractTextContentFromNode = extractTextContentFromNode;
|
|
|
67
111
|
exports.isAmpBoilerplate = isAmpBoilerplate;
|
|
68
112
|
exports.isComment = isComment;
|
|
69
113
|
exports.isConditionalComment = isConditionalComment;
|
|
114
|
+
exports.isCssStyleType = isCssStyleType;
|
|
70
115
|
exports.isEventHandler = isEventHandler;
|
|
71
116
|
exports.isStyleNode = isStyleNode;
|
|
117
|
+
exports.normalizeMimeType = normalizeMimeType;
|
|
72
118
|
exports.optionalImport = optionalImport;
|
|
119
|
+
exports.stripCssCdata = stripCssCdata;
|
|
120
|
+
exports.wrapCssCdata = wrapCssCdata;
|
package/dist/helpers.mjs
CHANGED
|
@@ -3,6 +3,8 @@ const ampBoilerplateAttributes = [
|
|
|
3
3
|
'amp4ads-boilerplate',
|
|
4
4
|
'amp4email-boilerplate'
|
|
5
5
|
];
|
|
6
|
+
const cssCdataStart = '<![CDATA[';
|
|
7
|
+
const cssCdataEnd = ']]>';
|
|
6
8
|
function isAmpBoilerplate(node) {
|
|
7
9
|
if (!node.attrs) {
|
|
8
10
|
return false;
|
|
@@ -30,6 +32,48 @@ function isStyleNode(node) {
|
|
|
30
32
|
function extractCssFromStyleNode(node) {
|
|
31
33
|
return Array.isArray(node.content) ? node.content.join(' ') : node.content;
|
|
32
34
|
}
|
|
35
|
+
function stripCssCdata(css) {
|
|
36
|
+
const trimmed = css.trim();
|
|
37
|
+
if (!trimmed.startsWith(cssCdataStart) || !trimmed.endsWith(cssCdataEnd)) {
|
|
38
|
+
return {
|
|
39
|
+
strippedCss: css,
|
|
40
|
+
isCdataWrapped: false
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
const strippedCss = trimmed.slice(cssCdataStart.length, trimmed.length - cssCdataEnd.length);
|
|
44
|
+
return {
|
|
45
|
+
strippedCss,
|
|
46
|
+
isCdataWrapped: true
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function wrapCssCdata(css, isCdataWrapped) {
|
|
50
|
+
if (!isCdataWrapped) {
|
|
51
|
+
return css;
|
|
52
|
+
}
|
|
53
|
+
return `${cssCdataStart}${css}${cssCdataEnd}`;
|
|
54
|
+
}
|
|
55
|
+
function isCssStyleType(node) {
|
|
56
|
+
if (!node.attrs || !('type' in node.attrs)) {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
const rawType = node.attrs.type;
|
|
60
|
+
if (rawType === '') {
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
if (typeof rawType !== 'string') {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
const normalizedType = rawType.trim().toLowerCase();
|
|
67
|
+
return /^text\/css(?:$|\s*;)/.test(normalizedType);
|
|
68
|
+
}
|
|
69
|
+
function normalizeMimeType(value) {
|
|
70
|
+
const trimmed = value.trim();
|
|
71
|
+
if (!trimmed) {
|
|
72
|
+
return '';
|
|
73
|
+
}
|
|
74
|
+
const [mimeType] = trimmed.split(';');
|
|
75
|
+
return mimeType.trim().toLowerCase();
|
|
76
|
+
}
|
|
33
77
|
function isEventHandler(attributeName) {
|
|
34
78
|
return attributeName && attributeName.slice(0, 2).toLowerCase() === 'on' && attributeName.length >= 5;
|
|
35
79
|
}
|
|
@@ -60,4 +104,4 @@ async function optionalImport(moduleName) {
|
|
|
60
104
|
}
|
|
61
105
|
}
|
|
62
106
|
|
|
63
|
-
export { extractCssFromStyleNode, extractTextContentFromNode, isAmpBoilerplate, isComment, isConditionalComment, isEventHandler, isStyleNode, optionalImport };
|
|
107
|
+
export { extractCssFromStyleNode, extractTextContentFromNode, isAmpBoilerplate, isComment, isConditionalComment, isCssStyleType, isEventHandler, isStyleNode, normalizeMimeType, optionalImport, stripCssCdata, wrapCssCdata };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,16 +2,24 @@ import PostHTML from 'posthtml';
|
|
|
2
2
|
import { MinifyOptions } from 'terser';
|
|
3
3
|
import { Options } from 'cssnano';
|
|
4
4
|
import { Config } from 'svgo';
|
|
5
|
+
import { UserDefinedOptions } from 'purgecss';
|
|
5
6
|
|
|
6
7
|
type PostHTMLTreeLike = [PostHTML.Node] & PostHTML.NodeAPI & {
|
|
7
8
|
options?: {
|
|
8
9
|
quoteAllAttributes?: boolean | undefined;
|
|
10
|
+
quoteStyle?: 0 | 1 | 2 | undefined;
|
|
11
|
+
replaceQuote?: boolean | undefined;
|
|
9
12
|
} | undefined;
|
|
10
13
|
render(): string;
|
|
11
14
|
render(node: PostHTML.Node | PostHTMLTreeLike, renderOptions?: any): string;
|
|
12
15
|
};
|
|
13
16
|
type MaybeArray<T> = T | Array<T>;
|
|
14
17
|
type PostHTMLNodeLike = PostHTML.Node | string;
|
|
18
|
+
type HtmlnanoTemplateRule = {
|
|
19
|
+
tag: string;
|
|
20
|
+
attrs?: Record<string, string | boolean | void>;
|
|
21
|
+
};
|
|
22
|
+
type MinifyHtmlTemplateOptions = boolean | HtmlnanoTemplateRule[];
|
|
15
23
|
interface HtmlnanoOptions {
|
|
16
24
|
skipConfigLoading?: boolean;
|
|
17
25
|
configPath?: string;
|
|
@@ -27,17 +35,42 @@ interface HtmlnanoOptions {
|
|
|
27
35
|
mergeStyles?: boolean;
|
|
28
36
|
mergeScripts?: boolean;
|
|
29
37
|
minifyCss?: Options | boolean;
|
|
38
|
+
minifyHtmlTemplate?: MinifyHtmlTemplateOptions;
|
|
30
39
|
minifyConditionalComments?: boolean;
|
|
31
40
|
minifyJs?: MinifyOptions | boolean;
|
|
32
41
|
minifyJson?: boolean;
|
|
42
|
+
minifyAttributes?: boolean | {
|
|
43
|
+
metaContent?: boolean;
|
|
44
|
+
redundantWhitespaces?: 'safe' | 'agressive' | false;
|
|
45
|
+
};
|
|
33
46
|
minifySvg?: Config | boolean;
|
|
34
47
|
normalizeAttributeValues?: boolean;
|
|
35
|
-
removeAttributeQuotes?: boolean
|
|
36
|
-
|
|
48
|
+
removeAttributeQuotes?: boolean | {
|
|
49
|
+
force?: boolean;
|
|
50
|
+
};
|
|
51
|
+
removeComments?: boolean | RegExp | ((comment: string) => boolean) | string;
|
|
37
52
|
removeEmptyAttributes?: boolean;
|
|
53
|
+
removeEmptyElements?: boolean | {
|
|
54
|
+
removeWithAttributes?: boolean;
|
|
55
|
+
};
|
|
38
56
|
removeRedundantAttributes?: boolean;
|
|
39
57
|
removeOptionalTags?: boolean;
|
|
40
|
-
removeUnusedCss?: boolean
|
|
58
|
+
removeUnusedCss?: boolean | ({
|
|
59
|
+
tool: 'purgeCSS';
|
|
60
|
+
} & Omit<UserDefinedOptions, 'content' | 'css' | 'extractors'>) | {
|
|
61
|
+
banner?: boolean;
|
|
62
|
+
csspath?: string;
|
|
63
|
+
htmlroot?: string;
|
|
64
|
+
ignore?: (string | RegExp)[];
|
|
65
|
+
inject?: string;
|
|
66
|
+
jsdom?: object;
|
|
67
|
+
media?: string[];
|
|
68
|
+
report?: boolean;
|
|
69
|
+
strictSSL?: boolean;
|
|
70
|
+
timeout?: number;
|
|
71
|
+
uncssrc?: string;
|
|
72
|
+
userAgent?: string;
|
|
73
|
+
};
|
|
41
74
|
sortAttributes?: boolean | 'alphabetical' | 'frequency';
|
|
42
75
|
sortAttributesWithLists?: boolean | 'alphabetical' | 'frequency';
|
|
43
76
|
}
|
|
@@ -77,4 +110,4 @@ declare function htmlMinimizerWebpackPluginMinify(input: {
|
|
|
77
110
|
}>;
|
|
78
111
|
|
|
79
112
|
export { htmlnano as default, getRequiredOptionalDependencies, htmlMinimizerWebpackPluginMinify, loadConfig, presets, process };
|
|
80
|
-
export type { HtmlnanoModule, HtmlnanoModuleAttrsHandler, HtmlnanoModuleContentHandler, HtmlnanoModuleNodeHandler, HtmlnanoOptions, HtmlnanoOptionsConfigFile, HtmlnanoPredefinedPreset, HtmlnanoPredefinedPresets, HtmlnanoPreset, PostHTMLNodeLike, PostHTMLTreeLike };
|
|
113
|
+
export type { HtmlnanoModule, HtmlnanoModuleAttrsHandler, HtmlnanoModuleContentHandler, HtmlnanoModuleNodeHandler, HtmlnanoOptions, HtmlnanoOptionsConfigFile, HtmlnanoPredefinedPreset, HtmlnanoPredefinedPresets, HtmlnanoPreset, HtmlnanoTemplateRule, MinifyHtmlTemplateOptions, PostHTMLNodeLike, PostHTMLTreeLike };
|
package/dist/index.js
CHANGED
|
@@ -125,14 +125,17 @@ const modules = {
|
|
|
125
125
|
mergeStyles: ()=>interop(import('./_modules/mergeStyles.js')),
|
|
126
126
|
minifyConditionalComments: ()=>interop(import('./_modules/minifyConditionalComments.js')),
|
|
127
127
|
minifyCss: ()=>interop(import('./_modules/minifyCss.js')),
|
|
128
|
+
minifyHtmlTemplate: ()=>interop(import('./_modules/minifyHtmlTemplate.js')),
|
|
128
129
|
minifyJs: ()=>interop(import('./_modules/minifyJs.js')),
|
|
129
130
|
minifyJson: ()=>interop(import('./_modules/minifyJson.js')),
|
|
131
|
+
minifyAttributes: ()=>interop(import('./_modules/minifyAttributes.js')),
|
|
130
132
|
minifySvg: ()=>interop(import('./_modules/minifySvg.js')),
|
|
131
133
|
minifyUrls: ()=>interop(import('./_modules/minifyUrls.js')),
|
|
132
134
|
normalizeAttributeValues: ()=>interop(import('./_modules/normalizeAttributeValues.js')),
|
|
133
135
|
removeAttributeQuotes: ()=>interop(import('./_modules/removeAttributeQuotes.js')),
|
|
134
136
|
removeComments: ()=>interop(import('./_modules/removeComments.js')),
|
|
135
137
|
removeEmptyAttributes: ()=>interop(import('./_modules/removeEmptyAttributes.js')),
|
|
138
|
+
removeEmptyElements: ()=>interop(import('./_modules/removeEmptyElements.js')),
|
|
136
139
|
removeOptionalTags: ()=>interop(import('./_modules/removeOptionalTags.js')),
|
|
137
140
|
removeRedundantAttributes: ()=>interop(import('./_modules/removeRedundantAttributes.js')),
|
|
138
141
|
removeUnusedCss: ()=>interop(import('./_modules/removeUnusedCss.js')),
|
|
@@ -152,7 +155,13 @@ const htmlnano = Object.assign(function htmlnano(optionsRun = {}, presetRun) {
|
|
|
152
155
|
...options
|
|
153
156
|
};
|
|
154
157
|
let promise = Promise.resolve(tree);
|
|
158
|
+
const nonModuleOptions = new Set([
|
|
159
|
+
'skipInternalWarnings'
|
|
160
|
+
]);
|
|
155
161
|
for (const [moduleName, moduleOptions] of Object.entries(options)){
|
|
162
|
+
if (nonModuleOptions.has(moduleName)) {
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
156
165
|
if (!moduleOptions) {
|
|
157
166
|
continue;
|
|
158
167
|
}
|
|
@@ -179,15 +188,19 @@ const htmlnano = Object.assign(function htmlnano(optionsRun = {}, presetRun) {
|
|
|
179
188
|
}
|
|
180
189
|
const mod = moduleName in modules ? await modules[moduleName]() : await import(`./_modules/${moduleName}.mjs`);
|
|
181
190
|
if (typeof mod.onAttrs === 'function') {
|
|
191
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- module options are generic
|
|
182
192
|
attrsHandlers.push(mod.onAttrs(options, moduleOptions));
|
|
183
193
|
}
|
|
184
194
|
if (typeof mod.onContent === 'function') {
|
|
195
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- module options are generic
|
|
185
196
|
contentsHandlers.push(mod.onContent(options, moduleOptions));
|
|
186
197
|
}
|
|
187
198
|
if (typeof mod.onNode === 'function') {
|
|
199
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- module options are generic
|
|
188
200
|
nodeHandlers.push(mod.onNode(options, moduleOptions));
|
|
189
201
|
}
|
|
190
202
|
if (typeof mod.default === 'function') {
|
|
203
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- module options are generic
|
|
191
204
|
promise = promise.then(async (tree)=>await mod.default(tree, options, moduleOptions));
|
|
192
205
|
}
|
|
193
206
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -116,14 +116,17 @@ const modules = {
|
|
|
116
116
|
mergeStyles: ()=>interop(import('./_modules/mergeStyles.mjs')),
|
|
117
117
|
minifyConditionalComments: ()=>interop(import('./_modules/minifyConditionalComments.mjs')),
|
|
118
118
|
minifyCss: ()=>interop(import('./_modules/minifyCss.mjs')),
|
|
119
|
+
minifyHtmlTemplate: ()=>interop(import('./_modules/minifyHtmlTemplate.mjs')),
|
|
119
120
|
minifyJs: ()=>interop(import('./_modules/minifyJs.mjs')),
|
|
120
121
|
minifyJson: ()=>interop(import('./_modules/minifyJson.mjs')),
|
|
122
|
+
minifyAttributes: ()=>interop(import('./_modules/minifyAttributes.mjs')),
|
|
121
123
|
minifySvg: ()=>interop(import('./_modules/minifySvg.mjs')),
|
|
122
124
|
minifyUrls: ()=>interop(import('./_modules/minifyUrls.mjs')),
|
|
123
125
|
normalizeAttributeValues: ()=>interop(import('./_modules/normalizeAttributeValues.mjs')),
|
|
124
126
|
removeAttributeQuotes: ()=>interop(import('./_modules/removeAttributeQuotes.mjs')),
|
|
125
127
|
removeComments: ()=>interop(import('./_modules/removeComments.mjs')),
|
|
126
128
|
removeEmptyAttributes: ()=>interop(import('./_modules/removeEmptyAttributes.mjs')),
|
|
129
|
+
removeEmptyElements: ()=>interop(import('./_modules/removeEmptyElements.mjs')),
|
|
127
130
|
removeOptionalTags: ()=>interop(import('./_modules/removeOptionalTags.mjs')),
|
|
128
131
|
removeRedundantAttributes: ()=>interop(import('./_modules/removeRedundantAttributes.mjs')),
|
|
129
132
|
removeUnusedCss: ()=>interop(import('./_modules/removeUnusedCss.mjs')),
|
|
@@ -143,7 +146,13 @@ const htmlnano = Object.assign(function htmlnano(optionsRun = {}, presetRun) {
|
|
|
143
146
|
...options
|
|
144
147
|
};
|
|
145
148
|
let promise = Promise.resolve(tree);
|
|
149
|
+
const nonModuleOptions = new Set([
|
|
150
|
+
'skipInternalWarnings'
|
|
151
|
+
]);
|
|
146
152
|
for (const [moduleName, moduleOptions] of Object.entries(options)){
|
|
153
|
+
if (nonModuleOptions.has(moduleName)) {
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
147
156
|
if (!moduleOptions) {
|
|
148
157
|
continue;
|
|
149
158
|
}
|
|
@@ -170,15 +179,19 @@ const htmlnano = Object.assign(function htmlnano(optionsRun = {}, presetRun) {
|
|
|
170
179
|
}
|
|
171
180
|
const mod = moduleName in modules ? await modules[moduleName]() : await import(`./_modules/${moduleName}.mjs`);
|
|
172
181
|
if (typeof mod.onAttrs === 'function') {
|
|
182
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- module options are generic
|
|
173
183
|
attrsHandlers.push(mod.onAttrs(options, moduleOptions));
|
|
174
184
|
}
|
|
175
185
|
if (typeof mod.onContent === 'function') {
|
|
186
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- module options are generic
|
|
176
187
|
contentsHandlers.push(mod.onContent(options, moduleOptions));
|
|
177
188
|
}
|
|
178
189
|
if (typeof mod.onNode === 'function') {
|
|
190
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- module options are generic
|
|
179
191
|
nodeHandlers.push(mod.onNode(options, moduleOptions));
|
|
180
192
|
}
|
|
181
193
|
if (typeof mod.default === 'function') {
|
|
194
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- module options are generic
|
|
182
195
|
promise = promise.then(async (tree)=>await mod.default(tree, options, moduleOptions));
|
|
183
196
|
}
|
|
184
197
|
}
|
|
@@ -2,15 +2,23 @@ import PostHTML from 'posthtml';
|
|
|
2
2
|
import { MinifyOptions } from 'terser';
|
|
3
3
|
import { Options } from 'cssnano';
|
|
4
4
|
import { Config } from 'svgo';
|
|
5
|
+
import { UserDefinedOptions } from 'purgecss';
|
|
5
6
|
|
|
6
7
|
type PostHTMLTreeLike = [PostHTML.Node] & PostHTML.NodeAPI & {
|
|
7
8
|
options?: {
|
|
8
9
|
quoteAllAttributes?: boolean | undefined;
|
|
10
|
+
quoteStyle?: 0 | 1 | 2 | undefined;
|
|
11
|
+
replaceQuote?: boolean | undefined;
|
|
9
12
|
} | undefined;
|
|
10
13
|
render(): string;
|
|
11
14
|
render(node: PostHTML.Node | PostHTMLTreeLike, renderOptions?: any): string;
|
|
12
15
|
};
|
|
13
16
|
type MaybeArray<T> = T | Array<T>;
|
|
17
|
+
type HtmlnanoTemplateRule = {
|
|
18
|
+
tag: string;
|
|
19
|
+
attrs?: Record<string, string | boolean | void>;
|
|
20
|
+
};
|
|
21
|
+
type MinifyHtmlTemplateOptions = boolean | HtmlnanoTemplateRule[];
|
|
14
22
|
interface HtmlnanoOptions {
|
|
15
23
|
skipConfigLoading?: boolean;
|
|
16
24
|
configPath?: string;
|
|
@@ -26,17 +34,42 @@ interface HtmlnanoOptions {
|
|
|
26
34
|
mergeStyles?: boolean;
|
|
27
35
|
mergeScripts?: boolean;
|
|
28
36
|
minifyCss?: Options | boolean;
|
|
37
|
+
minifyHtmlTemplate?: MinifyHtmlTemplateOptions;
|
|
29
38
|
minifyConditionalComments?: boolean;
|
|
30
39
|
minifyJs?: MinifyOptions | boolean;
|
|
31
40
|
minifyJson?: boolean;
|
|
41
|
+
minifyAttributes?: boolean | {
|
|
42
|
+
metaContent?: boolean;
|
|
43
|
+
redundantWhitespaces?: 'safe' | 'agressive' | false;
|
|
44
|
+
};
|
|
32
45
|
minifySvg?: Config | boolean;
|
|
33
46
|
normalizeAttributeValues?: boolean;
|
|
34
|
-
removeAttributeQuotes?: boolean
|
|
35
|
-
|
|
47
|
+
removeAttributeQuotes?: boolean | {
|
|
48
|
+
force?: boolean;
|
|
49
|
+
};
|
|
50
|
+
removeComments?: boolean | RegExp | ((comment: string) => boolean) | string;
|
|
36
51
|
removeEmptyAttributes?: boolean;
|
|
52
|
+
removeEmptyElements?: boolean | {
|
|
53
|
+
removeWithAttributes?: boolean;
|
|
54
|
+
};
|
|
37
55
|
removeRedundantAttributes?: boolean;
|
|
38
56
|
removeOptionalTags?: boolean;
|
|
39
|
-
removeUnusedCss?: boolean
|
|
57
|
+
removeUnusedCss?: boolean | ({
|
|
58
|
+
tool: 'purgeCSS';
|
|
59
|
+
} & Omit<UserDefinedOptions, 'content' | 'css' | 'extractors'>) | {
|
|
60
|
+
banner?: boolean;
|
|
61
|
+
csspath?: string;
|
|
62
|
+
htmlroot?: string;
|
|
63
|
+
ignore?: (string | RegExp)[];
|
|
64
|
+
inject?: string;
|
|
65
|
+
jsdom?: object;
|
|
66
|
+
media?: string[];
|
|
67
|
+
report?: boolean;
|
|
68
|
+
strictSSL?: boolean;
|
|
69
|
+
timeout?: number;
|
|
70
|
+
uncssrc?: string;
|
|
71
|
+
userAgent?: string;
|
|
72
|
+
};
|
|
40
73
|
sortAttributes?: boolean | 'alphabetical' | 'frequency';
|
|
41
74
|
sortAttributesWithLists?: boolean | 'alphabetical' | 'frequency';
|
|
42
75
|
}
|
package/dist/presets/max.d.ts
CHANGED
|
@@ -2,15 +2,23 @@ import PostHTML from 'posthtml';
|
|
|
2
2
|
import { MinifyOptions } from 'terser';
|
|
3
3
|
import { Options } from 'cssnano';
|
|
4
4
|
import { Config } from 'svgo';
|
|
5
|
+
import { UserDefinedOptions } from 'purgecss';
|
|
5
6
|
|
|
6
7
|
type PostHTMLTreeLike = [PostHTML.Node] & PostHTML.NodeAPI & {
|
|
7
8
|
options?: {
|
|
8
9
|
quoteAllAttributes?: boolean | undefined;
|
|
10
|
+
quoteStyle?: 0 | 1 | 2 | undefined;
|
|
11
|
+
replaceQuote?: boolean | undefined;
|
|
9
12
|
} | undefined;
|
|
10
13
|
render(): string;
|
|
11
14
|
render(node: PostHTML.Node | PostHTMLTreeLike, renderOptions?: any): string;
|
|
12
15
|
};
|
|
13
16
|
type MaybeArray<T> = T | Array<T>;
|
|
17
|
+
type HtmlnanoTemplateRule = {
|
|
18
|
+
tag: string;
|
|
19
|
+
attrs?: Record<string, string | boolean | void>;
|
|
20
|
+
};
|
|
21
|
+
type MinifyHtmlTemplateOptions = boolean | HtmlnanoTemplateRule[];
|
|
14
22
|
interface HtmlnanoOptions {
|
|
15
23
|
skipConfigLoading?: boolean;
|
|
16
24
|
configPath?: string;
|
|
@@ -26,17 +34,42 @@ interface HtmlnanoOptions {
|
|
|
26
34
|
mergeStyles?: boolean;
|
|
27
35
|
mergeScripts?: boolean;
|
|
28
36
|
minifyCss?: Options | boolean;
|
|
37
|
+
minifyHtmlTemplate?: MinifyHtmlTemplateOptions;
|
|
29
38
|
minifyConditionalComments?: boolean;
|
|
30
39
|
minifyJs?: MinifyOptions | boolean;
|
|
31
40
|
minifyJson?: boolean;
|
|
41
|
+
minifyAttributes?: boolean | {
|
|
42
|
+
metaContent?: boolean;
|
|
43
|
+
redundantWhitespaces?: 'safe' | 'agressive' | false;
|
|
44
|
+
};
|
|
32
45
|
minifySvg?: Config | boolean;
|
|
33
46
|
normalizeAttributeValues?: boolean;
|
|
34
|
-
removeAttributeQuotes?: boolean
|
|
35
|
-
|
|
47
|
+
removeAttributeQuotes?: boolean | {
|
|
48
|
+
force?: boolean;
|
|
49
|
+
};
|
|
50
|
+
removeComments?: boolean | RegExp | ((comment: string) => boolean) | string;
|
|
36
51
|
removeEmptyAttributes?: boolean;
|
|
52
|
+
removeEmptyElements?: boolean | {
|
|
53
|
+
removeWithAttributes?: boolean;
|
|
54
|
+
};
|
|
37
55
|
removeRedundantAttributes?: boolean;
|
|
38
56
|
removeOptionalTags?: boolean;
|
|
39
|
-
removeUnusedCss?: boolean
|
|
57
|
+
removeUnusedCss?: boolean | ({
|
|
58
|
+
tool: 'purgeCSS';
|
|
59
|
+
} & Omit<UserDefinedOptions, 'content' | 'css' | 'extractors'>) | {
|
|
60
|
+
banner?: boolean;
|
|
61
|
+
csspath?: string;
|
|
62
|
+
htmlroot?: string;
|
|
63
|
+
ignore?: (string | RegExp)[];
|
|
64
|
+
inject?: string;
|
|
65
|
+
jsdom?: object;
|
|
66
|
+
media?: string[];
|
|
67
|
+
report?: boolean;
|
|
68
|
+
strictSSL?: boolean;
|
|
69
|
+
timeout?: number;
|
|
70
|
+
uncssrc?: string;
|
|
71
|
+
userAgent?: string;
|
|
72
|
+
};
|
|
40
73
|
sortAttributes?: boolean | 'alphabetical' | 'frequency';
|
|
41
74
|
sortAttributesWithLists?: boolean | 'alphabetical' | 'frequency';
|
|
42
75
|
}
|