htmlnano 2.1.2 → 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 -58
  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 -59
  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 +48 -56
  105. package/.eslintignore +0 -3
  106. package/CHANGELOG.md +0 -409
  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 -21630
  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 -94
  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 -202
  143. package/lib/htmlnano.mjs +0 -198
  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 -98
  182. package/lib/modules/sortAttributesWithLists.cjs +0 -114
  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 -23
@@ -0,0 +1,293 @@
1
+ import { isEventHandler } from '../helpers.mjs';
2
+
3
+ const attributesWithLists = new Set([
4
+ 'class',
5
+ 'dropzone',
6
+ 'rel',
7
+ 'ping',
8
+ 'sandbox',
9
+ /**
10
+ * https://github.com/posthtml/htmlnano/issues/180
11
+ * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link#attr-sizes
12
+ *
13
+ * "sizes" of <img> should not be modified, while "sizes" of <link> will only have one entry in most cases.
14
+ */ // 'sizes', // link
15
+ 'headers' // td, th
16
+ ]);
17
+ /** empty set means the attribute is alwasy trimmable */ const attributesWithSingleValue = new Map([
18
+ [
19
+ 'accept',
20
+ new Set([
21
+ 'input'
22
+ ])
23
+ ],
24
+ [
25
+ 'action',
26
+ new Set([
27
+ 'form'
28
+ ])
29
+ ],
30
+ [
31
+ 'accesskey',
32
+ new Set()
33
+ ],
34
+ [
35
+ 'accept-charset',
36
+ new Set([
37
+ 'form'
38
+ ])
39
+ ],
40
+ [
41
+ 'cite',
42
+ new Set([
43
+ 'blockquote',
44
+ 'del',
45
+ 'ins',
46
+ 'q'
47
+ ])
48
+ ],
49
+ [
50
+ 'cols',
51
+ new Set([
52
+ 'textarea'
53
+ ])
54
+ ],
55
+ [
56
+ 'colspan',
57
+ new Set([
58
+ 'td',
59
+ 'th'
60
+ ])
61
+ ],
62
+ [
63
+ 'data',
64
+ new Set([
65
+ 'object'
66
+ ])
67
+ ],
68
+ [
69
+ 'dropzone',
70
+ new Set()
71
+ ],
72
+ [
73
+ 'formaction',
74
+ new Set([
75
+ 'button',
76
+ 'input'
77
+ ])
78
+ ],
79
+ [
80
+ 'height',
81
+ new Set([
82
+ 'canvas',
83
+ 'embed',
84
+ 'iframe',
85
+ 'img',
86
+ 'input',
87
+ 'object',
88
+ 'video'
89
+ ])
90
+ ],
91
+ [
92
+ 'high',
93
+ new Set([
94
+ 'meter'
95
+ ])
96
+ ],
97
+ [
98
+ 'href',
99
+ new Set([
100
+ 'a',
101
+ 'area',
102
+ 'base',
103
+ 'link'
104
+ ])
105
+ ],
106
+ [
107
+ 'itemid',
108
+ new Set()
109
+ ],
110
+ [
111
+ 'low',
112
+ new Set([
113
+ 'meter'
114
+ ])
115
+ ],
116
+ [
117
+ 'manifest',
118
+ new Set([
119
+ 'html'
120
+ ])
121
+ ],
122
+ [
123
+ 'max',
124
+ new Set([
125
+ 'meter',
126
+ 'progress'
127
+ ])
128
+ ],
129
+ [
130
+ 'maxlength',
131
+ new Set([
132
+ 'input',
133
+ 'textarea'
134
+ ])
135
+ ],
136
+ [
137
+ 'media',
138
+ new Set([
139
+ 'source'
140
+ ])
141
+ ],
142
+ [
143
+ 'min',
144
+ new Set([
145
+ 'meter'
146
+ ])
147
+ ],
148
+ [
149
+ 'minlength',
150
+ new Set([
151
+ 'input',
152
+ 'textarea'
153
+ ])
154
+ ],
155
+ [
156
+ 'optimum',
157
+ new Set([
158
+ 'meter'
159
+ ])
160
+ ],
161
+ [
162
+ 'ping',
163
+ new Set([
164
+ 'a',
165
+ 'area'
166
+ ])
167
+ ],
168
+ [
169
+ 'poster',
170
+ new Set([
171
+ 'video'
172
+ ])
173
+ ],
174
+ [
175
+ 'profile',
176
+ new Set([
177
+ 'head'
178
+ ])
179
+ ],
180
+ [
181
+ 'rows',
182
+ new Set([
183
+ 'textarea'
184
+ ])
185
+ ],
186
+ [
187
+ 'rowspan',
188
+ new Set([
189
+ 'td',
190
+ 'th'
191
+ ])
192
+ ],
193
+ [
194
+ 'size',
195
+ new Set([
196
+ 'input',
197
+ 'select'
198
+ ])
199
+ ],
200
+ [
201
+ 'span',
202
+ new Set([
203
+ 'col',
204
+ 'colgroup'
205
+ ])
206
+ ],
207
+ [
208
+ 'src',
209
+ new Set([
210
+ 'audio',
211
+ 'embed',
212
+ 'iframe',
213
+ 'img',
214
+ 'input',
215
+ 'script',
216
+ 'source',
217
+ 'track',
218
+ 'video'
219
+ ])
220
+ ],
221
+ [
222
+ 'start',
223
+ new Set([
224
+ 'ol'
225
+ ])
226
+ ],
227
+ [
228
+ 'step',
229
+ new Set([
230
+ 'input'
231
+ ])
232
+ ],
233
+ [
234
+ 'style',
235
+ new Set()
236
+ ],
237
+ [
238
+ 'tabindex',
239
+ new Set()
240
+ ],
241
+ [
242
+ 'usemap',
243
+ new Set([
244
+ 'img',
245
+ 'object'
246
+ ])
247
+ ],
248
+ [
249
+ 'value',
250
+ new Set([
251
+ 'li',
252
+ 'meter',
253
+ 'progress'
254
+ ])
255
+ ],
256
+ [
257
+ 'width',
258
+ new Set([
259
+ 'canvas',
260
+ 'embed',
261
+ 'iframe',
262
+ 'img',
263
+ 'input',
264
+ 'object',
265
+ 'video'
266
+ ])
267
+ ]
268
+ ]);
269
+ /** Collapse whitespaces inside list-like attributes (e.g. class, rel) */ const mod = {
270
+ onAttrs () {
271
+ return (attrs, node)=>{
272
+ const newAttrs = attrs;
273
+ Object.entries(attrs).forEach(([attrName, attrValue])=>{
274
+ if (typeof attrValue !== 'string') return;
275
+ if (attributesWithLists.has(attrName)) {
276
+ newAttrs[attrName] = attrValue.replace(/\s+/g, ' ').trim();
277
+ return;
278
+ }
279
+ if (isEventHandler(attrName)) {
280
+ newAttrs[attrName] = attrValue.trim();
281
+ } else if (node.tag && attributesWithSingleValue.has(attrName)) {
282
+ const tagSet = attributesWithSingleValue.get(attrName);
283
+ if (tagSet.size === 0 || tagSet.has(node.tag)) {
284
+ newAttrs[attrName] = attrValue.trim();
285
+ }
286
+ }
287
+ });
288
+ return newAttrs;
289
+ };
290
+ }
291
+ };
292
+
293
+ export { attributesWithLists, mod as default };
@@ -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 CollapseBooleanAttributesOptions {
55
+ amphtml: boolean;
56
+ }
57
+ declare const mod: HtmlnanoModule<CollapseBooleanAttributesOptions>;
58
+
59
+ export { mod as default };
60
+ export type { CollapseBooleanAttributesOptions };
@@ -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 CollapseBooleanAttributesOptions {
55
+ amphtml: boolean;
56
+ }
57
+ declare const mod: HtmlnanoModule<CollapseBooleanAttributesOptions>;
58
+
59
+ export { mod as default };
60
+ export type { CollapseBooleanAttributesOptions };
@@ -0,0 +1,159 @@
1
+ Object.defineProperty(exports, '__esModule', { value: true });
2
+
3
+ // Source: https://github.com/kangax/html-minifier/issues/63
4
+ // https://html.spec.whatwg.org/#boolean-attribute
5
+ // https://html.spec.whatwg.org/#attributes-1
6
+ const htmlBooleanAttributes = new Set([
7
+ 'allowfullscreen',
8
+ 'allowpaymentrequest',
9
+ 'allowtransparency',
10
+ 'async',
11
+ 'autofocus',
12
+ 'autoplay',
13
+ 'checked',
14
+ 'compact',
15
+ 'controls',
16
+ 'declare',
17
+ 'default',
18
+ 'defaultchecked',
19
+ 'defaultmuted',
20
+ 'defaultselected',
21
+ 'defer',
22
+ 'disabled',
23
+ 'enabled',
24
+ 'formnovalidate',
25
+ 'hidden',
26
+ 'indeterminate',
27
+ 'inert',
28
+ 'ismap',
29
+ 'itemscope',
30
+ 'loop',
31
+ 'multiple',
32
+ 'muted',
33
+ 'nohref',
34
+ 'nomodule',
35
+ 'noresize',
36
+ 'noshade',
37
+ 'novalidate',
38
+ 'nowrap',
39
+ 'open',
40
+ 'pauseonexit',
41
+ 'playsinline',
42
+ 'readonly',
43
+ 'required',
44
+ 'reversed',
45
+ 'scoped',
46
+ 'seamless',
47
+ 'selected',
48
+ 'sortable',
49
+ 'truespeed',
50
+ 'typemustmatch',
51
+ 'visible'
52
+ ]);
53
+ const amphtmlBooleanAttributes = new Set([
54
+ '⚡',
55
+ 'amp',
56
+ '⚡4ads',
57
+ 'amp4ads',
58
+ '⚡4email',
59
+ 'amp4email',
60
+ 'amp-custom',
61
+ 'amp-boilerplate',
62
+ 'amp4ads-boilerplate',
63
+ 'amp4email-boilerplate',
64
+ 'allow-blocked-ranges',
65
+ 'amp-access-hide',
66
+ 'amp-access-template',
67
+ 'amp-keyframes',
68
+ 'animate',
69
+ 'arrows',
70
+ 'data-block-on-consent',
71
+ 'data-enable-refresh',
72
+ 'data-multi-size',
73
+ 'date-template',
74
+ 'disable-double-tap',
75
+ 'disable-session-states',
76
+ 'disableremoteplayback',
77
+ 'dots',
78
+ 'expand-single-section',
79
+ 'expanded',
80
+ 'fallback',
81
+ 'first',
82
+ 'fullscreen',
83
+ 'inline',
84
+ 'lightbox',
85
+ 'noaudio',
86
+ 'noautoplay',
87
+ 'noloading',
88
+ 'once',
89
+ 'open-after-clear',
90
+ 'open-after-select',
91
+ 'open-button',
92
+ 'placeholder',
93
+ 'preload',
94
+ 'reset-on-refresh',
95
+ 'reset-on-resize',
96
+ 'resizable',
97
+ 'rotate-to-fullscreen',
98
+ 'second',
99
+ 'standalone',
100
+ 'stereo',
101
+ 'submit-error',
102
+ 'submit-success',
103
+ 'submitting',
104
+ 'subscriptions-actions',
105
+ 'subscriptions-dialog'
106
+ ]);
107
+ const missingValueDefaultEmptyStringAttributes = {
108
+ // https://html.spec.whatwg.org/#attr-media-preload
109
+ audio: {
110
+ preload: 'auto'
111
+ },
112
+ video: {
113
+ preload: 'auto'
114
+ }
115
+ };
116
+ const tagsHasMissingValueDefaultEmptyStringAttributes = new Set(Object.keys(missingValueDefaultEmptyStringAttributes));
117
+ const mod = {
118
+ onAttrs (options, moduleOptions) {
119
+ return (attrs, node)=>{
120
+ if (!node.tag) return attrs;
121
+ const newAttrs = attrs;
122
+ if (tagsHasMissingValueDefaultEmptyStringAttributes.has(node.tag)) {
123
+ const tagAttributesCanBeReplacedWithEmptyString = missingValueDefaultEmptyStringAttributes[node.tag];
124
+ for (const attributesCanBeReplacedWithEmptyString of Object.keys(tagAttributesCanBeReplacedWithEmptyString)){
125
+ if (attributesCanBeReplacedWithEmptyString in attrs && attributesCanBeReplacedWithEmptyString in tagAttributesCanBeReplacedWithEmptyString && attrs[attributesCanBeReplacedWithEmptyString] === tagAttributesCanBeReplacedWithEmptyString[attributesCanBeReplacedWithEmptyString]) {
126
+ attrs[attributesCanBeReplacedWithEmptyString] = true;
127
+ }
128
+ }
129
+ }
130
+ for (const attrName of Object.keys(attrs)){
131
+ if (attrName === 'visible' && node.tag.startsWith('a-')) {
132
+ continue;
133
+ }
134
+ if (htmlBooleanAttributes.has(attrName)) {
135
+ newAttrs[attrName] = true;
136
+ }
137
+ // Fast path optimization.
138
+ // The rest of tranformations are only for string type attrValue.
139
+ if (typeof newAttrs[attrName] !== 'string') continue;
140
+ if (moduleOptions.amphtml && amphtmlBooleanAttributes.has(attrName) && attrs[attrName] === '') {
141
+ newAttrs[attrName] = true;
142
+ }
143
+ // https://html.spec.whatwg.org/#a-quick-introduction-to-html
144
+ // The value, along with the "=" character, can be omitted altogether if the value is the empty string.
145
+ if (attrs[attrName] === '') {
146
+ newAttrs[attrName] = true;
147
+ }
148
+ // collapse crossorigin attributes
149
+ // Specification: https://html.spec.whatwg.org/multipage/urls-and-fetching.html#cors-settings-attributes
150
+ if (attrName.toLowerCase() === 'crossorigin' && attrs[attrName] === 'anonymous') {
151
+ newAttrs[attrName] = true;
152
+ }
153
+ }
154
+ return newAttrs;
155
+ };
156
+ }
157
+ };
158
+
159
+ exports.default = mod;