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.
Files changed (88) hide show
  1. package/README.md +37 -23
  2. package/dist/_modules/collapseAttributeWhitespace.d.mts +58 -14
  3. package/dist/_modules/collapseAttributeWhitespace.d.ts +58 -14
  4. package/dist/_modules/collapseBooleanAttributes.d.mts +58 -14
  5. package/dist/_modules/collapseBooleanAttributes.d.ts +58 -14
  6. package/dist/_modules/collapseWhitespace.d.mts +58 -14
  7. package/dist/_modules/collapseWhitespace.d.ts +58 -14
  8. package/dist/_modules/custom.d.mts +58 -14
  9. package/dist/_modules/custom.d.ts +58 -14
  10. package/dist/_modules/deduplicateAttributeValues.d.mts +58 -14
  11. package/dist/_modules/deduplicateAttributeValues.d.ts +58 -14
  12. package/dist/_modules/example.d.mts +58 -14
  13. package/dist/_modules/example.d.ts +58 -14
  14. package/dist/_modules/mergeScripts.d.mts +58 -14
  15. package/dist/_modules/mergeScripts.d.ts +58 -14
  16. package/dist/_modules/mergeScripts.js +30 -23
  17. package/dist/_modules/mergeScripts.mjs +30 -23
  18. package/dist/_modules/mergeStyles.d.mts +58 -14
  19. package/dist/_modules/mergeStyles.d.ts +58 -14
  20. package/dist/_modules/mergeStyles.js +26 -21
  21. package/dist/_modules/mergeStyles.mjs +26 -21
  22. package/dist/_modules/minifyAttributes.d.mts +58 -14
  23. package/dist/_modules/minifyAttributes.d.ts +58 -14
  24. package/dist/_modules/minifyAttributes.js +2 -2
  25. package/dist/_modules/minifyAttributes.mjs +2 -2
  26. package/dist/_modules/minifyConditionalComments.d.mts +58 -14
  27. package/dist/_modules/minifyConditionalComments.d.ts +58 -14
  28. package/dist/_modules/minifyCss.d.mts +61 -14
  29. package/dist/_modules/minifyCss.d.ts +61 -14
  30. package/dist/_modules/minifyCss.js +79 -12
  31. package/dist/_modules/minifyCss.mjs +79 -13
  32. package/dist/_modules/minifyHtmlTemplate.d.mts +58 -14
  33. package/dist/_modules/minifyHtmlTemplate.d.ts +58 -14
  34. package/dist/_modules/minifyJs.d.mts +58 -13
  35. package/dist/_modules/minifyJs.d.ts +58 -13
  36. package/dist/_modules/minifyJs.js +12 -0
  37. package/dist/_modules/minifyJs.mjs +12 -0
  38. package/dist/_modules/minifyJson.d.mts +58 -14
  39. package/dist/_modules/minifyJson.d.ts +58 -14
  40. package/dist/_modules/minifyJson.js +1 -1
  41. package/dist/_modules/minifyJson.mjs +1 -1
  42. package/dist/_modules/minifySvg.d.mts +58 -13
  43. package/dist/_modules/minifySvg.d.ts +58 -13
  44. package/dist/_modules/minifySvg.js +2 -2
  45. package/dist/_modules/minifySvg.mjs +2 -2
  46. package/dist/_modules/minifyUrls.d.mts +58 -14
  47. package/dist/_modules/minifyUrls.d.ts +58 -14
  48. package/dist/_modules/minifyUrls.js +2 -2
  49. package/dist/_modules/minifyUrls.mjs +2 -2
  50. package/dist/_modules/normalizeAttributeValues.d.mts +58 -14
  51. package/dist/_modules/normalizeAttributeValues.d.ts +58 -14
  52. package/dist/_modules/removeAttributeQuotes.d.mts +58 -14
  53. package/dist/_modules/removeAttributeQuotes.d.ts +58 -14
  54. package/dist/_modules/removeComments.d.mts +58 -14
  55. package/dist/_modules/removeComments.d.ts +58 -14
  56. package/dist/_modules/removeComments.js +1 -1
  57. package/dist/_modules/removeComments.mjs +1 -1
  58. package/dist/_modules/removeEmptyAttributes.d.mts +58 -14
  59. package/dist/_modules/removeEmptyAttributes.d.ts +58 -14
  60. package/dist/_modules/removeEmptyElements.d.mts +58 -14
  61. package/dist/_modules/removeEmptyElements.d.ts +58 -14
  62. package/dist/_modules/removeOptionalTags.d.mts +58 -14
  63. package/dist/_modules/removeOptionalTags.d.ts +58 -14
  64. package/dist/_modules/removeRedundantAttributes.d.mts +58 -14
  65. package/dist/_modules/removeRedundantAttributes.d.ts +58 -14
  66. package/dist/_modules/removeUnusedCss.d.mts +58 -14
  67. package/dist/_modules/removeUnusedCss.d.ts +58 -14
  68. package/dist/_modules/removeUnusedCss.js +3 -2
  69. package/dist/_modules/removeUnusedCss.mjs +3 -2
  70. package/dist/_modules/sortAttributes.d.mts +61 -16
  71. package/dist/_modules/sortAttributes.d.ts +61 -16
  72. package/dist/_modules/sortAttributes.js +5 -9
  73. package/dist/_modules/sortAttributes.mjs +5 -9
  74. package/dist/_modules/sortAttributesWithLists.d.mts +61 -15
  75. package/dist/_modules/sortAttributesWithLists.d.ts +61 -15
  76. package/dist/_modules/sortAttributesWithLists.js +43 -56
  77. package/dist/_modules/sortAttributesWithLists.mjs +43 -56
  78. package/dist/index.d.ts +59 -15
  79. package/dist/index.js +7 -6
  80. package/dist/index.mjs +7 -6
  81. package/dist/presets/ampSafe.d.ts +57 -12
  82. package/dist/presets/max.d.ts +57 -12
  83. package/dist/presets/max.js +9 -5
  84. package/dist/presets/max.mjs +9 -5
  85. package/dist/presets/safe.d.ts +57 -12
  86. package/dist/presets/safe.js +1 -1
  87. package/dist/presets/safe.mjs +1 -1
  88. package/package.json +20 -14
