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.
Files changed (186) hide show
  1. package/README.md +53 -12
  2. package/dist/_modules/collapseAttributeWhitespace.d.mts +57 -0
  3. package/dist/_modules/collapseAttributeWhitespace.d.ts +57 -0
  4. package/dist/_modules/collapseAttributeWhitespace.js +296 -0
  5. package/dist/_modules/collapseAttributeWhitespace.mjs +293 -0
  6. package/dist/_modules/collapseBooleanAttributes.d.mts +60 -0
  7. package/dist/_modules/collapseBooleanAttributes.d.ts +60 -0
  8. package/dist/_modules/collapseBooleanAttributes.js +159 -0
  9. package/{lib/modules → dist/_modules}/collapseBooleanAttributes.mjs +39 -57
  10. package/dist/_modules/collapseWhitespace.d.mts +57 -0
  11. package/dist/_modules/collapseWhitespace.d.ts +57 -0
  12. package/dist/_modules/collapseWhitespace.js +172 -0
  13. package/dist/_modules/collapseWhitespace.mjs +170 -0
  14. package/dist/_modules/custom.d.mts +57 -0
  15. package/dist/_modules/custom.d.ts +57 -0
  16. package/dist/_modules/custom.js +22 -0
  17. package/dist/_modules/custom.mjs +20 -0
  18. package/dist/_modules/deduplicateAttributeValues.d.mts +56 -0
  19. package/dist/_modules/deduplicateAttributeValues.d.ts +56 -0
  20. package/dist/_modules/deduplicateAttributeValues.js +38 -0
  21. package/dist/_modules/deduplicateAttributeValues.mjs +36 -0
  22. package/dist/_modules/example.d.mts +59 -0
  23. package/dist/_modules/example.d.ts +59 -0
  24. package/dist/_modules/example.js +67 -0
  25. package/dist/_modules/example.mjs +65 -0
  26. package/dist/_modules/mergeScripts.d.mts +56 -0
  27. package/dist/_modules/mergeScripts.d.ts +56 -0
  28. package/dist/_modules/mergeScripts.js +53 -0
  29. package/dist/_modules/mergeScripts.mjs +51 -0
  30. package/dist/_modules/mergeStyles.d.mts +56 -0
  31. package/dist/_modules/mergeStyles.d.ts +56 -0
  32. package/dist/_modules/mergeStyles.js +42 -0
  33. package/dist/_modules/mergeStyles.mjs +40 -0
  34. package/dist/_modules/minifyConditionalComments.d.mts +56 -0
  35. package/dist/_modules/minifyConditionalComments.d.ts +56 -0
  36. package/dist/_modules/minifyConditionalComments.js +54 -0
  37. package/{lib/modules → dist/_modules}/minifyConditionalComments.mjs +21 -22
  38. package/dist/_modules/minifyCss.d.mts +56 -0
  39. package/dist/_modules/minifyCss.d.ts +56 -0
  40. package/dist/_modules/minifyCss.js +84 -0
  41. package/dist/_modules/minifyCss.mjs +82 -0
  42. package/dist/_modules/minifyJs.d.mts +56 -0
  43. package/dist/_modules/minifyJs.d.ts +56 -0
  44. package/dist/_modules/minifyJs.js +108 -0
  45. package/dist/_modules/minifyJs.mjs +106 -0
  46. package/dist/_modules/minifyJson.d.mts +56 -0
  47. package/dist/_modules/minifyJson.d.ts +56 -0
  48. package/dist/_modules/minifyJson.js +35 -0
  49. package/dist/_modules/minifyJson.mjs +33 -0
  50. package/dist/_modules/minifySvg.d.mts +56 -0
  51. package/dist/_modules/minifySvg.d.ts +56 -0
  52. package/dist/_modules/minifySvg.js +40 -0
  53. package/dist/_modules/minifySvg.mjs +38 -0
  54. package/dist/_modules/minifyUrls.d.mts +56 -0
  55. package/dist/_modules/minifyUrls.d.ts +56 -0
  56. package/dist/_modules/minifyUrls.js +180 -0
  57. package/dist/_modules/minifyUrls.mjs +178 -0
  58. package/dist/_modules/normalizeAttributeValues.d.mts +56 -0
  59. package/dist/_modules/normalizeAttributeValues.d.ts +56 -0
  60. package/dist/_modules/normalizeAttributeValues.js +234 -0
  61. package/dist/_modules/normalizeAttributeValues.mjs +232 -0
  62. package/dist/_modules/removeAttributeQuotes.d.mts +56 -0
  63. package/dist/_modules/removeAttributeQuotes.d.ts +56 -0
  64. package/dist/_modules/removeAttributeQuotes.js +15 -0
  65. package/dist/_modules/removeAttributeQuotes.mjs +13 -0
  66. package/dist/_modules/removeComments.d.mts +58 -0
  67. package/dist/_modules/removeComments.d.ts +58 -0
  68. package/dist/_modules/removeComments.js +83 -0
  69. package/{lib/modules → dist/_modules}/removeComments.mjs +24 -35
  70. package/dist/_modules/removeEmptyAttributes.d.mts +56 -0
  71. package/dist/_modules/removeEmptyAttributes.d.ts +56 -0
  72. package/dist/_modules/removeEmptyAttributes.js +197 -0
  73. package/dist/_modules/removeEmptyAttributes.mjs +195 -0
  74. package/dist/_modules/removeOptionalTags.d.mts +56 -0
  75. package/dist/_modules/removeOptionalTags.d.ts +56 -0
  76. package/dist/_modules/removeOptionalTags.js +190 -0
  77. package/{lib/modules → dist/_modules}/removeOptionalTags.mjs +54 -91
  78. package/dist/_modules/removeRedundantAttributes.d.mts +57 -0
  79. package/dist/_modules/removeRedundantAttributes.d.ts +57 -0
  80. package/dist/_modules/removeRedundantAttributes.js +128 -0
  81. package/{lib/modules → dist/_modules}/removeRedundantAttributes.mjs +43 -59
  82. package/dist/_modules/removeUnusedCss.d.mts +60 -0
  83. package/dist/_modules/removeUnusedCss.d.ts +60 -0
  84. package/dist/_modules/removeUnusedCss.js +134 -0
  85. package/dist/_modules/removeUnusedCss.mjs +132 -0
  86. package/dist/_modules/sortAttributes.d.mts +57 -0
  87. package/dist/_modules/sortAttributes.d.ts +57 -0
  88. package/dist/_modules/sortAttributes.js +102 -0
  89. package/{lib/modules → dist/_modules}/sortAttributes.mjs +39 -60
  90. package/dist/_modules/sortAttributesWithLists.d.mts +56 -0
  91. package/dist/_modules/sortAttributesWithLists.d.ts +56 -0
  92. package/dist/_modules/sortAttributesWithLists.js +118 -0
  93. package/{lib/modules → dist/_modules}/sortAttributesWithLists.mjs +41 -60
  94. package/dist/helpers.js +72 -0
  95. package/dist/helpers.mjs +63 -0
  96. package/dist/index.js +223 -0
  97. package/dist/index.mjs +209 -0
  98. package/dist/presets/ampSafe.js +19 -0
  99. package/{lib → dist}/presets/ampSafe.mjs +6 -4
  100. package/dist/presets/max.js +28 -0
  101. package/{lib → dist}/presets/max.mjs +6 -4
  102. package/dist/presets/safe.js +60 -0
  103. package/{lib → dist}/presets/safe.mjs +13 -20
  104. package/package.json +53 -59
  105. package/.eslintignore +0 -3
  106. package/CHANGELOG.md +0 -398
  107. package/docs/README.md +0 -33
  108. package/docs/babel.config.js +0 -3
  109. package/docs/docs/010-introduction.md +0 -22
  110. package/docs/docs/020-usage.md +0 -117
  111. package/docs/docs/030-config.md +0 -21
  112. package/docs/docs/040-presets.md +0 -75
  113. package/docs/docs/050-modules.md +0 -855
  114. package/docs/docs/060-contribute.md +0 -16
  115. package/docs/docusaurus.config.js +0 -65
  116. package/docs/netlify.toml +0 -4
  117. package/docs/package-lock.json +0 -21796
  118. package/docs/package.json +0 -40
  119. package/docs/sidebars.js +0 -26
  120. package/docs/versioned_docs/version-1.1.1/010-introduction.md +0 -22
  121. package/docs/versioned_docs/version-1.1.1/020-usage.md +0 -77
  122. package/docs/versioned_docs/version-1.1.1/030-config.md +0 -21
  123. package/docs/versioned_docs/version-1.1.1/040-presets.md +0 -75
  124. package/docs/versioned_docs/version-1.1.1/050-modules.md +0 -785
  125. package/docs/versioned_docs/version-1.1.1/060-contribute.md +0 -16
  126. package/docs/versioned_docs/version-2.0.0/010-introduction.md +0 -22
  127. package/docs/versioned_docs/version-2.0.0/020-usage.md +0 -77
  128. package/docs/versioned_docs/version-2.0.0/030-config.md +0 -21
  129. package/docs/versioned_docs/version-2.0.0/040-presets.md +0 -75
  130. package/docs/versioned_docs/version-2.0.0/050-modules.md +0 -838
  131. package/docs/versioned_docs/version-2.0.0/060-contribute.md +0 -16
  132. package/docs/versioned_sidebars/version-1.1.1-sidebars.json +0 -8
  133. package/docs/versioned_sidebars/version-2.0.0-sidebars.json +0 -8
  134. package/docs/versions.json +0 -4
  135. package/index.cjs +0 -11
  136. package/index.d.cts +0 -3
  137. package/index.d.mts +0 -3
  138. package/index.d.ts +0 -93
  139. package/index.mjs +0 -2
  140. package/lib/helpers.cjs +0 -79
  141. package/lib/helpers.mjs +0 -53
  142. package/lib/htmlnano.cjs +0 -200
  143. package/lib/htmlnano.mjs +0 -196
  144. package/lib/modules/collapseAttributeWhitespace.cjs +0 -86
  145. package/lib/modules/collapseAttributeWhitespace.mjs +0 -104
  146. package/lib/modules/collapseBooleanAttributes.cjs +0 -62
  147. package/lib/modules/collapseWhitespace.cjs +0 -100
  148. package/lib/modules/collapseWhitespace.mjs +0 -132
  149. package/lib/modules/custom.cjs +0 -19
  150. package/lib/modules/custom.mjs +0 -16
  151. package/lib/modules/deduplicateAttributeValues.cjs +0 -38
  152. package/lib/modules/deduplicateAttributeValues.mjs +0 -40
  153. package/lib/modules/example.cjs +0 -85
  154. package/lib/modules/example.mjs +0 -75
  155. package/lib/modules/mergeScripts.cjs +0 -54
  156. package/lib/modules/mergeScripts.mjs +0 -56
  157. package/lib/modules/mergeStyles.cjs +0 -38
  158. package/lib/modules/mergeStyles.mjs +0 -36
  159. package/lib/modules/minifyConditionalComments.cjs +0 -47
  160. package/lib/modules/minifyCss.cjs +0 -73
  161. package/lib/modules/minifyCss.mjs +0 -88
  162. package/lib/modules/minifyJs.cjs +0 -103
  163. package/lib/modules/minifyJs.mjs +0 -121
  164. package/lib/modules/minifyJson.cjs +0 -24
  165. package/lib/modules/minifyJson.mjs +0 -21
  166. package/lib/modules/minifySvg.cjs +0 -37
  167. package/lib/modules/minifySvg.mjs +0 -30
  168. package/lib/modules/minifyUrls.cjs +0 -141
  169. package/lib/modules/minifyUrls.mjs +0 -229
  170. package/lib/modules/normalizeAttributeValues.cjs +0 -120
  171. package/lib/modules/normalizeAttributeValues.mjs +0 -140
  172. package/lib/modules/removeAttributeQuotes.cjs +0 -17
  173. package/lib/modules/removeAttributeQuotes.mjs +0 -12
  174. package/lib/modules/removeComments.cjs +0 -86
  175. package/lib/modules/removeEmptyAttributes.cjs +0 -72
  176. package/lib/modules/removeEmptyAttributes.mjs +0 -121
  177. package/lib/modules/removeOptionalTags.cjs +0 -183
  178. package/lib/modules/removeRedundantAttributes.cjs +0 -112
  179. package/lib/modules/removeUnusedCss.cjs +0 -113
  180. package/lib/modules/removeUnusedCss.mjs +0 -122
  181. package/lib/modules/sortAttributes.cjs +0 -99
  182. package/lib/modules/sortAttributesWithLists.cjs +0 -115
  183. package/lib/presets/ampSafe.cjs +0 -18
  184. package/lib/presets/max.cjs +0 -27
  185. package/lib/presets/safe.cjs +0 -65
  186. 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
