htmlnano 2.1.1 → 2.1.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/README.md +53 -12
- package/dist/_modules/collapseAttributeWhitespace.d.mts +57 -0
- package/dist/_modules/collapseAttributeWhitespace.d.ts +57 -0
- package/dist/_modules/collapseAttributeWhitespace.js +296 -0
- package/dist/_modules/collapseAttributeWhitespace.mjs +293 -0
- package/dist/_modules/collapseBooleanAttributes.d.mts +60 -0
- package/dist/_modules/collapseBooleanAttributes.d.ts +60 -0
- package/dist/_modules/collapseBooleanAttributes.js +159 -0
- package/{lib/modules → dist/_modules}/collapseBooleanAttributes.mjs +39 -57
- package/dist/_modules/collapseWhitespace.d.mts +57 -0
- package/dist/_modules/collapseWhitespace.d.ts +57 -0
- package/dist/_modules/collapseWhitespace.js +172 -0
- package/dist/_modules/collapseWhitespace.mjs +170 -0
- package/dist/_modules/custom.d.mts +57 -0
- package/dist/_modules/custom.d.ts +57 -0
- package/dist/_modules/custom.js +22 -0
- package/dist/_modules/custom.mjs +20 -0
- package/dist/_modules/deduplicateAttributeValues.d.mts +56 -0
- package/dist/_modules/deduplicateAttributeValues.d.ts +56 -0
- package/dist/_modules/deduplicateAttributeValues.js +38 -0
- package/dist/_modules/deduplicateAttributeValues.mjs +36 -0
- package/dist/_modules/example.d.mts +59 -0
- package/dist/_modules/example.d.ts +59 -0
- package/dist/_modules/example.js +67 -0
- package/dist/_modules/example.mjs +65 -0
- package/dist/_modules/mergeScripts.d.mts +56 -0
- package/dist/_modules/mergeScripts.d.ts +56 -0
- package/dist/_modules/mergeScripts.js +53 -0
- package/dist/_modules/mergeScripts.mjs +51 -0
- package/dist/_modules/mergeStyles.d.mts +56 -0
- package/dist/_modules/mergeStyles.d.ts +56 -0
- package/dist/_modules/mergeStyles.js +42 -0
- package/dist/_modules/mergeStyles.mjs +40 -0
- package/dist/_modules/minifyConditionalComments.d.mts +56 -0
- package/dist/_modules/minifyConditionalComments.d.ts +56 -0
- package/dist/_modules/minifyConditionalComments.js +54 -0
- package/{lib/modules → dist/_modules}/minifyConditionalComments.mjs +21 -22
- package/dist/_modules/minifyCss.d.mts +56 -0
- package/dist/_modules/minifyCss.d.ts +56 -0
- package/dist/_modules/minifyCss.js +84 -0
- package/dist/_modules/minifyCss.mjs +82 -0
- package/dist/_modules/minifyJs.d.mts +56 -0
- package/dist/_modules/minifyJs.d.ts +56 -0
- package/dist/_modules/minifyJs.js +108 -0
- package/dist/_modules/minifyJs.mjs +106 -0
- package/dist/_modules/minifyJson.d.mts +56 -0
- package/dist/_modules/minifyJson.d.ts +56 -0
- package/dist/_modules/minifyJson.js +35 -0
- package/dist/_modules/minifyJson.mjs +33 -0
- package/dist/_modules/minifySvg.d.mts +56 -0
- package/dist/_modules/minifySvg.d.ts +56 -0
- package/dist/_modules/minifySvg.js +40 -0
- package/dist/_modules/minifySvg.mjs +38 -0
- package/dist/_modules/minifyUrls.d.mts +56 -0
- package/dist/_modules/minifyUrls.d.ts +56 -0
- package/dist/_modules/minifyUrls.js +180 -0
- package/dist/_modules/minifyUrls.mjs +178 -0
- package/dist/_modules/normalizeAttributeValues.d.mts +56 -0
- package/dist/_modules/normalizeAttributeValues.d.ts +56 -0
- package/dist/_modules/normalizeAttributeValues.js +234 -0
- package/dist/_modules/normalizeAttributeValues.mjs +232 -0
- package/dist/_modules/removeAttributeQuotes.d.mts +56 -0
- package/dist/_modules/removeAttributeQuotes.d.ts +56 -0
- package/dist/_modules/removeAttributeQuotes.js +15 -0
- package/dist/_modules/removeAttributeQuotes.mjs +13 -0
- package/dist/_modules/removeComments.d.mts +58 -0
- package/dist/_modules/removeComments.d.ts +58 -0
- package/dist/_modules/removeComments.js +83 -0
- package/{lib/modules → dist/_modules}/removeComments.mjs +24 -35
- package/dist/_modules/removeEmptyAttributes.d.mts +56 -0
- package/dist/_modules/removeEmptyAttributes.d.ts +56 -0
- package/dist/_modules/removeEmptyAttributes.js +197 -0
- package/dist/_modules/removeEmptyAttributes.mjs +195 -0
- package/dist/_modules/removeOptionalTags.d.mts +56 -0
- package/dist/_modules/removeOptionalTags.d.ts +56 -0
- package/dist/_modules/removeOptionalTags.js +190 -0
- package/{lib/modules → dist/_modules}/removeOptionalTags.mjs +54 -91
- package/dist/_modules/removeRedundantAttributes.d.mts +57 -0
- package/dist/_modules/removeRedundantAttributes.d.ts +57 -0
- package/dist/_modules/removeRedundantAttributes.js +128 -0
- package/{lib/modules → dist/_modules}/removeRedundantAttributes.mjs +43 -59
- package/dist/_modules/removeUnusedCss.d.mts +60 -0
- package/dist/_modules/removeUnusedCss.d.ts +60 -0
- package/dist/_modules/removeUnusedCss.js +134 -0
- package/dist/_modules/removeUnusedCss.mjs +132 -0
- package/dist/_modules/sortAttributes.d.mts +57 -0
- package/dist/_modules/sortAttributes.d.ts +57 -0
- package/dist/_modules/sortAttributes.js +102 -0
- package/{lib/modules → dist/_modules}/sortAttributes.mjs +39 -60
- package/dist/_modules/sortAttributesWithLists.d.mts +56 -0
- package/dist/_modules/sortAttributesWithLists.d.ts +56 -0
- package/dist/_modules/sortAttributesWithLists.js +118 -0
- package/{lib/modules → dist/_modules}/sortAttributesWithLists.mjs +41 -60
- package/dist/helpers.js +72 -0
- package/dist/helpers.mjs +63 -0
- package/dist/index.js +223 -0
- package/dist/index.mjs +209 -0
- package/dist/presets/ampSafe.js +19 -0
- package/{lib → dist}/presets/ampSafe.mjs +6 -4
- package/dist/presets/max.js +28 -0
- package/{lib → dist}/presets/max.mjs +6 -4
- package/dist/presets/safe.js +60 -0
- package/{lib → dist}/presets/safe.mjs +13 -20
- package/package.json +53 -59
- package/.eslintignore +0 -3
- package/CHANGELOG.md +0 -398
- package/docs/README.md +0 -33
- package/docs/babel.config.js +0 -3
- package/docs/docs/010-introduction.md +0 -22
- package/docs/docs/020-usage.md +0 -117
- package/docs/docs/030-config.md +0 -21
- package/docs/docs/040-presets.md +0 -75
- package/docs/docs/050-modules.md +0 -855
- package/docs/docs/060-contribute.md +0 -16
- package/docs/docusaurus.config.js +0 -65
- package/docs/netlify.toml +0 -4
- package/docs/package-lock.json +0 -21796
- package/docs/package.json +0 -40
- package/docs/sidebars.js +0 -26
- package/docs/versioned_docs/version-1.1.1/010-introduction.md +0 -22
- package/docs/versioned_docs/version-1.1.1/020-usage.md +0 -77
- package/docs/versioned_docs/version-1.1.1/030-config.md +0 -21
- package/docs/versioned_docs/version-1.1.1/040-presets.md +0 -75
- package/docs/versioned_docs/version-1.1.1/050-modules.md +0 -785
- package/docs/versioned_docs/version-1.1.1/060-contribute.md +0 -16
- package/docs/versioned_docs/version-2.0.0/010-introduction.md +0 -22
- package/docs/versioned_docs/version-2.0.0/020-usage.md +0 -77
- package/docs/versioned_docs/version-2.0.0/030-config.md +0 -21
- package/docs/versioned_docs/version-2.0.0/040-presets.md +0 -75
- package/docs/versioned_docs/version-2.0.0/050-modules.md +0 -838
- package/docs/versioned_docs/version-2.0.0/060-contribute.md +0 -16
- package/docs/versioned_sidebars/version-1.1.1-sidebars.json +0 -8
- package/docs/versioned_sidebars/version-2.0.0-sidebars.json +0 -8
- package/docs/versions.json +0 -4
- package/index.cjs +0 -11
- package/index.d.cts +0 -3
- package/index.d.mts +0 -3
- package/index.d.ts +0 -93
- package/index.mjs +0 -2
- package/lib/helpers.cjs +0 -79
- package/lib/helpers.mjs +0 -53
- package/lib/htmlnano.cjs +0 -200
- package/lib/htmlnano.mjs +0 -196
- package/lib/modules/collapseAttributeWhitespace.cjs +0 -86
- package/lib/modules/collapseAttributeWhitespace.mjs +0 -104
- package/lib/modules/collapseBooleanAttributes.cjs +0 -62
- package/lib/modules/collapseWhitespace.cjs +0 -100
- package/lib/modules/collapseWhitespace.mjs +0 -132
- package/lib/modules/custom.cjs +0 -19
- package/lib/modules/custom.mjs +0 -16
- package/lib/modules/deduplicateAttributeValues.cjs +0 -38
- package/lib/modules/deduplicateAttributeValues.mjs +0 -40
- package/lib/modules/example.cjs +0 -85
- package/lib/modules/example.mjs +0 -75
- package/lib/modules/mergeScripts.cjs +0 -54
- package/lib/modules/mergeScripts.mjs +0 -56
- package/lib/modules/mergeStyles.cjs +0 -38
- package/lib/modules/mergeStyles.mjs +0 -36
- package/lib/modules/minifyConditionalComments.cjs +0 -47
- package/lib/modules/minifyCss.cjs +0 -73
- package/lib/modules/minifyCss.mjs +0 -88
- package/lib/modules/minifyJs.cjs +0 -103
- package/lib/modules/minifyJs.mjs +0 -121
- package/lib/modules/minifyJson.cjs +0 -24
- package/lib/modules/minifyJson.mjs +0 -21
- package/lib/modules/minifySvg.cjs +0 -37
- package/lib/modules/minifySvg.mjs +0 -30
- package/lib/modules/minifyUrls.cjs +0 -141
- package/lib/modules/minifyUrls.mjs +0 -229
- package/lib/modules/normalizeAttributeValues.cjs +0 -120
- package/lib/modules/normalizeAttributeValues.mjs +0 -140
- package/lib/modules/removeAttributeQuotes.cjs +0 -17
- package/lib/modules/removeAttributeQuotes.mjs +0 -12
- package/lib/modules/removeComments.cjs +0 -86
- package/lib/modules/removeEmptyAttributes.cjs +0 -72
- package/lib/modules/removeEmptyAttributes.mjs +0 -121
- package/lib/modules/removeOptionalTags.cjs +0 -183
- package/lib/modules/removeRedundantAttributes.cjs +0 -112
- package/lib/modules/removeUnusedCss.cjs +0 -113
- package/lib/modules/removeUnusedCss.mjs +0 -122
- package/lib/modules/sortAttributes.cjs +0 -99
- package/lib/modules/sortAttributesWithLists.cjs +0 -115
- package/lib/presets/ampSafe.cjs +0 -18
- package/lib/presets/max.cjs +0 -27
- package/lib/presets/safe.cjs +0 -65
- package/test.js +0 -48
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types#JavaScript_types
|
|
2
|
-
|
|
2
|
+
const redundantScriptTypes = new Set([
|
|
3
3
|
'application/javascript',
|
|
4
4
|
'application/ecmascript',
|
|
5
5
|
'application/x-ecmascript',
|
|
@@ -17,57 +17,51 @@ export const redundantScriptTypes = new Set([
|
|
|
17
17
|
'text/x-ecmascript',
|
|
18
18
|
'text/x-javascript'
|
|
19
19
|
]);
|
|
20
|
-
|
|
21
20
|
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#missing-value-default
|
|
22
21
|
const missingValueDefaultAttributes = {
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
form: {
|
|
23
|
+
method: 'get'
|
|
25
24
|
},
|
|
26
|
-
|
|
27
25
|
input: {
|
|
28
26
|
type: 'text'
|
|
29
27
|
},
|
|
30
|
-
|
|
31
28
|
button: {
|
|
32
29
|
// https://html.spec.whatwg.org/multipage/form-elements.html#attr-button-type
|
|
33
30
|
type: 'submit'
|
|
34
31
|
},
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
for (const [attrName, attrValue] of Object.entries(attrs)) {
|
|
32
|
+
script: {
|
|
33
|
+
language: 'javascript',
|
|
34
|
+
type: (attrs)=>{
|
|
35
|
+
for (const [attrName, attrValue] of Object.entries(attrs)){
|
|
40
36
|
if (attrName.toLowerCase() !== 'type') {
|
|
41
37
|
continue;
|
|
42
38
|
}
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
if (typeof attrValue === 'string') {
|
|
40
|
+
return redundantScriptTypes.has(attrValue);
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
45
43
|
}
|
|
46
|
-
|
|
47
44
|
return false;
|
|
48
45
|
},
|
|
49
46
|
// Remove attribute if the function returns false
|
|
50
|
-
|
|
47
|
+
charset: (attrs)=>{
|
|
51
48
|
// The charset attribute only really makes sense on “external” SCRIPT elements:
|
|
52
49
|
// http://perfectionkills.com/optimizing-html/#8_script_charset
|
|
53
50
|
return !attrs.src;
|
|
54
51
|
}
|
|
55
52
|
},
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
'type': 'text/css'
|
|
53
|
+
style: {
|
|
54
|
+
media: 'all',
|
|
55
|
+
type: 'text/css'
|
|
60
56
|
},
|
|
61
|
-
|
|
62
|
-
'link': {
|
|
57
|
+
link: {
|
|
63
58
|
media: 'all',
|
|
64
|
-
|
|
59
|
+
type: (attrs)=>{
|
|
65
60
|
// https://html.spec.whatwg.org/multipage/links.html#link-type-stylesheet
|
|
66
61
|
let isRelStyleSheet = false;
|
|
67
62
|
let isTypeTextCSS = false;
|
|
68
|
-
|
|
69
63
|
if (attrs) {
|
|
70
|
-
for (const [attrName, attrValue] of Object.entries(attrs))
|
|
64
|
+
for (const [attrName, attrValue] of Object.entries(attrs)){
|
|
71
65
|
if (attrName.toLowerCase() === 'rel' && attrValue === 'stylesheet') {
|
|
72
66
|
isRelStyleSheet = true;
|
|
73
67
|
}
|
|
@@ -76,66 +70,56 @@ const missingValueDefaultAttributes = {
|
|
|
76
70
|
}
|
|
77
71
|
}
|
|
78
72
|
}
|
|
79
|
-
|
|
80
73
|
// Only "text/css" is redudant for link[rel=stylesheet]. Otherwise "type" shouldn't be removed
|
|
81
74
|
return isRelStyleSheet && isTypeTextCSS;
|
|
82
75
|
}
|
|
83
76
|
},
|
|
84
|
-
|
|
85
77
|
// See: https://html.spec.whatwg.org/#lazy-loading-attributes
|
|
86
78
|
img: {
|
|
87
|
-
|
|
79
|
+
loading: 'eager',
|
|
88
80
|
// https://html.spec.whatwg.org/multipage/embedded-content.html#dom-img-decoding
|
|
89
81
|
decoding: 'auto'
|
|
90
82
|
},
|
|
91
83
|
iframe: {
|
|
92
|
-
|
|
84
|
+
loading: 'eager'
|
|
93
85
|
},
|
|
94
|
-
|
|
95
86
|
// https://html.spec.whatwg.org/multipage/media.html#htmltrackelement
|
|
96
87
|
track: {
|
|
97
88
|
kind: 'subtitles'
|
|
98
89
|
},
|
|
99
|
-
|
|
100
90
|
textarea: {
|
|
101
91
|
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-textarea-wrap
|
|
102
92
|
wrap: 'soft'
|
|
103
93
|
},
|
|
104
|
-
|
|
105
94
|
area: {
|
|
106
95
|
// https://html.spec.whatwg.org/multipage/image-maps.html#attr-area-shape
|
|
107
96
|
shape: 'rect'
|
|
108
97
|
}
|
|
109
98
|
};
|
|
110
|
-
|
|
111
99
|
const tagsHaveMissingValueDefaultAttributes = new Set(Object.keys(missingValueDefaultAttributes));
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
isRemove = true;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
if (isRemove) {
|
|
134
|
-
delete newAttrs[redundantAttributeName];
|
|
100
|
+
/** Removes redundant attributes */ const mod = {
|
|
101
|
+
onAttrs () {
|
|
102
|
+
return (attrs, node)=>{
|
|
103
|
+
if (!node.tag) return attrs;
|
|
104
|
+
const newAttrs = attrs;
|
|
105
|
+
if (tagsHaveMissingValueDefaultAttributes.has(node.tag)) {
|
|
106
|
+
const tagRedundantAttributes = missingValueDefaultAttributes[node.tag];
|
|
107
|
+
for (const redundantAttributeName of Object.keys(tagRedundantAttributes)){
|
|
108
|
+
const tagRedundantAttributeValue = tagRedundantAttributes[redundantAttributeName];
|
|
109
|
+
let isRemove = false;
|
|
110
|
+
if (typeof tagRedundantAttributeValue === 'function') {
|
|
111
|
+
isRemove = tagRedundantAttributeValue(attrs);
|
|
112
|
+
} else if (attrs[redundantAttributeName] === tagRedundantAttributeValue) {
|
|
113
|
+
isRemove = true;
|
|
114
|
+
}
|
|
115
|
+
if (isRemove) {
|
|
116
|
+
delete newAttrs[redundantAttributeName];
|
|
117
|
+
}
|
|
135
118
|
}
|
|
136
119
|
}
|
|
137
|
-
|
|
120
|
+
return newAttrs;
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
};
|
|
138
124
|
|
|
139
|
-
|
|
140
|
-
};
|
|
141
|
-
}
|
|
125
|
+
export { mod as default, redundantScriptTypes };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import PostHTML from 'posthtml';
|
|
2
|
+
import { MinifyOptions } from 'terser';
|
|
3
|
+
import { Options } from 'cssnano';
|
|
4
|
+
import { Config } from 'svgo';
|
|
5
|
+
|
|
6
|
+
type PostHTMLTreeLike = [PostHTML.Node] & PostHTML.NodeAPI & {
|
|
7
|
+
options?: {
|
|
8
|
+
quoteAllAttributes?: boolean | undefined;
|
|
9
|
+
} | undefined;
|
|
10
|
+
render(): string;
|
|
11
|
+
render(node: PostHTML.Node | PostHTMLTreeLike, renderOptions?: any): string;
|
|
12
|
+
};
|
|
13
|
+
type MaybeArray<T> = T | Array<T>;
|
|
14
|
+
type PostHTMLNodeLike = PostHTML.Node | string;
|
|
15
|
+
interface HtmlnanoOptions {
|
|
16
|
+
skipConfigLoading?: boolean;
|
|
17
|
+
skipInternalWarnings?: boolean;
|
|
18
|
+
collapseAttributeWhitespace?: boolean;
|
|
19
|
+
collapseBooleanAttributes?: {
|
|
20
|
+
amphtml?: boolean;
|
|
21
|
+
};
|
|
22
|
+
collapseWhitespace?: 'conservative' | 'all' | 'aggressive';
|
|
23
|
+
custom?: MaybeArray<(tree: PostHTMLTreeLike, options?: any) => (PostHTML.Node | PostHTMLTreeLike)>;
|
|
24
|
+
deduplicateAttributeValues?: boolean;
|
|
25
|
+
minifyUrls?: URL | string | false;
|
|
26
|
+
mergeStyles?: boolean;
|
|
27
|
+
mergeScripts?: boolean;
|
|
28
|
+
minifyCss?: Options | boolean;
|
|
29
|
+
minifyConditionalComments?: boolean;
|
|
30
|
+
minifyJs?: MinifyOptions | boolean;
|
|
31
|
+
minifyJson?: boolean;
|
|
32
|
+
minifySvg?: Config | boolean;
|
|
33
|
+
normalizeAttributeValues?: boolean;
|
|
34
|
+
removeAttributeQuotes?: boolean;
|
|
35
|
+
removeComments?: boolean | 'safe' | 'all' | RegExp | ((comment: string) => boolean);
|
|
36
|
+
removeEmptyAttributes?: boolean;
|
|
37
|
+
removeRedundantAttributes?: boolean;
|
|
38
|
+
removeOptionalTags?: boolean;
|
|
39
|
+
removeUnusedCss?: boolean;
|
|
40
|
+
sortAttributes?: boolean | 'alphabetical' | 'frequency';
|
|
41
|
+
sortAttributesWithLists?: boolean | 'alphabetical' | 'frequency';
|
|
42
|
+
}
|
|
43
|
+
type HtmlnanoModuleAttrsHandler = (attrs: Record<string, string | boolean | void>, node: PostHTML.Node) => Record<string, string | boolean | void>;
|
|
44
|
+
type HtmlnanoModuleContentHandler = (content: Array<PostHTMLNodeLike>, node: PostHTML.Node) => MaybeArray<PostHTMLNodeLike>;
|
|
45
|
+
type HtmlnanoModuleNodeHandler = (node: PostHTMLNodeLike) => PostHTML.Node | string;
|
|
46
|
+
type OptionalOptions<T> = T extends boolean | string | Function | number | null | undefined ? T : T extends object ? Partial<T> : T;
|
|
47
|
+
type HtmlnanoModule<Options = any> = {
|
|
48
|
+
onAttrs?: (options: Partial<HtmlnanoOptions>, moduleOptions: OptionalOptions<Options>) => HtmlnanoModuleAttrsHandler;
|
|
49
|
+
onContent?: (options: Partial<HtmlnanoOptions>, moduleOptions: OptionalOptions<Options>) => HtmlnanoModuleContentHandler;
|
|
50
|
+
onNode?: (options: Partial<HtmlnanoOptions>, moduleOptions: OptionalOptions<Options>) => HtmlnanoModuleNodeHandler;
|
|
51
|
+
default?: (tree: PostHTMLTreeLike, options: Partial<HtmlnanoOptions>, moduleOptions: OptionalOptions<Options>) => PostHTMLTreeLike | Promise<PostHTMLTreeLike>;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
interface RemoveUnusedCssOptions {
|
|
55
|
+
tool?: 'purgeCSS' | 'uncss';
|
|
56
|
+
}
|
|
57
|
+
declare const mod: HtmlnanoModule<RemoveUnusedCssOptions>;
|
|
58
|
+
|
|
59
|
+
export { mod as default };
|
|
60
|
+
export type { RemoveUnusedCssOptions };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import PostHTML from 'posthtml';
|
|
2
|
+
import { MinifyOptions } from 'terser';
|
|
3
|
+
import { Options } from 'cssnano';
|
|
4
|
+
import { Config } from 'svgo';
|
|
5
|
+
|
|
6
|
+
type PostHTMLTreeLike = [PostHTML.Node] & PostHTML.NodeAPI & {
|
|
7
|
+
options?: {
|
|
8
|
+
quoteAllAttributes?: boolean | undefined;
|
|
9
|
+
} | undefined;
|
|
10
|
+
render(): string;
|
|
11
|
+
render(node: PostHTML.Node | PostHTMLTreeLike, renderOptions?: any): string;
|
|
12
|
+
};
|
|
13
|
+
type MaybeArray<T> = T | Array<T>;
|
|
14
|
+
type PostHTMLNodeLike = PostHTML.Node | string;
|
|
15
|
+
interface HtmlnanoOptions {
|
|
16
|
+
skipConfigLoading?: boolean;
|
|
17
|
+
skipInternalWarnings?: boolean;
|
|
18
|
+
collapseAttributeWhitespace?: boolean;
|
|
19
|
+
collapseBooleanAttributes?: {
|
|
20
|
+
amphtml?: boolean;
|
|
21
|
+
};
|
|
22
|
+
collapseWhitespace?: 'conservative' | 'all' | 'aggressive';
|
|
23
|
+
custom?: MaybeArray<(tree: PostHTMLTreeLike, options?: any) => (PostHTML.Node | PostHTMLTreeLike)>;
|
|
24
|
+
deduplicateAttributeValues?: boolean;
|
|
25
|
+
minifyUrls?: URL | string | false;
|
|
26
|
+
mergeStyles?: boolean;
|
|
27
|
+
mergeScripts?: boolean;
|
|
28
|
+
minifyCss?: Options | boolean;
|
|
29
|
+
minifyConditionalComments?: boolean;
|
|
30
|
+
minifyJs?: MinifyOptions | boolean;
|
|
31
|
+
minifyJson?: boolean;
|
|
32
|
+
minifySvg?: Config | boolean;
|
|
33
|
+
normalizeAttributeValues?: boolean;
|
|
34
|
+
removeAttributeQuotes?: boolean;
|
|
35
|
+
removeComments?: boolean | 'safe' | 'all' | RegExp | ((comment: string) => boolean);
|
|
36
|
+
removeEmptyAttributes?: boolean;
|
|
37
|
+
removeRedundantAttributes?: boolean;
|
|
38
|
+
removeOptionalTags?: boolean;
|
|
39
|
+
removeUnusedCss?: boolean;
|
|
40
|
+
sortAttributes?: boolean | 'alphabetical' | 'frequency';
|
|
41
|
+
sortAttributesWithLists?: boolean | 'alphabetical' | 'frequency';
|
|
42
|
+
}
|
|
43
|
+
type HtmlnanoModuleAttrsHandler = (attrs: Record<string, string | boolean | void>, node: PostHTML.Node) => Record<string, string | boolean | void>;
|
|
44
|
+
type HtmlnanoModuleContentHandler = (content: Array<PostHTMLNodeLike>, node: PostHTML.Node) => MaybeArray<PostHTMLNodeLike>;
|
|
45
|
+
type HtmlnanoModuleNodeHandler = (node: PostHTMLNodeLike) => PostHTML.Node | string;
|
|
46
|
+
type OptionalOptions<T> = T extends boolean | string | Function | number | null | undefined ? T : T extends object ? Partial<T> : T;
|
|
47
|
+
type HtmlnanoModule<Options = any> = {
|
|
48
|
+
onAttrs?: (options: Partial<HtmlnanoOptions>, moduleOptions: OptionalOptions<Options>) => HtmlnanoModuleAttrsHandler;
|
|
49
|
+
onContent?: (options: Partial<HtmlnanoOptions>, moduleOptions: OptionalOptions<Options>) => HtmlnanoModuleContentHandler;
|
|
50
|
+
onNode?: (options: Partial<HtmlnanoOptions>, moduleOptions: OptionalOptions<Options>) => HtmlnanoModuleNodeHandler;
|
|
51
|
+
default?: (tree: PostHTMLTreeLike, options: Partial<HtmlnanoOptions>, moduleOptions: OptionalOptions<Options>) => PostHTMLTreeLike | Promise<PostHTMLTreeLike>;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
interface RemoveUnusedCssOptions {
|
|
55
|
+
tool?: 'purgeCSS' | 'uncss';
|
|
56
|
+
}
|
|
57
|
+
declare const mod: HtmlnanoModule<RemoveUnusedCssOptions>;
|
|
58
|
+
|
|
59
|
+
export { mod as default };
|
|
60
|
+
export type { RemoveUnusedCssOptions };
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
2
|
+
|
|
3
|
+
var helpers_js = require('../helpers.js');
|
|
4
|
+
|
|
5
|
+
// These options must be set and shouldn't be overriden to ensure uncss doesn't look at linked stylesheets.
|
|
6
|
+
const uncssOptions = {
|
|
7
|
+
ignoreSheets: [
|
|
8
|
+
/\s*/
|
|
9
|
+
],
|
|
10
|
+
stylesheets: []
|
|
11
|
+
};
|
|
12
|
+
function processStyleNodeUnCSS(html, styleNode, uncssOptions, uncss) {
|
|
13
|
+
const css = helpers_js.extractCssFromStyleNode(styleNode);
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- uncss no types
|
|
15
|
+
return runUncss(html, css, uncssOptions, uncss).then((css)=>{
|
|
16
|
+
// uncss may have left some style tags empty
|
|
17
|
+
if (css.trim().length === 0) {
|
|
18
|
+
// @ts-expect-error -- explicitly remove the tag
|
|
19
|
+
styleNode.tag = false;
|
|
20
|
+
styleNode.content = [];
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
styleNode.content = [
|
|
24
|
+
css
|
|
25
|
+
];
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function runUncss(html, css, userOptions, uncss) {
|
|
29
|
+
if (typeof userOptions !== 'object') {
|
|
30
|
+
userOptions = {};
|
|
31
|
+
}
|
|
32
|
+
const options = {
|
|
33
|
+
...userOptions,
|
|
34
|
+
...uncssOptions
|
|
35
|
+
};
|
|
36
|
+
return new Promise((resolve, reject)=>{
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access -- we dont have uncss types
|
|
38
|
+
options.raw = css;
|
|
39
|
+
uncss(html, options, (error, output)=>{
|
|
40
|
+
if (error) {
|
|
41
|
+
reject(error);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
resolve(output);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
const purgeFromHtml = function(tree) {
|
|
49
|
+
// content is not used as we can directly used the parsed HTML,
|
|
50
|
+
// making the process faster
|
|
51
|
+
const selectors = [];
|
|
52
|
+
tree.walk((node)=>{
|
|
53
|
+
const classes = node.attrs && node.attrs.class && node.attrs.class.split(' ') || [];
|
|
54
|
+
const ids = node.attrs && node.attrs.id && node.attrs.id.split(' ') || [];
|
|
55
|
+
selectors.push(...classes, ...ids);
|
|
56
|
+
if (node.tag) {
|
|
57
|
+
selectors.push(node.tag);
|
|
58
|
+
}
|
|
59
|
+
return node;
|
|
60
|
+
});
|
|
61
|
+
return ()=>selectors;
|
|
62
|
+
};
|
|
63
|
+
function processStyleNodePurgeCSS(tree, styleNode, purgecssOptions, purgecss) {
|
|
64
|
+
const css = helpers_js.extractCssFromStyleNode(styleNode);
|
|
65
|
+
return runPurgecss(tree, css, purgecssOptions, purgecss).then((css)=>{
|
|
66
|
+
if (css.trim().length === 0) {
|
|
67
|
+
// @ts-expect-error -- explicitly remove the tag
|
|
68
|
+
styleNode.tag = false;
|
|
69
|
+
styleNode.content = [];
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
styleNode.content = [
|
|
73
|
+
css
|
|
74
|
+
];
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
function runPurgecss(tree, css, userOptions, purgecss) {
|
|
78
|
+
if (typeof userOptions !== 'object') {
|
|
79
|
+
userOptions = {};
|
|
80
|
+
}
|
|
81
|
+
const options = {
|
|
82
|
+
...userOptions,
|
|
83
|
+
content: [
|
|
84
|
+
{
|
|
85
|
+
raw: tree.render(),
|
|
86
|
+
extension: 'html'
|
|
87
|
+
}
|
|
88
|
+
],
|
|
89
|
+
css: [
|
|
90
|
+
{
|
|
91
|
+
raw: css,
|
|
92
|
+
// @ts-expect-error -- old purgecss options
|
|
93
|
+
extension: 'css'
|
|
94
|
+
}
|
|
95
|
+
],
|
|
96
|
+
extractors: [
|
|
97
|
+
{
|
|
98
|
+
extractor: purgeFromHtml(tree),
|
|
99
|
+
extensions: [
|
|
100
|
+
'html'
|
|
101
|
+
]
|
|
102
|
+
}
|
|
103
|
+
]
|
|
104
|
+
};
|
|
105
|
+
return new purgecss.PurgeCSS().purge(options).then((result)=>{
|
|
106
|
+
return result[0].css;
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
/** Remove unused CSS */ const mod = {
|
|
110
|
+
async default (tree, options, userOptions) {
|
|
111
|
+
const promises = [];
|
|
112
|
+
let html;
|
|
113
|
+
const purgecss = await helpers_js.optionalImport('purgecss');
|
|
114
|
+
const uncss = await helpers_js.optionalImport('uncss');
|
|
115
|
+
tree.walk((node)=>{
|
|
116
|
+
if (helpers_js.isStyleNode(node)) {
|
|
117
|
+
if (userOptions.tool === 'purgeCSS') {
|
|
118
|
+
if (purgecss) {
|
|
119
|
+
promises.push(processStyleNodePurgeCSS(tree, node, userOptions, purgecss));
|
|
120
|
+
}
|
|
121
|
+
} else {
|
|
122
|
+
if (uncss) {
|
|
123
|
+
html != null ? html : html = tree.render(tree);
|
|
124
|
+
promises.push(processStyleNodeUnCSS(html, node, userOptions, uncss));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return node;
|
|
129
|
+
});
|
|
130
|
+
return Promise.all(promises).then(()=>tree);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
exports.default = mod;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { optionalImport, isStyleNode, extractCssFromStyleNode } from '../helpers.mjs';
|
|
2
|
+
|
|
3
|
+
// These options must be set and shouldn't be overriden to ensure uncss doesn't look at linked stylesheets.
|
|
4
|
+
const uncssOptions = {
|
|
5
|
+
ignoreSheets: [
|
|
6
|
+
/\s*/
|
|
7
|
+
],
|
|
8
|
+
stylesheets: []
|
|
9
|
+
};
|
|
10
|
+
function processStyleNodeUnCSS(html, styleNode, uncssOptions, uncss) {
|
|
11
|
+
const css = extractCssFromStyleNode(styleNode);
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- uncss no types
|
|
13
|
+
return runUncss(html, css, uncssOptions, uncss).then((css)=>{
|
|
14
|
+
// uncss may have left some style tags empty
|
|
15
|
+
if (css.trim().length === 0) {
|
|
16
|
+
// @ts-expect-error -- explicitly remove the tag
|
|
17
|
+
styleNode.tag = false;
|
|
18
|
+
styleNode.content = [];
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
styleNode.content = [
|
|
22
|
+
css
|
|
23
|
+
];
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
function runUncss(html, css, userOptions, uncss) {
|
|
27
|
+
if (typeof userOptions !== 'object') {
|
|
28
|
+
userOptions = {};
|
|
29
|
+
}
|
|
30
|
+
const options = {
|
|
31
|
+
...userOptions,
|
|
32
|
+
...uncssOptions
|
|
33
|
+
};
|
|
34
|
+
return new Promise((resolve, reject)=>{
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access -- we dont have uncss types
|
|
36
|
+
options.raw = css;
|
|
37
|
+
uncss(html, options, (error, output)=>{
|
|
38
|
+
if (error) {
|
|
39
|
+
reject(error);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
resolve(output);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
const purgeFromHtml = function(tree) {
|
|
47
|
+
// content is not used as we can directly used the parsed HTML,
|
|
48
|
+
// making the process faster
|
|
49
|
+
const selectors = [];
|
|
50
|
+
tree.walk((node)=>{
|
|
51
|
+
const classes = node.attrs && node.attrs.class && node.attrs.class.split(' ') || [];
|
|
52
|
+
const ids = node.attrs && node.attrs.id && node.attrs.id.split(' ') || [];
|
|
53
|
+
selectors.push(...classes, ...ids);
|
|
54
|
+
if (node.tag) {
|
|
55
|
+
selectors.push(node.tag);
|
|
56
|
+
}
|
|
57
|
+
return node;
|
|
58
|
+
});
|
|
59
|
+
return ()=>selectors;
|
|
60
|
+
};
|
|
61
|
+
function processStyleNodePurgeCSS(tree, styleNode, purgecssOptions, purgecss) {
|
|
62
|
+
const css = extractCssFromStyleNode(styleNode);
|
|
63
|
+
return runPurgecss(tree, css, purgecssOptions, purgecss).then((css)=>{
|
|
64
|
+
if (css.trim().length === 0) {
|
|
65
|
+
// @ts-expect-error -- explicitly remove the tag
|
|
66
|
+
styleNode.tag = false;
|
|
67
|
+
styleNode.content = [];
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
styleNode.content = [
|
|
71
|
+
css
|
|
72
|
+
];
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
function runPurgecss(tree, css, userOptions, purgecss) {
|
|
76
|
+
if (typeof userOptions !== 'object') {
|
|
77
|
+
userOptions = {};
|
|
78
|
+
}
|
|
79
|
+
const options = {
|
|
80
|
+
...userOptions,
|
|
81
|
+
content: [
|
|
82
|
+
{
|
|
83
|
+
raw: tree.render(),
|
|
84
|
+
extension: 'html'
|
|
85
|
+
}
|
|
86
|
+
],
|
|
87
|
+
css: [
|
|
88
|
+
{
|
|
89
|
+
raw: css,
|
|
90
|
+
// @ts-expect-error -- old purgecss options
|
|
91
|
+
extension: 'css'
|
|
92
|
+
}
|
|
93
|
+
],
|
|
94
|
+
extractors: [
|
|
95
|
+
{
|
|
96
|
+
extractor: purgeFromHtml(tree),
|
|
97
|
+
extensions: [
|
|
98
|
+
'html'
|
|
99
|
+
]
|
|
100
|
+
}
|
|
101
|
+
]
|
|
102
|
+
};
|
|
103
|
+
return new purgecss.PurgeCSS().purge(options).then((result)=>{
|
|
104
|
+
return result[0].css;
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
/** Remove unused CSS */ const mod = {
|
|
108
|
+
async default (tree, options, userOptions) {
|
|
109
|
+
const promises = [];
|
|
110
|
+
let html;
|
|
111
|
+
const purgecss = await optionalImport('purgecss');
|
|
112
|
+
const uncss = await optionalImport('uncss');
|
|
113
|
+
tree.walk((node)=>{
|
|
114
|
+
if (isStyleNode(node)) {
|
|
115
|
+
if (userOptions.tool === 'purgeCSS') {
|
|
116
|
+
if (purgecss) {
|
|
117
|
+
promises.push(processStyleNodePurgeCSS(tree, node, userOptions, purgecss));
|
|
118
|
+
}
|
|
119
|
+
} else {
|
|
120
|
+
if (uncss) {
|
|
121
|
+
html != null ? html : html = tree.render(tree);
|
|
122
|
+
promises.push(processStyleNodeUnCSS(html, node, userOptions, uncss));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return node;
|
|
127
|
+
});
|
|
128
|
+
return Promise.all(promises).then(()=>tree);
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
export { mod as default };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import PostHTML from 'posthtml';
|
|
2
|
+
import { MinifyOptions } from 'terser';
|
|
3
|
+
import { Options } from 'cssnano';
|
|
4
|
+
import { Config } from 'svgo';
|
|
5
|
+
|
|
6
|
+
type PostHTMLTreeLike = [PostHTML.Node] & PostHTML.NodeAPI & {
|
|
7
|
+
options?: {
|
|
8
|
+
quoteAllAttributes?: boolean | undefined;
|
|
9
|
+
} | undefined;
|
|
10
|
+
render(): string;
|
|
11
|
+
render(node: PostHTML.Node | PostHTMLTreeLike, renderOptions?: any): string;
|
|
12
|
+
};
|
|
13
|
+
type MaybeArray<T> = T | Array<T>;
|
|
14
|
+
type PostHTMLNodeLike = PostHTML.Node | string;
|
|
15
|
+
interface HtmlnanoOptions {
|
|
16
|
+
skipConfigLoading?: boolean;
|
|
17
|
+
skipInternalWarnings?: boolean;
|
|
18
|
+
collapseAttributeWhitespace?: boolean;
|
|
19
|
+
collapseBooleanAttributes?: {
|
|
20
|
+
amphtml?: boolean;
|
|
21
|
+
};
|
|
22
|
+
collapseWhitespace?: 'conservative' | 'all' | 'aggressive';
|
|
23
|
+
custom?: MaybeArray<(tree: PostHTMLTreeLike, options?: any) => (PostHTML.Node | PostHTMLTreeLike)>;
|
|
24
|
+
deduplicateAttributeValues?: boolean;
|
|
25
|
+
minifyUrls?: URL | string | false;
|
|
26
|
+
mergeStyles?: boolean;
|
|
27
|
+
mergeScripts?: boolean;
|
|
28
|
+
minifyCss?: Options | boolean;
|
|
29
|
+
minifyConditionalComments?: boolean;
|
|
30
|
+
minifyJs?: MinifyOptions | boolean;
|
|
31
|
+
minifyJson?: boolean;
|
|
32
|
+
minifySvg?: Config | boolean;
|
|
33
|
+
normalizeAttributeValues?: boolean;
|
|
34
|
+
removeAttributeQuotes?: boolean;
|
|
35
|
+
removeComments?: boolean | 'safe' | 'all' | RegExp | ((comment: string) => boolean);
|
|
36
|
+
removeEmptyAttributes?: boolean;
|
|
37
|
+
removeRedundantAttributes?: boolean;
|
|
38
|
+
removeOptionalTags?: boolean;
|
|
39
|
+
removeUnusedCss?: boolean;
|
|
40
|
+
sortAttributes?: boolean | 'alphabetical' | 'frequency';
|
|
41
|
+
sortAttributesWithLists?: boolean | 'alphabetical' | 'frequency';
|
|
42
|
+
}
|
|
43
|
+
type HtmlnanoModuleAttrsHandler = (attrs: Record<string, string | boolean | void>, node: PostHTML.Node) => Record<string, string | boolean | void>;
|
|
44
|
+
type HtmlnanoModuleContentHandler = (content: Array<PostHTMLNodeLike>, node: PostHTML.Node) => MaybeArray<PostHTMLNodeLike>;
|
|
45
|
+
type HtmlnanoModuleNodeHandler = (node: PostHTMLNodeLike) => PostHTML.Node | string;
|
|
46
|
+
type OptionalOptions<T> = T extends boolean | string | Function | number | null | undefined ? T : T extends object ? Partial<T> : T;
|
|
47
|
+
type HtmlnanoModule<Options = any> = {
|
|
48
|
+
onAttrs?: (options: Partial<HtmlnanoOptions>, moduleOptions: OptionalOptions<Options>) => HtmlnanoModuleAttrsHandler;
|
|
49
|
+
onContent?: (options: Partial<HtmlnanoOptions>, moduleOptions: OptionalOptions<Options>) => HtmlnanoModuleContentHandler;
|
|
50
|
+
onNode?: (options: Partial<HtmlnanoOptions>, moduleOptions: OptionalOptions<Options>) => HtmlnanoModuleNodeHandler;
|
|
51
|
+
default?: (tree: PostHTMLTreeLike, options: Partial<HtmlnanoOptions>, moduleOptions: OptionalOptions<Options>) => PostHTMLTreeLike | Promise<PostHTMLTreeLike>;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
type ValidOptions = 'alphabetical' | 'frequency';
|
|
55
|
+
declare const mod: HtmlnanoModule<boolean | ValidOptions>;
|
|
56
|
+
|
|
57
|
+
export { mod as default };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import PostHTML from 'posthtml';
|
|
2
|
+
import { MinifyOptions } from 'terser';
|
|
3
|
+
import { Options } from 'cssnano';
|
|
4
|
+
import { Config } from 'svgo';
|
|
5
|
+
|
|
6
|
+
type PostHTMLTreeLike = [PostHTML.Node] & PostHTML.NodeAPI & {
|
|
7
|
+
options?: {
|
|
8
|
+
quoteAllAttributes?: boolean | undefined;
|
|
9
|
+
} | undefined;
|
|
10
|
+
render(): string;
|
|
11
|
+
render(node: PostHTML.Node | PostHTMLTreeLike, renderOptions?: any): string;
|
|
12
|
+
};
|
|
13
|
+
type MaybeArray<T> = T | Array<T>;
|
|
14
|
+
type PostHTMLNodeLike = PostHTML.Node | string;
|
|
15
|
+
interface HtmlnanoOptions {
|
|
16
|
+
skipConfigLoading?: boolean;
|
|
17
|
+
skipInternalWarnings?: boolean;
|
|
18
|
+
collapseAttributeWhitespace?: boolean;
|
|
19
|
+
collapseBooleanAttributes?: {
|
|
20
|
+
amphtml?: boolean;
|
|
21
|
+
};
|
|
22
|
+
collapseWhitespace?: 'conservative' | 'all' | 'aggressive';
|
|
23
|
+
custom?: MaybeArray<(tree: PostHTMLTreeLike, options?: any) => (PostHTML.Node | PostHTMLTreeLike)>;
|
|
24
|
+
deduplicateAttributeValues?: boolean;
|
|
25
|
+
minifyUrls?: URL | string | false;
|
|
26
|
+
mergeStyles?: boolean;
|
|
27
|
+
mergeScripts?: boolean;
|
|
28
|
+
minifyCss?: Options | boolean;
|
|
29
|
+
minifyConditionalComments?: boolean;
|
|
30
|
+
minifyJs?: MinifyOptions | boolean;
|
|
31
|
+
minifyJson?: boolean;
|
|
32
|
+
minifySvg?: Config | boolean;
|
|
33
|
+
normalizeAttributeValues?: boolean;
|
|
34
|
+
removeAttributeQuotes?: boolean;
|
|
35
|
+
removeComments?: boolean | 'safe' | 'all' | RegExp | ((comment: string) => boolean);
|
|
36
|
+
removeEmptyAttributes?: boolean;
|
|
37
|
+
removeRedundantAttributes?: boolean;
|
|
38
|
+
removeOptionalTags?: boolean;
|
|
39
|
+
removeUnusedCss?: boolean;
|
|
40
|
+
sortAttributes?: boolean | 'alphabetical' | 'frequency';
|
|
41
|
+
sortAttributesWithLists?: boolean | 'alphabetical' | 'frequency';
|
|
42
|
+
}
|
|
43
|
+
type HtmlnanoModuleAttrsHandler = (attrs: Record<string, string | boolean | void>, node: PostHTML.Node) => Record<string, string | boolean | void>;
|
|
44
|
+
type HtmlnanoModuleContentHandler = (content: Array<PostHTMLNodeLike>, node: PostHTML.Node) => MaybeArray<PostHTMLNodeLike>;
|
|
45
|
+
type HtmlnanoModuleNodeHandler = (node: PostHTMLNodeLike) => PostHTML.Node | string;
|
|
46
|
+
type OptionalOptions<T> = T extends boolean | string | Function | number | null | undefined ? T : T extends object ? Partial<T> : T;
|
|
47
|
+
type HtmlnanoModule<Options = any> = {
|
|
48
|
+
onAttrs?: (options: Partial<HtmlnanoOptions>, moduleOptions: OptionalOptions<Options>) => HtmlnanoModuleAttrsHandler;
|
|
49
|
+
onContent?: (options: Partial<HtmlnanoOptions>, moduleOptions: OptionalOptions<Options>) => HtmlnanoModuleContentHandler;
|
|
50
|
+
onNode?: (options: Partial<HtmlnanoOptions>, moduleOptions: OptionalOptions<Options>) => HtmlnanoModuleNodeHandler;
|
|
51
|
+
default?: (tree: PostHTMLTreeLike, options: Partial<HtmlnanoOptions>, moduleOptions: OptionalOptions<Options>) => PostHTMLTreeLike | Promise<PostHTMLTreeLike>;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
type ValidOptions = 'alphabetical' | 'frequency';
|
|
55
|
+
declare const mod: HtmlnanoModule<boolean | ValidOptions>;
|
|
56
|
+
|
|
57
|
+
export { mod as default };
|