@@ -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 PostHTMLTreeLike = [PostHTML.Node] & PostHTML.NodeAPI & {
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: PostHTML.Node | PostHTMLTreeLike, renderOptions?: any): string;
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?: Options | boolean;
82
+ minifyCss?: HtmlnanoMinifyCssOptions | boolean;
38
83
  minifyHtmlTemplate?: MinifyHtmlTemplateOptions;
39
84
  minifyConditionalComments?: boolean;
40
- minifyJs?: MinifyOptions | boolean;
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?: Config | boolean;
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: 'purgeCSS';
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 PostHTMLTreeLike = [PostHTML.Node] & PostHTML.NodeAPI & {
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: PostHTML.Node | PostHTMLTreeLike, renderOptions?: any): string;
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?: Options | boolean;
82
+ minifyCss?: HtmlnanoMinifyCssOptions | boolean;
38
83
  minifyHtmlTemplate?: MinifyHtmlTemplateOptions;
39
84
  minifyConditionalComments?: boolean;
40
- minifyJs?: MinifyOptions | boolean;
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?: Config | boolean;
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: 'purgeCSS';
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;
@@ -112,13 +112,14 @@ function runPurgecss(tree, css, userOptions, purgecss, extractor) {
112
112
  }
113
113
  /** Remove unused CSS */ const mod = {
114
114
  async default (tree, options, userOptions) {
115
+ var _resolvedOptions_tool;
115
116
  const promises = [];
116
117
  let html;
117
118
  let extractor;
118
119
  const purgecss = await helpers_js.optionalImport('purgecss');
119
120
  const uncss = await helpers_js.optionalImport('uncss');
120
121
  const resolvedOptions = resolveUserOptions(userOptions);
121
- const tool = resolvedOptions.tool;
122
+ const tool = (_resolvedOptions_tool = resolvedOptions.tool) != null ? _resolvedOptions_tool : 'purgeCSS';
122
123
  const toolOptions = stripToolOption(resolvedOptions);
123
124
  tree.walk((node)=>{
124
125
  if (helpers_js.isStyleNode(node) && helpers_js.isCssStyleType(node)) {
@@ -127,7 +128,7 @@ function runPurgecss(tree, css, userOptions, purgecss, extractor) {
127
128
  extractor != null ? extractor : extractor = purgeFromHtml(tree);
128
129
  promises.push(processStyleNodePurgeCSS(tree, node, toolOptions, purgecss, extractor));
129
130
  }
130
- } else {
131
+ } else if (tool === 'uncss') {
131
132
  if (uncss) {
132
133
  html != null ? html : html = tree.render(tree);
133
134
  promises.push(processStyleNodeUnCSS(html, node, toolOptions, uncss));
@@ -110,13 +110,14 @@ function runPurgecss(tree, css, userOptions, purgecss, extractor) {
110
110
  }
111
111
  /** Remove unused CSS */ const mod = {
112
112
  async default (tree, options, userOptions) {
113
+ var _resolvedOptions_tool;
113
114
  const promises = [];
114
115
  let html;
115
116
  let extractor;
116
117
  const purgecss = await optionalImport('purgecss');
117
118
  const uncss = await optionalImport('uncss');
118
119
  const resolvedOptions = resolveUserOptions(userOptions);
119
- const tool = resolvedOptions.tool;
120
+ const tool = (_resolvedOptions_tool = resolvedOptions.tool) != null ? _resolvedOptions_tool : 'purgeCSS';
120
121
  const toolOptions = stripToolOption(resolvedOptions);
121
122
  tree.walk((node)=>{
122
123
  if (isStyleNode(node) && isCssStyleType(node)) {
@@ -125,7 +126,7 @@ function runPurgecss(tree, css, userOptions, purgecss, extractor) {
125
126
  extractor != null ? extractor : extractor = purgeFromHtml(tree);
126
127
  promises.push(processStyleNodePurgeCSS(tree, node, toolOptions, purgecss, extractor));
127
128
  }
128
- } else {
129
+ } else if (tool === 'uncss') {
129
130
  if (uncss) {
130
131
  html != null ? html : html = tree.render(tree);
131
132
  promises.push(processStyleNodeUnCSS(html, node, toolOptions, uncss));
@@ -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 PostHTMLTreeLike = [PostHTML.Node] & PostHTML.NodeAPI & {
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: PostHTML.Node | PostHTMLTreeLike, renderOptions?: any): string;
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?: Options | boolean;
82
+ minifyCss?: HtmlnanoMinifyCssOptions | boolean;
38
83
  minifyHtmlTemplate?: MinifyHtmlTemplateOptions;
39
84
  minifyConditionalComments?: boolean;
40
- minifyJs?: MinifyOptions | boolean;
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?: Config | boolean;
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: 'purgeCSS';
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;
@@ -85,7 +129,8 @@ type HtmlnanoModule<Options = any> = {
85
129
  default?: (tree: PostHTMLTreeLike, options: Partial<HtmlnanoOptions>, moduleOptions: OptionalOptions<Options>) => PostHTMLTreeLike | Promise<PostHTMLTreeLike>;
86
130
  };
87
131
 
88
- type ValidOptions = 'alphabetical' | 'frequency';
89
- declare const mod: HtmlnanoModule<boolean | ValidOptions>;
132
+ type SortAttributesOption = 'alphabetical' | 'frequency';
133
+
134
+ declare const mod: HtmlnanoModule<boolean | SortAttributesOption>;
90
135
 
91
136
  export { mod as default };
@@ -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 PostHTMLTreeLike = [PostHTML.Node] & PostHTML.NodeAPI & {
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: PostHTML.Node | PostHTMLTreeLike, renderOptions?: any): string;
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?: Options | boolean;
82
+ minifyCss?: HtmlnanoMinifyCssOptions | boolean;
38
83
  minifyHtmlTemplate?: MinifyHtmlTemplateOptions;
39
84
  minifyConditionalComments?: boolean;
40
- minifyJs?: MinifyOptions | boolean;
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?: Config | boolean;
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: 'purgeCSS';
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;
@@ -85,7 +129,8 @@ type HtmlnanoModule<Options = any> = {
85
129
  default?: (tree: PostHTMLTreeLike, options: Partial<HtmlnanoOptions>, moduleOptions: OptionalOptions<Options>) => PostHTMLTreeLike | Promise<PostHTMLTreeLike>;
86
130
  };
87
131
 
88
- type ValidOptions = 'alphabetical' | 'frequency';
89
- declare const mod: HtmlnanoModule<boolean | ValidOptions>;
132
+ type SortAttributesOption = 'alphabetical' | 'frequency';
133
+
134
+ declare const mod: HtmlnanoModule<boolean | SortAttributesOption>;
90
135
 
91
136
  export { mod as default };
@@ -4,11 +4,12 @@ const validOptions = new Set([
4
4
  'frequency',
5
5
  'alphabetical'
6
6
  ]);
7
- const processModuleOptions = (options)=>{
7
+ function resolveSortType(options) {
8
8
  if (options === true) return 'alphabetical';
9
9
  if (options === false) return false;
10
10
  return validOptions.has(options) ? options : false;
11
- };
11
+ }
12
+
12
13
  class AttributeTokenChain {
13
14
  addFromNodeAttrs(nodeAttrs) {
14
15
  Object.keys(nodeAttrs).forEach((attrName)=>{
@@ -70,7 +71,7 @@ class AttributeTokenChain {
70
71
  }
71
72
  /** Sort attibutes */ const mod = {
72
73
  default (tree, options, moduleOptions) {
73
- const sortType = processModuleOptions(moduleOptions);
74
+ const sortType = resolveSortType(moduleOptions);
74
75
  if (sortType === 'alphabetical') {
75
76
  return sortAttributesInAlphabeticalOrder(tree);
76
77
  }
@@ -86,12 +87,7 @@ function sortAttributesInAlphabeticalOrder(tree) {
86
87
  if (!node.attrs) {
87
88
  return node;
88
89
  }
89
- const newAttrs = {};
90
- Object.keys(node.attrs)// @ts-expect-error -- deliberately use minus operator to sort things
91
- .sort((a, b)=>typeof a.localeCompare === 'function' ? a.localeCompare(b) : a - b).forEach((attr)=>{
92
- newAttrs[attr] = node.attrs[attr];
93
- });
94
- node.attrs = newAttrs;
90
+ node.attrs = Object.fromEntries(Object.entries(node.attrs).sort(([attrA], [attrB])=>attrA.localeCompare(attrB)));
95
91
  return node;
96
92
  });
97
93
  return tree;
@@ -2,11 +2,12 @@ const validOptions = new Set([
2
2
  'frequency',
3
3
  'alphabetical'
4
4
  ]);
5
- const processModuleOptions = (options)=>{
5
+ function resolveSortType(options) {
6
6
  if (options === true) return 'alphabetical';
7
7
  if (options === false) return false;
8
8
  return validOptions.has(options) ? options : false;
9
- };
9
+ }
10
+
10
11
  class AttributeTokenChain {
11
12
  addFromNodeAttrs(nodeAttrs) {
12
13
  Object.keys(nodeAttrs).forEach((attrName)=>{
@@ -68,7 +69,7 @@ class AttributeTokenChain {
68
69
  }
69
70
  /** Sort attibutes */ const mod = {
70
71
  default (tree, options, moduleOptions) {
71
- const sortType = processModuleOptions(moduleOptions);
72
+ const sortType = resolveSortType(moduleOptions);
72
73
  if (sortType === 'alphabetical') {
73
74
  return sortAttributesInAlphabeticalOrder(tree);
74
75
  }
@@ -84,12 +85,7 @@ function sortAttributesInAlphabeticalOrder(tree) {
84
85
  if (!node.attrs) {
85
86
  return node;
86
87
  }
87
- const newAttrs = {};
88
- Object.keys(node.attrs)// @ts-expect-error -- deliberately use minus operator to sort things
89
- .sort((a, b)=>typeof a.localeCompare === 'function' ? a.localeCompare(b) : a - b).forEach((attr)=>{
90
- newAttrs[attr] = node.attrs[attr];
91
- });
92
- node.attrs = newAttrs;
88
+ node.attrs = Object.fromEntries(Object.entries(node.attrs).sort(([attrA], [attrB])=>attrA.localeCompare(attrB)));
93
89
  return node;
94
90
  });
95
91
  return tree;