- export const redundantScriptTypes = new Set([
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
- 'form': {
24
- 'method': 'get'
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
- 'script': {
37
- 'language': 'javascript',
38
- 'type': attrs => {
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
- return redundantScriptTypes.has(attrValue);
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
- 'charset': attrs => {
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
- 'style': {
58
- 'media': 'all',
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
- 'type': attrs => {
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
- 'loading': 'eager',
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
- 'loading': 'eager'
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
- /** Removes redundant attributes */
114
- export function onAttrs() {
115
- return (attrs, node) => {
116
- if (!node.tag) return attrs;
117
-
118
- const newAttrs = attrs;
119
-
120
- if (tagsHaveMissingValueDefaultAttributes.has(node.tag)) {
121
- const tagRedundantAttributes = missingValueDefaultAttributes[node.tag];
122
-
123
- for (const redundantAttributeName of Object.keys(tagRedundantAttributes)) {
124
- let tagRedundantAttributeValue = tagRedundantAttributes[redundantAttributeName];
125
- let isRemove = false;
126
-
127
- if (typeof tagRedundantAttributeValue === 'function') {
128
- isRemove = tagRedundantAttributeValue(attrs);
129
- } else if (attrs[redundantAttributeName] === tagRedundantAttributeValue) {
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
- return newAttrs;
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 };