htmlnano 3.1.0 → 3.2.1
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 +37 -23
- package/dist/_modules/collapseAttributeWhitespace.d.mts +58 -14
- package/dist/_modules/collapseAttributeWhitespace.d.ts +58 -14
- package/dist/_modules/collapseBooleanAttributes.d.mts +58 -14
- package/dist/_modules/collapseBooleanAttributes.d.ts +58 -14
- package/dist/_modules/collapseWhitespace.d.mts +58 -14
- package/dist/_modules/collapseWhitespace.d.ts +58 -14
- package/dist/_modules/custom.d.mts +58 -14
- package/dist/_modules/custom.d.ts +58 -14
- package/dist/_modules/deduplicateAttributeValues.d.mts +58 -14
- package/dist/_modules/deduplicateAttributeValues.d.ts +58 -14
- package/dist/_modules/example.d.mts +58 -14
- package/dist/_modules/example.d.ts +58 -14
- package/dist/_modules/mergeScripts.d.mts +58 -14
- package/dist/_modules/mergeScripts.d.ts +58 -14
- package/dist/_modules/mergeScripts.js +30 -23
- package/dist/_modules/mergeScripts.mjs +30 -23
- package/dist/_modules/mergeStyles.d.mts +58 -14
- package/dist/_modules/mergeStyles.d.ts +58 -14
- package/dist/_modules/mergeStyles.js +26 -21
- package/dist/_modules/mergeStyles.mjs +26 -21
- package/dist/_modules/minifyAttributes.d.mts +58 -14
- package/dist/_modules/minifyAttributes.d.ts +58 -14
- package/dist/_modules/minifyAttributes.js +2 -2
- package/dist/_modules/minifyAttributes.mjs +2 -2
- package/dist/_modules/minifyConditionalComments.d.mts +58 -14
- package/dist/_modules/minifyConditionalComments.d.ts +58 -14
- package/dist/_modules/minifyCss.d.mts +61 -14
- package/dist/_modules/minifyCss.d.ts +61 -14
- package/dist/_modules/minifyCss.js +79 -12
- package/dist/_modules/minifyCss.mjs +79 -13
- package/dist/_modules/minifyHtmlTemplate.d.mts +58 -14
- package/dist/_modules/minifyHtmlTemplate.d.ts +58 -14
- package/dist/_modules/minifyJs.d.mts +58 -13
- package/dist/_modules/minifyJs.d.ts +58 -13
- package/dist/_modules/minifyJs.js +12 -0
- package/dist/_modules/minifyJs.mjs +12 -0
- package/dist/_modules/minifyJson.d.mts +58 -14
- package/dist/_modules/minifyJson.d.ts +58 -14
- package/dist/_modules/minifyJson.js +1 -1
- package/dist/_modules/minifyJson.mjs +1 -1
- package/dist/_modules/minifySvg.d.mts +58 -13
- package/dist/_modules/minifySvg.d.ts +58 -13
- package/dist/_modules/minifySvg.js +2 -2
- package/dist/_modules/minifySvg.mjs +2 -2
- package/dist/_modules/minifyUrls.d.mts +58 -14
- package/dist/_modules/minifyUrls.d.ts +58 -14
- package/dist/_modules/minifyUrls.js +2 -2
- package/dist/_modules/minifyUrls.mjs +2 -2
- package/dist/_modules/normalizeAttributeValues.d.mts +58 -14
- package/dist/_modules/normalizeAttributeValues.d.ts +58 -14
- package/dist/_modules/removeAttributeQuotes.d.mts +58 -14
- package/dist/_modules/removeAttributeQuotes.d.ts +58 -14
- package/dist/_modules/removeComments.d.mts +58 -14
- package/dist/_modules/removeComments.d.ts +58 -14
- package/dist/_modules/removeComments.js +1 -1
- package/dist/_modules/removeComments.mjs +1 -1
- package/dist/_modules/removeEmptyAttributes.d.mts +58 -14
- package/dist/_modules/removeEmptyAttributes.d.ts +58 -14
- package/dist/_modules/removeEmptyElements.d.mts +58 -14
- package/dist/_modules/removeEmptyElements.d.ts +58 -14
- package/dist/_modules/removeOptionalTags.d.mts +58 -14
- package/dist/_modules/removeOptionalTags.d.ts +58 -14
- package/dist/_modules/removeRedundantAttributes.d.mts +58 -14
- package/dist/_modules/removeRedundantAttributes.d.ts +58 -14
- package/dist/_modules/removeUnusedCss.d.mts +58 -14
- package/dist/_modules/removeUnusedCss.d.ts +58 -14
- package/dist/_modules/removeUnusedCss.js +3 -2
- package/dist/_modules/removeUnusedCss.mjs +3 -2
- package/dist/_modules/sortAttributes.d.mts +61 -16
- package/dist/_modules/sortAttributes.d.ts +61 -16
- package/dist/_modules/sortAttributes.js +5 -9
- package/dist/_modules/sortAttributes.mjs +5 -9
- package/dist/_modules/sortAttributesWithLists.d.mts +61 -15
- package/dist/_modules/sortAttributesWithLists.d.ts +61 -15
- package/dist/_modules/sortAttributesWithLists.js +43 -56
- package/dist/_modules/sortAttributesWithLists.mjs +43 -56
- package/dist/index.d.ts +59 -15
- package/dist/index.js +7 -6
- package/dist/index.mjs +7 -6
- package/dist/presets/ampSafe.d.ts +57 -12
- package/dist/presets/max.d.ts +57 -12
- package/dist/presets/max.js +9 -5
- package/dist/presets/max.mjs +9 -5
- package/dist/presets/safe.d.ts +57 -12
- package/dist/presets/safe.js +1 -1
- package/dist/presets/safe.mjs +1 -1
- package/package.json +20 -14
|
@@ -6,6 +6,14 @@ const postcssOptions = {
|
|
|
6
6
|
// > Set it to CSS file path or to `undefined` to prevent this warning.
|
|
7
7
|
from: undefined
|
|
8
8
|
};
|
|
9
|
+
const inlineCssExcludedPlugins = {
|
|
10
|
+
mergeRules: false,
|
|
11
|
+
minifySelectors: false,
|
|
12
|
+
minifyParams: false,
|
|
13
|
+
normalizeCharset: false,
|
|
14
|
+
uniqueSelectors: false,
|
|
15
|
+
normalizeUnicode: false
|
|
16
|
+
};
|
|
9
17
|
/** Minify CSS with cssnano */ const mod = {
|
|
10
18
|
async default (tree, _, cssnanoOptions) {
|
|
11
19
|
const cssnano = await optionalImport('cssnano');
|
|
@@ -13,6 +21,9 @@ const postcssOptions = {
|
|
|
13
21
|
if (!cssnano || !postcss) {
|
|
14
22
|
return tree;
|
|
15
23
|
}
|
|
24
|
+
const processor = createCssProcessor(postcss, cssnano, cssnanoOptions);
|
|
25
|
+
const inlineStyleProcessor = createCssProcessor(postcss, cssnano, getInlineCssnanoOptions(cssnanoOptions));
|
|
26
|
+
const minifiedCssCache = new Map();
|
|
16
27
|
const promises = [];
|
|
17
28
|
let p;
|
|
18
29
|
tree.walk((node)=>{
|
|
@@ -21,12 +32,12 @@ const postcssOptions = {
|
|
|
21
32
|
return node;
|
|
22
33
|
}
|
|
23
34
|
if (isStyleNode(node) && isCssStyleType(node)) {
|
|
24
|
-
p = processStyleNode(node,
|
|
35
|
+
p = processStyleNode(node, processor, minifiedCssCache);
|
|
25
36
|
if (p) {
|
|
26
37
|
promises.push(p);
|
|
27
38
|
}
|
|
28
39
|
} else if (node.attrs && node.attrs.style) {
|
|
29
|
-
p = processStyleAttr(node,
|
|
40
|
+
p = processStyleAttr(node, inlineStyleProcessor, minifiedCssCache);
|
|
30
41
|
if (p) {
|
|
31
42
|
promises.push(p);
|
|
32
43
|
}
|
|
@@ -36,22 +47,69 @@ const postcssOptions = {
|
|
|
36
47
|
return Promise.all(promises).then(()=>tree);
|
|
37
48
|
}
|
|
38
49
|
};
|
|
39
|
-
function
|
|
50
|
+
function createCssProcessor(postcss, cssnano, cssnanoOptions) {
|
|
51
|
+
return postcss([
|
|
52
|
+
cssnano(cssnanoOptions)
|
|
53
|
+
]);
|
|
54
|
+
}
|
|
55
|
+
function getInlineCssnanoOptions(cssnanoOptions) {
|
|
56
|
+
if (!cssnanoOptions || typeof cssnanoOptions !== 'object') {
|
|
57
|
+
return {
|
|
58
|
+
preset: [
|
|
59
|
+
'default',
|
|
60
|
+
inlineCssExcludedPlugins
|
|
61
|
+
]
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
if (Array.isArray(cssnanoOptions.plugins)) {
|
|
65
|
+
return cssnanoOptions;
|
|
66
|
+
}
|
|
67
|
+
if (!('preset' in cssnanoOptions) || cssnanoOptions.preset === undefined) {
|
|
68
|
+
return {
|
|
69
|
+
...cssnanoOptions,
|
|
70
|
+
preset: [
|
|
71
|
+
'default',
|
|
72
|
+
inlineCssExcludedPlugins
|
|
73
|
+
]
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
if (cssnanoOptions.preset === 'default') {
|
|
77
|
+
return {
|
|
78
|
+
...cssnanoOptions,
|
|
79
|
+
preset: [
|
|
80
|
+
'default',
|
|
81
|
+
inlineCssExcludedPlugins
|
|
82
|
+
]
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
if (Array.isArray(cssnanoOptions.preset) && cssnanoOptions.preset[0] === 'default') {
|
|
86
|
+
const presetOptions = cssnanoOptions.preset[1];
|
|
87
|
+
return {
|
|
88
|
+
...cssnanoOptions,
|
|
89
|
+
preset: [
|
|
90
|
+
'default',
|
|
91
|
+
{
|
|
92
|
+
...inlineCssExcludedPlugins,
|
|
93
|
+
...presetOptions && typeof presetOptions === 'object' ? presetOptions : {}
|
|
94
|
+
}
|
|
95
|
+
]
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
return cssnanoOptions;
|
|
99
|
+
}
|
|
100
|
+
function processStyleNode(styleNode, processor, minifiedCssCache) {
|
|
40
101
|
let css = extractCssFromStyleNode(styleNode);
|
|
41
102
|
if (!css || css.trim() === '') return;
|
|
42
103
|
// Improve performance by avoiding calling stripCssCdata again and again
|
|
43
104
|
const { strippedCss, isCdataWrapped } = stripCssCdata(css);
|
|
44
105
|
css = strippedCss;
|
|
45
|
-
return
|
|
46
|
-
cssnano(cssnanoOptions)
|
|
47
|
-
]).process(css, postcssOptions).then((result)=>{
|
|
48
|
-
const minifiedCss = isCdataWrapped ? result.toString() : result.css;
|
|
106
|
+
return processCss(processor, minifiedCssCache, `${isCdataWrapped ? 'style-cdata:' : 'style:'}${css}`, css, isCdataWrapped).then((minifiedCss)=>{
|
|
49
107
|
styleNode.content = [
|
|
50
108
|
wrapCssCdata(minifiedCss, isCdataWrapped)
|
|
51
109
|
];
|
|
52
110
|
});
|
|
53
111
|
}
|
|
54
|
-
function processStyleAttr(node,
|
|
112
|
+
function processStyleAttr(node, processor, minifiedCssCache) {
|
|
55
113
|
// CSS "color: red;" is invalid. Therefore it should be wrapped inside some selector:
|
|
56
114
|
// a{color: red;}
|
|
57
115
|
const wrapperStart = 'a{';
|
|
@@ -63,13 +121,21 @@ function processStyleAttr(node, cssnanoOptions, cssnano, postcss) {
|
|
|
63
121
|
return;
|
|
64
122
|
}
|
|
65
123
|
const wrappedStyle = wrapperStart + (node.attrs.style || '') + wrapperEnd;
|
|
66
|
-
return
|
|
67
|
-
cssnano(cssnanoOptions)
|
|
68
|
-
]).process(wrappedStyle, postcssOptions).then((result)=>{
|
|
69
|
-
const minifiedCss = result.css;
|
|
124
|
+
return processCss(processor, minifiedCssCache, `attr:${wrappedStyle}`, wrappedStyle).then((minifiedCss)=>{
|
|
70
125
|
// Remove wrapperStart at the start and wrapperEnd at the end of minifiedCss
|
|
71
126
|
node.attrs.style = minifiedCss.substring(wrapperStart.length, minifiedCss.length - wrapperEnd.length);
|
|
72
127
|
});
|
|
73
128
|
}
|
|
129
|
+
function processCss(processor, minifiedCssCache, cacheKey, css, useToString = false) {
|
|
130
|
+
let minifiedCss = minifiedCssCache.get(cacheKey);
|
|
131
|
+
if (!minifiedCss) {
|
|
132
|
+
minifiedCss = processor.process(css, postcssOptions).then((result)=>useToString ? result.toString() : result.css).catch((error)=>{
|
|
133
|
+
minifiedCssCache.delete(cacheKey);
|
|
134
|
+
throw error;
|
|
135
|
+
});
|
|
136
|
+
minifiedCssCache.set(cacheKey, minifiedCss);
|
|
137
|
+
}
|
|
138
|
+
return minifiedCss;
|
|
139
|
+
}
|
|
74
140
|
|
|
75
|
-
export { mod as default };
|
|
141
|
+
export { mod as default, getInlineCssnanoOptions };
|
|
@@ -1,25 +1,70 @@
|
|
|
1
1
|
import PostHTML from 'posthtml';
|
|
2
|
-
import { MinifyOptions } from 'terser';
|
|
3
|
-
import { Options } from 'cssnano';
|
|
4
|
-
import { Config } from 'svgo';
|
|
5
|
-
import { UserDefinedOptions } from 'purgecss';
|
|
6
2
|
|
|
7
|
-
type
|
|
3
|
+
type PostHTMLNodeLike = PostHTML.Node | string;
|
|
4
|
+
type PostHTMLTreeLike = [PostHTMLNodeLike] & PostHTML.NodeAPI & {
|
|
8
5
|
options?: {
|
|
9
6
|
quoteAllAttributes?: boolean | undefined;
|
|
10
7
|
quoteStyle?: 0 | 1 | 2 | undefined;
|
|
11
8
|
replaceQuote?: boolean | undefined;
|
|
12
9
|
} | undefined;
|
|
13
10
|
render(): string;
|
|
14
|
-
render(node:
|
|
11
|
+
render(node: PostHTMLNodeLike | PostHTMLTreeLike, renderOptions?: any): string;
|
|
15
12
|
};
|
|
16
13
|
type MaybeArray<T> = T | Array<T>;
|
|
17
|
-
type PostHTMLNodeLike = PostHTML.Node | string;
|
|
18
14
|
type HtmlnanoTemplateRule = {
|
|
19
15
|
tag: string;
|
|
20
16
|
attrs?: Record<string, string | boolean | void>;
|
|
21
17
|
};
|
|
22
18
|
type MinifyHtmlTemplateOptions = boolean | HtmlnanoTemplateRule[];
|
|
19
|
+
type HtmlnanoMinifyCssOptions = object;
|
|
20
|
+
type HtmlnanoMinifyJsOptions = object;
|
|
21
|
+
type HtmlnanoMinifySvgOptions = object;
|
|
22
|
+
type HtmlnanoPurgeCssPattern = string | RegExp;
|
|
23
|
+
type HtmlnanoPurgeCssExtractorResultDetailed = {
|
|
24
|
+
attributes: {
|
|
25
|
+
names: string[];
|
|
26
|
+
values: string[];
|
|
27
|
+
};
|
|
28
|
+
classes: string[];
|
|
29
|
+
ids: string[];
|
|
30
|
+
tags: string[];
|
|
31
|
+
undetermined: string[];
|
|
32
|
+
};
|
|
33
|
+
type HtmlnanoPurgeCssExtractorResult = HtmlnanoPurgeCssExtractorResultDetailed | string[];
|
|
34
|
+
type HtmlnanoPurgeCssDefaultExtractor = (content: string) => HtmlnanoPurgeCssExtractorResult;
|
|
35
|
+
type HtmlnanoPurgeCssSourceMapOptions = {
|
|
36
|
+
absolute?: boolean;
|
|
37
|
+
annotation?: boolean | string;
|
|
38
|
+
from?: string;
|
|
39
|
+
inline?: boolean;
|
|
40
|
+
prev?: boolean | object | string;
|
|
41
|
+
sourcesContent?: boolean;
|
|
42
|
+
to?: string;
|
|
43
|
+
};
|
|
44
|
+
type HtmlnanoPurgeCssSafelist = HtmlnanoPurgeCssPattern[] | {
|
|
45
|
+
standard?: HtmlnanoPurgeCssPattern[];
|
|
46
|
+
deep?: RegExp[];
|
|
47
|
+
greedy?: RegExp[];
|
|
48
|
+
variables?: HtmlnanoPurgeCssPattern[];
|
|
49
|
+
keyframes?: HtmlnanoPurgeCssPattern[];
|
|
50
|
+
};
|
|
51
|
+
interface HtmlnanoPurgeCssOptions {
|
|
52
|
+
tool: 'purgeCSS';
|
|
53
|
+
defaultExtractor?: HtmlnanoPurgeCssDefaultExtractor;
|
|
54
|
+
fontFace?: boolean;
|
|
55
|
+
keyframes?: boolean;
|
|
56
|
+
output?: string;
|
|
57
|
+
rejected?: boolean;
|
|
58
|
+
rejectedCss?: boolean;
|
|
59
|
+
sourceMap?: boolean | HtmlnanoPurgeCssSourceMapOptions;
|
|
60
|
+
stdin?: boolean;
|
|
61
|
+
stdout?: boolean;
|
|
62
|
+
variables?: boolean;
|
|
63
|
+
safelist?: HtmlnanoPurgeCssSafelist;
|
|
64
|
+
blocklist?: HtmlnanoPurgeCssPattern[];
|
|
65
|
+
skippedContentGlobs?: string[];
|
|
66
|
+
dynamicAttributes?: string[];
|
|
67
|
+
}
|
|
23
68
|
interface HtmlnanoOptions {
|
|
24
69
|
skipConfigLoading?: boolean;
|
|
25
70
|
configPath?: string;
|
|
@@ -34,16 +79,16 @@ interface HtmlnanoOptions {
|
|
|
34
79
|
minifyUrls?: URL | string | false;
|
|
35
80
|
mergeStyles?: boolean;
|
|
36
81
|
mergeScripts?: boolean;
|
|
37
|
-
minifyCss?:
|
|
82
|
+
minifyCss?: HtmlnanoMinifyCssOptions | boolean;
|
|
38
83
|
minifyHtmlTemplate?: MinifyHtmlTemplateOptions;
|
|
39
84
|
minifyConditionalComments?: boolean;
|
|
40
|
-
minifyJs?:
|
|
85
|
+
minifyJs?: HtmlnanoMinifyJsOptions | boolean;
|
|
41
86
|
minifyJson?: boolean;
|
|
42
87
|
minifyAttributes?: boolean | {
|
|
43
88
|
metaContent?: boolean;
|
|
44
89
|
redundantWhitespaces?: 'safe' | 'agressive' | false;
|
|
45
90
|
};
|
|
46
|
-
minifySvg?:
|
|
91
|
+
minifySvg?: HtmlnanoMinifySvgOptions | boolean;
|
|
47
92
|
normalizeAttributeValues?: boolean;
|
|
48
93
|
removeAttributeQuotes?: boolean | {
|
|
49
94
|
force?: boolean;
|
|
@@ -55,9 +100,8 @@ interface HtmlnanoOptions {
|
|
|
55
100
|
};
|
|
56
101
|
removeRedundantAttributes?: boolean;
|
|
57
102
|
removeOptionalTags?: boolean;
|
|
58
|
-
removeUnusedCss?: boolean |
|
|
59
|
-
tool
|
|
60
|
-
} & Omit<UserDefinedOptions, 'content' | 'css' | 'extractors'>) | {
|
|
103
|
+
removeUnusedCss?: boolean | HtmlnanoPurgeCssOptions | {
|
|
104
|
+
tool?: 'uncss';
|
|
61
105
|
banner?: boolean;
|
|
62
106
|
csspath?: string;
|
|
63
107
|
htmlroot?: string;
|
|
@@ -77,7 +121,7 @@ interface HtmlnanoOptions {
|
|
|
77
121
|
type HtmlnanoModuleAttrsHandler = (attrs: Record<string, string | boolean | void>, node: PostHTML.Node) => Record<string, string | boolean | void>;
|
|
78
122
|
type HtmlnanoModuleContentHandler = (content: Array<PostHTMLNodeLike>, node: PostHTML.Node) => MaybeArray<PostHTMLNodeLike>;
|
|
79
123
|
type HtmlnanoModuleNodeHandler = (node: PostHTMLNodeLike) => PostHTML.Node | string;
|
|
80
|
-
type OptionalOptions<T> = T extends boolean | string | Function | number | null | undefined ? T : T extends object ? Partial<T> : T;
|
|
124
|
+
type OptionalOptions<T> = T extends boolean | string | Function | number | null | undefined ? T : T extends Array<infer Item> ? Array<Item> : T extends object ? Partial<T> : T;
|
|
81
125
|
type HtmlnanoModule<Options = any> = {
|
|
82
126
|
onAttrs?: (options: Partial<HtmlnanoOptions>, moduleOptions: OptionalOptions<Options>) => HtmlnanoModuleAttrsHandler;
|
|
83
127
|
onContent?: (options: Partial<HtmlnanoOptions>, moduleOptions: OptionalOptions<Options>) => HtmlnanoModuleContentHandler;
|
|
@@ -1,25 +1,70 @@
|
|
|
1
1
|
import PostHTML from 'posthtml';
|
|
2
|
-
import { MinifyOptions } from 'terser';
|
|
3
|
-
import { Options } from 'cssnano';
|
|
4
|
-
import { Config } from 'svgo';
|
|
5
|
-
import { UserDefinedOptions } from 'purgecss';
|
|
6
2
|
|
|
7
|
-
type
|
|
3
|
+
type PostHTMLNodeLike = PostHTML.Node | string;
|
|
4
|
+
type PostHTMLTreeLike = [PostHTMLNodeLike] & PostHTML.NodeAPI & {
|
|
8
5
|
options?: {
|
|
9
6
|
quoteAllAttributes?: boolean | undefined;
|
|
10
7
|
quoteStyle?: 0 | 1 | 2 | undefined;
|
|
11
8
|
replaceQuote?: boolean | undefined;
|
|
12
9
|
} | undefined;
|
|
13
10
|
render(): string;
|
|
14
|
-
render(node:
|
|
11
|
+
render(node: PostHTMLNodeLike | PostHTMLTreeLike, renderOptions?: any): string;
|
|
15
12
|
};
|
|
16
13
|
type MaybeArray<T> = T | Array<T>;
|
|
17
|
-
type PostHTMLNodeLike = PostHTML.Node | string;
|
|
18
14
|
type HtmlnanoTemplateRule = {
|
|
19
15
|
tag: string;
|
|
20
16
|
attrs?: Record<string, string | boolean | void>;
|
|
21
17
|
};
|
|
22
18
|
type MinifyHtmlTemplateOptions = boolean | HtmlnanoTemplateRule[];
|
|
19
|
+
type HtmlnanoMinifyCssOptions = object;
|
|
20
|
+
type HtmlnanoMinifyJsOptions = object;
|
|
21
|
+
type HtmlnanoMinifySvgOptions = object;
|
|
22
|
+
type HtmlnanoPurgeCssPattern = string | RegExp;
|
|
23
|
+
type HtmlnanoPurgeCssExtractorResultDetailed = {
|
|
24
|
+
attributes: {
|
|
25
|
+
names: string[];
|
|
26
|
+
values: string[];
|
|
27
|
+
};
|
|
28
|
+
classes: string[];
|
|
29
|
+
ids: string[];
|
|
30
|
+
tags: string[];
|
|
31
|
+
undetermined: string[];
|
|
32
|
+
};
|
|
33
|
+
type HtmlnanoPurgeCssExtractorResult = HtmlnanoPurgeCssExtractorResultDetailed | string[];
|
|
34
|
+
type HtmlnanoPurgeCssDefaultExtractor = (content: string) => HtmlnanoPurgeCssExtractorResult;
|
|
35
|
+
type HtmlnanoPurgeCssSourceMapOptions = {
|
|
36
|
+
absolute?: boolean;
|
|
37
|
+
annotation?: boolean | string;
|
|
38
|
+
from?: string;
|
|
39
|
+
inline?: boolean;
|
|
40
|
+
prev?: boolean | object | string;
|
|
41
|
+
sourcesContent?: boolean;
|
|
42
|
+
to?: string;
|
|
43
|
+
};
|
|
44
|
+
type HtmlnanoPurgeCssSafelist = HtmlnanoPurgeCssPattern[] | {
|
|
45
|
+
standard?: HtmlnanoPurgeCssPattern[];
|
|
46
|
+
deep?: RegExp[];
|
|
47
|
+
greedy?: RegExp[];
|
|
48
|
+
variables?: HtmlnanoPurgeCssPattern[];
|
|
49
|
+
keyframes?: HtmlnanoPurgeCssPattern[];
|
|
50
|
+
};
|
|
51
|
+
interface HtmlnanoPurgeCssOptions {
|
|
52
|
+
tool: 'purgeCSS';
|
|
53
|
+
defaultExtractor?: HtmlnanoPurgeCssDefaultExtractor;
|
|
54
|
+
fontFace?: boolean;
|
|
55
|
+
keyframes?: boolean;
|
|
56
|
+
output?: string;
|
|
57
|
+
rejected?: boolean;
|
|
58
|
+
rejectedCss?: boolean;
|
|
59
|
+
sourceMap?: boolean | HtmlnanoPurgeCssSourceMapOptions;
|
|
60
|
+
stdin?: boolean;
|
|
61
|
+
stdout?: boolean;
|
|
62
|
+
variables?: boolean;
|
|
63
|
+
safelist?: HtmlnanoPurgeCssSafelist;
|
|
64
|
+
blocklist?: HtmlnanoPurgeCssPattern[];
|
|
65
|
+
skippedContentGlobs?: string[];
|
|
66
|
+
dynamicAttributes?: string[];
|
|
67
|
+
}
|
|
23
68
|
interface HtmlnanoOptions {
|
|
24
69
|
skipConfigLoading?: boolean;
|
|
25
70
|
configPath?: string;
|
|
@@ -34,16 +79,16 @@ interface HtmlnanoOptions {
|
|
|
34
79
|
minifyUrls?: URL | string | false;
|
|
35
80
|
mergeStyles?: boolean;
|
|
36
81
|
mergeScripts?: boolean;
|
|
37
|
-
minifyCss?:
|
|
82
|
+
minifyCss?: HtmlnanoMinifyCssOptions | boolean;
|
|
38
83
|
minifyHtmlTemplate?: MinifyHtmlTemplateOptions;
|
|
39
84
|
minifyConditionalComments?: boolean;
|
|
40
|
-
minifyJs?:
|
|
85
|
+
minifyJs?: HtmlnanoMinifyJsOptions | boolean;
|
|
41
86
|
minifyJson?: boolean;
|
|
42
87
|
minifyAttributes?: boolean | {
|
|
43
88
|
metaContent?: boolean;
|
|
44
89
|
redundantWhitespaces?: 'safe' | 'agressive' | false;
|
|
45
90
|
};
|
|
46
|
-
minifySvg?:
|
|
91
|
+
minifySvg?: HtmlnanoMinifySvgOptions | boolean;
|
|
47
92
|
normalizeAttributeValues?: boolean;
|
|
48
93
|
removeAttributeQuotes?: boolean | {
|
|
49
94
|
force?: boolean;
|
|
@@ -55,9 +100,8 @@ interface HtmlnanoOptions {
|
|
|
55
100
|
};
|
|
56
101
|
removeRedundantAttributes?: boolean;
|
|
57
102
|
removeOptionalTags?: boolean;
|
|
58
|
-
removeUnusedCss?: boolean |
|
|
59
|
-
tool
|
|
60
|
-
} & Omit<UserDefinedOptions, 'content' | 'css' | 'extractors'>) | {
|
|
103
|
+
removeUnusedCss?: boolean | HtmlnanoPurgeCssOptions | {
|
|
104
|
+
tool?: 'uncss';
|
|
61
105
|
banner?: boolean;
|
|
62
106
|
csspath?: string;
|
|
63
107
|
htmlroot?: string;
|
|
@@ -77,7 +121,7 @@ interface HtmlnanoOptions {
|
|
|
77
121
|
type HtmlnanoModuleAttrsHandler = (attrs: Record<string, string | boolean | void>, node: PostHTML.Node) => Record<string, string | boolean | void>;
|
|
78
122
|
type HtmlnanoModuleContentHandler = (content: Array<PostHTMLNodeLike>, node: PostHTML.Node) => MaybeArray<PostHTMLNodeLike>;
|
|
79
123
|
type HtmlnanoModuleNodeHandler = (node: PostHTMLNodeLike) => PostHTML.Node | string;
|
|
80
|
-
type OptionalOptions<T> = T extends boolean | string | Function | number | null | undefined ? T : T extends object ? Partial<T> : T;
|
|
124
|
+
type OptionalOptions<T> = T extends boolean | string | Function | number | null | undefined ? T : T extends Array<infer Item> ? Array<Item> : T extends object ? Partial<T> : T;
|
|
81
125
|
type HtmlnanoModule<Options = any> = {
|
|
82
126
|
onAttrs?: (options: Partial<HtmlnanoOptions>, moduleOptions: OptionalOptions<Options>) => HtmlnanoModuleAttrsHandler;
|
|
83
127
|
onContent?: (options: Partial<HtmlnanoOptions>, moduleOptions: OptionalOptions<Options>) => HtmlnanoModuleContentHandler;
|
|
@@ -1,25 +1,71 @@
|
|
|
1
1
|
import PostHTML from 'posthtml';
|
|
2
2
|
import { MinifyOptions } from 'terser';
|
|
3
|
-
import { Options } from 'cssnano';
|
|
4
|
-
import { Config } from 'svgo';
|
|
5
|
-
import { UserDefinedOptions } from 'purgecss';
|
|
6
3
|
|
|
7
|
-
type
|
|
4
|
+
type PostHTMLNodeLike = PostHTML.Node | string;
|
|
5
|
+
type PostHTMLTreeLike = [PostHTMLNodeLike] & PostHTML.NodeAPI & {
|
|
8
6
|
options?: {
|
|
9
7
|
quoteAllAttributes?: boolean | undefined;
|
|
10
8
|
quoteStyle?: 0 | 1 | 2 | undefined;
|
|
11
9
|
replaceQuote?: boolean | undefined;
|
|
12
10
|
} | undefined;
|
|
13
11
|
render(): string;
|
|
14
|
-
render(node:
|
|
12
|
+
render(node: PostHTMLNodeLike | PostHTMLTreeLike, renderOptions?: any): string;
|
|
15
13
|
};
|
|
16
14
|
type MaybeArray<T> = T | Array<T>;
|
|
17
|
-
type PostHTMLNodeLike = PostHTML.Node | string;
|
|
18
15
|
type HtmlnanoTemplateRule = {
|
|
19
16
|
tag: string;
|
|
20
17
|
attrs?: Record<string, string | boolean | void>;
|
|
21
18
|
};
|
|
22
19
|
type MinifyHtmlTemplateOptions = boolean | HtmlnanoTemplateRule[];
|
|
20
|
+
type HtmlnanoMinifyCssOptions = object;
|
|
21
|
+
type HtmlnanoMinifyJsOptions = object;
|
|
22
|
+
type HtmlnanoMinifySvgOptions = object;
|
|
23
|
+
type HtmlnanoPurgeCssPattern = string | RegExp;
|
|
24
|
+
type HtmlnanoPurgeCssExtractorResultDetailed = {
|
|
25
|
+
attributes: {
|
|
26
|
+
names: string[];
|
|
27
|
+
values: string[];
|
|
28
|
+
};
|
|
29
|
+
classes: string[];
|
|
30
|
+
ids: string[];
|
|
31
|
+
tags: string[];
|
|
32
|
+
undetermined: string[];
|
|
33
|
+
};
|
|
34
|
+
type HtmlnanoPurgeCssExtractorResult = HtmlnanoPurgeCssExtractorResultDetailed | string[];
|
|
35
|
+
type HtmlnanoPurgeCssDefaultExtractor = (content: string) => HtmlnanoPurgeCssExtractorResult;
|
|
36
|
+
type HtmlnanoPurgeCssSourceMapOptions = {
|
|
37
|
+
absolute?: boolean;
|
|
38
|
+
annotation?: boolean | string;
|
|
39
|
+
from?: string;
|
|
40
|
+
inline?: boolean;
|
|
41
|
+
prev?: boolean | object | string;
|
|
42
|
+
sourcesContent?: boolean;
|
|
43
|
+
to?: string;
|
|
44
|
+
};
|
|
45
|
+
type HtmlnanoPurgeCssSafelist = HtmlnanoPurgeCssPattern[] | {
|
|
46
|
+
standard?: HtmlnanoPurgeCssPattern[];
|
|
47
|
+
deep?: RegExp[];
|
|
48
|
+
greedy?: RegExp[];
|
|
49
|
+
variables?: HtmlnanoPurgeCssPattern[];
|
|
50
|
+
keyframes?: HtmlnanoPurgeCssPattern[];
|
|
51
|
+
};
|
|
52
|
+
interface HtmlnanoPurgeCssOptions {
|
|
53
|
+
tool: 'purgeCSS';
|
|
54
|
+
defaultExtractor?: HtmlnanoPurgeCssDefaultExtractor;
|
|
55
|
+
fontFace?: boolean;
|
|
56
|
+
keyframes?: boolean;
|
|
57
|
+
output?: string;
|
|
58
|
+
rejected?: boolean;
|
|
59
|
+
rejectedCss?: boolean;
|
|
60
|
+
sourceMap?: boolean | HtmlnanoPurgeCssSourceMapOptions;
|
|
61
|
+
stdin?: boolean;
|
|
62
|
+
stdout?: boolean;
|
|
63
|
+
variables?: boolean;
|
|
64
|
+
safelist?: HtmlnanoPurgeCssSafelist;
|
|
65
|
+
blocklist?: HtmlnanoPurgeCssPattern[];
|
|
66
|
+
skippedContentGlobs?: string[];
|
|
67
|
+
dynamicAttributes?: string[];
|
|
68
|
+
}
|
|
23
69
|
interface HtmlnanoOptions {
|
|
24
70
|
skipConfigLoading?: boolean;
|
|
25
71
|
configPath?: string;
|
|
@@ -34,16 +80,16 @@ interface HtmlnanoOptions {
|
|
|
34
80
|
minifyUrls?: URL | string | false;
|
|
35
81
|
mergeStyles?: boolean;
|
|
36
82
|
mergeScripts?: boolean;
|
|
37
|
-
minifyCss?:
|
|
83
|
+
minifyCss?: HtmlnanoMinifyCssOptions | boolean;
|
|
38
84
|
minifyHtmlTemplate?: MinifyHtmlTemplateOptions;
|
|
39
85
|
minifyConditionalComments?: boolean;
|
|
40
|
-
minifyJs?:
|
|
86
|
+
minifyJs?: HtmlnanoMinifyJsOptions | boolean;
|
|
41
87
|
minifyJson?: boolean;
|
|
42
88
|
minifyAttributes?: boolean | {
|
|
43
89
|
metaContent?: boolean;
|
|
44
90
|
redundantWhitespaces?: 'safe' | 'agressive' | false;
|
|
45
91
|
};
|
|
46
|
-
minifySvg?:
|
|
92
|
+
minifySvg?: HtmlnanoMinifySvgOptions | boolean;
|
|
47
93
|
normalizeAttributeValues?: boolean;
|
|
48
94
|
removeAttributeQuotes?: boolean | {
|
|
49
95
|
force?: boolean;
|
|
@@ -55,9 +101,8 @@ interface HtmlnanoOptions {
|
|
|
55
101
|
};
|
|
56
102
|
removeRedundantAttributes?: boolean;
|
|
57
103
|
removeOptionalTags?: boolean;
|
|
58
|
-
removeUnusedCss?: boolean |
|
|
59
|
-
tool
|
|
60
|
-
} & Omit<UserDefinedOptions, 'content' | 'css' | 'extractors'>) | {
|
|
104
|
+
removeUnusedCss?: boolean | HtmlnanoPurgeCssOptions | {
|
|
105
|
+
tool?: 'uncss';
|
|
61
106
|
banner?: boolean;
|
|
62
107
|
csspath?: string;
|
|
63
108
|
htmlroot?: string;
|
|
@@ -77,7 +122,7 @@ interface HtmlnanoOptions {
|
|
|
77
122
|
type HtmlnanoModuleAttrsHandler = (attrs: Record<string, string | boolean | void>, node: PostHTML.Node) => Record<string, string | boolean | void>;
|
|
78
123
|
type HtmlnanoModuleContentHandler = (content: Array<PostHTMLNodeLike>, node: PostHTML.Node) => MaybeArray<PostHTMLNodeLike>;
|
|
79
124
|
type HtmlnanoModuleNodeHandler = (node: PostHTMLNodeLike) => PostHTML.Node | string;
|
|
80
|
-
type OptionalOptions<T> = T extends boolean | string | Function | number | null | undefined ? T : T extends object ? Partial<T> : T;
|
|
125
|
+
type OptionalOptions<T> = T extends boolean | string | Function | number | null | undefined ? T : T extends Array<infer Item> ? Array<Item> : T extends object ? Partial<T> : T;
|
|
81
126
|
type HtmlnanoModule<Options = any> = {
|
|
82
127
|
onAttrs?: (options: Partial<HtmlnanoOptions>, moduleOptions: OptionalOptions<Options>) => HtmlnanoModuleAttrsHandler;
|
|
83
128
|
onContent?: (options: Partial<HtmlnanoOptions>, moduleOptions: OptionalOptions<Options>) => HtmlnanoModuleContentHandler;
|
|
@@ -1,25 +1,71 @@
|
|
|
1
1
|
import PostHTML from 'posthtml';
|
|
2
2
|
import { MinifyOptions } from 'terser';
|
|
3
|
-
import { Options } from 'cssnano';
|
|
4
|
-
import { Config } from 'svgo';
|
|
5
|
-
import { UserDefinedOptions } from 'purgecss';
|
|
6
3
|
|
|
7
|
-
type
|
|
4
|
+
type PostHTMLNodeLike = PostHTML.Node | string;
|
|
5
|
+
type PostHTMLTreeLike = [PostHTMLNodeLike] & PostHTML.NodeAPI & {
|
|
8
6
|
options?: {
|
|
9
7
|
quoteAllAttributes?: boolean | undefined;
|
|
10
8
|
quoteStyle?: 0 | 1 | 2 | undefined;
|
|
11
9
|
replaceQuote?: boolean | undefined;
|
|
12
10
|
} | undefined;
|
|
13
11
|
render(): string;
|
|
14
|
-
render(node:
|
|
12
|
+
render(node: PostHTMLNodeLike | PostHTMLTreeLike, renderOptions?: any): string;
|
|
15
13
|
};
|
|
16
14
|
type MaybeArray<T> = T | Array<T>;
|
|
17
|
-
type PostHTMLNodeLike = PostHTML.Node | string;
|
|
18
15
|
type HtmlnanoTemplateRule = {
|
|
19
16
|
tag: string;
|
|
20
17
|
attrs?: Record<string, string | boolean | void>;
|
|
21
18
|
};
|
|
22
19
|
type MinifyHtmlTemplateOptions = boolean | HtmlnanoTemplateRule[];
|
|
20
|
+
type HtmlnanoMinifyCssOptions = object;
|
|
21
|
+
type HtmlnanoMinifyJsOptions = object;
|
|
22
|
+
type HtmlnanoMinifySvgOptions = object;
|
|
23
|
+
type HtmlnanoPurgeCssPattern = string | RegExp;
|
|
24
|
+
type HtmlnanoPurgeCssExtractorResultDetailed = {
|
|
25
|
+
attributes: {
|
|
26
|
+
names: string[];
|
|
27
|
+
values: string[];
|
|
28
|
+
};
|
|
29
|
+
classes: string[];
|
|
30
|
+
ids: string[];
|
|
31
|
+
tags: string[];
|
|
32
|
+
undetermined: string[];
|
|
33
|
+
};
|
|
34
|
+
type HtmlnanoPurgeCssExtractorResult = HtmlnanoPurgeCssExtractorResultDetailed | string[];
|
|
35
|
+
type HtmlnanoPurgeCssDefaultExtractor = (content: string) => HtmlnanoPurgeCssExtractorResult;
|
|
36
|
+
type HtmlnanoPurgeCssSourceMapOptions = {
|
|
37
|
+
absolute?: boolean;
|
|
38
|
+
annotation?: boolean | string;
|
|
39
|
+
from?: string;
|
|
40
|
+
inline?: boolean;
|
|
41
|
+
prev?: boolean | object | string;
|
|
42
|
+
sourcesContent?: boolean;
|
|
43
|
+
to?: string;
|
|
44
|
+
};
|
|
45
|
+
type HtmlnanoPurgeCssSafelist = HtmlnanoPurgeCssPattern[] | {
|
|
46
|
+
standard?: HtmlnanoPurgeCssPattern[];
|
|
47
|
+
deep?: RegExp[];
|
|
48
|
+
greedy?: RegExp[];
|
|
49
|
+
variables?: HtmlnanoPurgeCssPattern[];
|
|
50
|
+
keyframes?: HtmlnanoPurgeCssPattern[];
|
|
51
|
+
};
|
|
52
|
+
interface HtmlnanoPurgeCssOptions {
|
|
53
|
+
tool: 'purgeCSS';
|
|
54
|
+
defaultExtractor?: HtmlnanoPurgeCssDefaultExtractor;
|
|
55
|
+
fontFace?: boolean;
|
|
56
|
+
keyframes?: boolean;
|
|
57
|
+
output?: string;
|
|
58
|
+
rejected?: boolean;
|
|
59
|
+
rejectedCss?: boolean;
|
|
60
|
+
sourceMap?: boolean | HtmlnanoPurgeCssSourceMapOptions;
|
|
61
|
+
stdin?: boolean;
|
|
62
|
+
stdout?: boolean;
|
|
63
|
+
variables?: boolean;
|
|
64
|
+
safelist?: HtmlnanoPurgeCssSafelist;
|
|
65
|
+
blocklist?: HtmlnanoPurgeCssPattern[];
|
|
66
|
+
skippedContentGlobs?: string[];
|
|
67
|
+
dynamicAttributes?: string[];
|
|
68
|
+
}
|
|
23
69
|
interface HtmlnanoOptions {
|
|
24
70
|
skipConfigLoading?: boolean;
|
|
25
71
|
configPath?: string;
|
|
@@ -34,16 +80,16 @@ interface HtmlnanoOptions {
|
|
|
34
80
|
minifyUrls?: URL | string | false;
|
|
35
81
|
mergeStyles?: boolean;
|
|
36
82
|
mergeScripts?: boolean;
|
|
37
|
-
minifyCss?:
|
|
83
|
+
minifyCss?: HtmlnanoMinifyCssOptions | boolean;
|
|
38
84
|
minifyHtmlTemplate?: MinifyHtmlTemplateOptions;
|
|
39
85
|
minifyConditionalComments?: boolean;
|
|
40
|
-
minifyJs?:
|
|
86
|
+
minifyJs?: HtmlnanoMinifyJsOptions | boolean;
|
|
41
87
|
minifyJson?: boolean;
|
|
42
88
|
minifyAttributes?: boolean | {
|
|
43
89
|
metaContent?: boolean;
|
|
44
90
|
redundantWhitespaces?: 'safe' | 'agressive' | false;
|
|
45
91
|
};
|
|
46
|
-
minifySvg?:
|
|
92
|
+
minifySvg?: HtmlnanoMinifySvgOptions | boolean;
|
|
47
93
|
normalizeAttributeValues?: boolean;
|
|
48
94
|
removeAttributeQuotes?: boolean | {
|
|
49
95
|
force?: boolean;
|
|
@@ -55,9 +101,8 @@ interface HtmlnanoOptions {
|
|
|
55
101
|
};
|
|
56
102
|
removeRedundantAttributes?: boolean;
|
|
57
103
|
removeOptionalTags?: boolean;
|
|
58
|
-
removeUnusedCss?: boolean |
|
|
59
|
-
tool
|
|
60
|
-
} & Omit<UserDefinedOptions, 'content' | 'css' | 'extractors'>) | {
|
|
104
|
+
removeUnusedCss?: boolean | HtmlnanoPurgeCssOptions | {
|
|
105
|
+
tool?: 'uncss';
|
|
61
106
|
banner?: boolean;
|
|
62
107
|
csspath?: string;
|
|
63
108
|
htmlroot?: string;
|
|
@@ -77,7 +122,7 @@ interface HtmlnanoOptions {
|
|
|
77
122
|
type HtmlnanoModuleAttrsHandler = (attrs: Record<string, string | boolean | void>, node: PostHTML.Node) => Record<string, string | boolean | void>;
|
|
78
123
|
type HtmlnanoModuleContentHandler = (content: Array<PostHTMLNodeLike>, node: PostHTML.Node) => MaybeArray<PostHTMLNodeLike>;
|
|
79
124
|
type HtmlnanoModuleNodeHandler = (node: PostHTMLNodeLike) => PostHTML.Node | string;
|
|
80
|
-
type OptionalOptions<T> = T extends boolean | string | Function | number | null | undefined ? T : T extends object ? Partial<T> : T;
|
|
125
|
+
type OptionalOptions<T> = T extends boolean | string | Function | number | null | undefined ? T : T extends Array<infer Item> ? Array<Item> : T extends object ? Partial<T> : T;
|
|
81
126
|
type HtmlnanoModule<Options = any> = {
|
|
82
127
|
onAttrs?: (options: Partial<HtmlnanoOptions>, moduleOptions: OptionalOptions<Options>) => HtmlnanoModuleAttrsHandler;
|
|
83
128
|
onContent?: (options: Partial<HtmlnanoOptions>, moduleOptions: OptionalOptions<Options>) => HtmlnanoModuleContentHandler;
|
|
@@ -192,10 +192,22 @@ function processNodeWithOnAttrs(node, terserOptions, terser) {
|
|
|
192
192
|
const minifiedJs = code.substring(jsWrapperStart.length, code.length - jsWrapperEnd.length);
|
|
193
193
|
node.attrs[attrName] = minifiedJs;
|
|
194
194
|
}
|
|
195
|
+
}).catch((error)=>{
|
|
196
|
+
// Skip invalid inline handler code and preserve the original value.
|
|
197
|
+
if (isTerserParseError(error)) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
throw error;
|
|
195
201
|
});
|
|
196
202
|
promises.push(promise);
|
|
197
203
|
}
|
|
198
204
|
return promises;
|
|
199
205
|
}
|
|
206
|
+
function isTerserParseError(error) {
|
|
207
|
+
if (!(error instanceof Error)) {
|
|
208
|
+
return false;
|
|
209
|
+
}
|
|
210
|
+
return error.name === 'SyntaxError' || error.message.includes('JS_Parse_Error');
|
|
211
|
+
}
|
|
200
212
|
|
|
201
213
|
exports.default = mod;
|
|
@@ -190,10 +190,22 @@ function processNodeWithOnAttrs(node, terserOptions, terser) {
|
|
|
190
190
|
const minifiedJs = code.substring(jsWrapperStart.length, code.length - jsWrapperEnd.length);
|
|
191
191
|
node.attrs[attrName] = minifiedJs;
|
|
192
192
|
}
|
|
193
|
+
}).catch((error)=>{
|
|
194
|
+
// Skip invalid inline handler code and preserve the original value.
|
|
195
|
+
if (isTerserParseError(error)) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
throw error;
|
|
193
199
|
});
|
|
194
200
|
promises.push(promise);
|
|
195
201
|
}
|
|
196
202
|
return promises;
|
|
197
203
|
}
|
|
204
|
+
function isTerserParseError(error) {
|
|
205
|
+
if (!(error instanceof Error)) {
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
return error.name === 'SyntaxError' || error.message.includes('JS_Parse_Error');
|
|
209
|
+
}
|
|
198
210
|
|
|
199
211
|
export { mod as default };
|