htmlnano 2.1.2 → 2.1.4

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 (191) hide show
  1. package/README.md +54 -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.d.ts +16 -0
  95. package/dist/helpers.js +72 -0
  96. package/dist/helpers.mjs +63 -0
  97. package/dist/index.d.ts +79 -0
  98. package/dist/index.js +223 -0
  99. package/dist/index.mjs +209 -0
  100. package/dist/presets/ampSafe.d.ts +47 -0
  101. package/dist/presets/ampSafe.js +19 -0
  102. package/{lib → dist}/presets/ampSafe.mjs +6 -4
  103. package/dist/presets/max.d.ts +47 -0
  104. package/dist/presets/max.js +28 -0
  105. package/{lib → dist}/presets/max.mjs +6 -4
  106. package/dist/presets/safe.d.ts +47 -0
  107. package/dist/presets/safe.js +60 -0
  108. package/{lib → dist}/presets/safe.mjs +13 -20
  109. package/package.json +53 -56
  110. package/.eslintignore +0 -3
  111. package/CHANGELOG.md +0 -409
  112. package/docs/README.md +0 -33
  113. package/docs/babel.config.js +0 -3
  114. package/docs/docs/010-introduction.md +0 -22
  115. package/docs/docs/020-usage.md +0 -117
  116. package/docs/docs/030-config.md +0 -21
  117. package/docs/docs/040-presets.md +0 -75
  118. package/docs/docs/050-modules.md +0 -855
  119. package/docs/docs/060-contribute.md +0 -16
  120. package/docs/docusaurus.config.js +0 -65
  121. package/docs/netlify.toml +0 -4
  122. package/docs/package-lock.json +0 -21630
  123. package/docs/package.json +0 -40
  124. package/docs/sidebars.js +0 -26
  125. package/docs/versioned_docs/version-1.1.1/010-introduction.md +0 -22
  126. package/docs/versioned_docs/version-1.1.1/020-usage.md +0 -77
  127. package/docs/versioned_docs/version-1.1.1/030-config.md +0 -21
  128. package/docs/versioned_docs/version-1.1.1/040-presets.md +0 -75
  129. package/docs/versioned_docs/version-1.1.1/050-modules.md +0 -785
  130. package/docs/versioned_docs/version-1.1.1/060-contribute.md +0 -16
  131. package/docs/versioned_docs/version-2.0.0/010-introduction.md +0 -22
  132. package/docs/versioned_docs/version-2.0.0/020-usage.md +0 -77
  133. package/docs/versioned_docs/version-2.0.0/030-config.md +0 -21
  134. package/docs/versioned_docs/version-2.0.0/040-presets.md +0 -75
  135. package/docs/versioned_docs/version-2.0.0/050-modules.md +0 -838
  136. package/docs/versioned_docs/version-2.0.0/060-contribute.md +0 -16
  137. package/docs/versioned_sidebars/version-1.1.1-sidebars.json +0 -8
  138. package/docs/versioned_sidebars/version-2.0.0-sidebars.json +0 -8
  139. package/docs/versions.json +0 -4
  140. package/index.cjs +0 -11
  141. package/index.d.cts +0 -3
  142. package/index.d.mts +0 -3
  143. package/index.d.ts +0 -94
  144. package/index.mjs +0 -2
  145. package/lib/helpers.cjs +0 -79
  146. package/lib/helpers.mjs +0 -53
  147. package/lib/htmlnano.cjs +0 -202
  148. package/lib/htmlnano.mjs +0 -198
  149. package/lib/modules/collapseAttributeWhitespace.cjs +0 -86
  150. package/lib/modules/collapseAttributeWhitespace.mjs +0 -104
  151. package/lib/modules/collapseBooleanAttributes.cjs +0 -62
  152. package/lib/modules/collapseWhitespace.cjs +0 -100
  153. package/lib/modules/collapseWhitespace.mjs +0 -132
  154. package/lib/modules/custom.cjs +0 -19
  155. package/lib/modules/custom.mjs +0 -16
  156. package/lib/modules/deduplicateAttributeValues.cjs +0 -38
  157. package/lib/modules/deduplicateAttributeValues.mjs +0 -40
  158. package/lib/modules/example.cjs +0 -85
  159. package/lib/modules/example.mjs +0 -75
  160. package/lib/modules/mergeScripts.cjs +0 -54
  161. package/lib/modules/mergeScripts.mjs +0 -56
  162. package/lib/modules/mergeStyles.cjs +0 -38
  163. package/lib/modules/mergeStyles.mjs +0 -36
  164. package/lib/modules/minifyConditionalComments.cjs +0 -47
  165. package/lib/modules/minifyCss.cjs +0 -73
  166. package/lib/modules/minifyCss.mjs +0 -88
  167. package/lib/modules/minifyJs.cjs +0 -103
  168. package/lib/modules/minifyJs.mjs +0 -121
  169. package/lib/modules/minifyJson.cjs +0 -24
  170. package/lib/modules/minifyJson.mjs +0 -21
  171. package/lib/modules/minifySvg.cjs +0 -37
  172. package/lib/modules/minifySvg.mjs +0 -30
  173. package/lib/modules/minifyUrls.cjs +0 -141
  174. package/lib/modules/minifyUrls.mjs +0 -229
  175. package/lib/modules/normalizeAttributeValues.cjs +0 -120
  176. package/lib/modules/normalizeAttributeValues.mjs +0 -140
  177. package/lib/modules/removeAttributeQuotes.cjs +0 -17
  178. package/lib/modules/removeAttributeQuotes.mjs +0 -12
  179. package/lib/modules/removeComments.cjs +0 -86
  180. package/lib/modules/removeEmptyAttributes.cjs +0 -72
  181. package/lib/modules/removeEmptyAttributes.mjs +0 -121
  182. package/lib/modules/removeOptionalTags.cjs +0 -183
  183. package/lib/modules/removeRedundantAttributes.cjs +0 -112
  184. package/lib/modules/removeUnusedCss.cjs +0 -113
  185. package/lib/modules/removeUnusedCss.mjs +0 -122
  186. package/lib/modules/sortAttributes.cjs +0 -98
  187. package/lib/modules/sortAttributesWithLists.cjs +0 -114
  188. package/lib/presets/ampSafe.cjs +0 -18
  189. package/lib/presets/max.cjs +0 -27
  190. package/lib/presets/safe.cjs +0 -65
  191. package/test.js +0 -23
@@ -0,0 +1,195 @@
1
+ import { isEventHandler } from '../helpers.mjs';
2
+
3
+ const safeToRemoveAttrs = {
4
+ id: null,
5
+ class: null,
6
+ style: null,
7
+ title: null,
8
+ lang: null,
9
+ dir: null,
10
+ abbr: [
11
+ 'th'
12
+ ],
13
+ accept: [
14
+ 'input'
15
+ ],
16
+ 'accept-charset': [
17
+ 'form'
18
+ ],
19
+ charset: [
20
+ 'meta',
21
+ 'script'
22
+ ],
23
+ action: [
24
+ 'form'
25
+ ],
26
+ cols: [
27
+ 'textarea'
28
+ ],
29
+ colspan: [
30
+ 'td',
31
+ 'th'
32
+ ],
33
+ coords: [
34
+ 'area'
35
+ ],
36
+ dirname: [
37
+ 'input',
38
+ 'textarea'
39
+ ],
40
+ dropzone: null,
41
+ headers: [
42
+ 'td',
43
+ 'th'
44
+ ],
45
+ form: [
46
+ 'button',
47
+ 'fieldset',
48
+ 'input',
49
+ 'keygen',
50
+ 'object',
51
+ 'output',
52
+ 'select',
53
+ 'textarea'
54
+ ],
55
+ formaction: [
56
+ 'button',
57
+ 'input'
58
+ ],
59
+ height: [
60
+ 'canvas',
61
+ 'embed',
62
+ 'iframe',
63
+ 'img',
64
+ 'input',
65
+ 'object',
66
+ 'video'
67
+ ],
68
+ high: 'meter',
69
+ href: 'link',
70
+ list: 'input',
71
+ low: 'meter',
72
+ manifest: 'html',
73
+ max: [
74
+ 'meter',
75
+ 'progress'
76
+ ],
77
+ maxLength: [
78
+ 'input',
79
+ 'textarea'
80
+ ],
81
+ menu: 'button',
82
+ min: 'meter',
83
+ minLength: [
84
+ 'input',
85
+ 'textarea'
86
+ ],
87
+ name: [
88
+ 'button',
89
+ 'fieldset',
90
+ 'input',
91
+ 'keygen',
92
+ 'output',
93
+ 'select',
94
+ 'textarea',
95
+ 'form',
96
+ 'map',
97
+ 'meta',
98
+ 'param',
99
+ 'slot'
100
+ ],
101
+ pattern: [
102
+ 'input'
103
+ ],
104
+ ping: [
105
+ 'a',
106
+ 'area'
107
+ ],
108
+ placeholder: [
109
+ 'input',
110
+ 'textarea'
111
+ ],
112
+ poster: [
113
+ 'video'
114
+ ],
115
+ rel: [
116
+ 'a',
117
+ 'area',
118
+ 'link'
119
+ ],
120
+ rows: 'textarea',
121
+ rowspan: [
122
+ 'td',
123
+ 'th'
124
+ ],
125
+ size: [
126
+ 'input',
127
+ 'select'
128
+ ],
129
+ span: [
130
+ 'col',
131
+ 'colgroup'
132
+ ],
133
+ src: [
134
+ 'audio',
135
+ 'embed',
136
+ 'iframe',
137
+ 'img',
138
+ 'input',
139
+ 'script',
140
+ 'source',
141
+ 'track',
142
+ 'video'
143
+ ],
144
+ start: 'ol',
145
+ tabindex: null,
146
+ type: [
147
+ 'a',
148
+ 'link',
149
+ 'button',
150
+ 'embed',
151
+ 'object',
152
+ 'script',
153
+ 'source',
154
+ 'style',
155
+ 'input',
156
+ 'menu',
157
+ 'menuitem',
158
+ 'ol'
159
+ ],
160
+ value: [
161
+ 'button',
162
+ 'input',
163
+ 'li'
164
+ ],
165
+ width: [
166
+ 'canvas',
167
+ 'embed',
168
+ 'iframe',
169
+ 'img',
170
+ 'input',
171
+ 'object',
172
+ 'video'
173
+ ]
174
+ };
175
+ const mod = {
176
+ onAttrs () {
177
+ return (attrs, node)=>{
178
+ const newAttrs = {
179
+ ...attrs
180
+ };
181
+ Object.entries(attrs).forEach(([attrName, attrValue])=>{
182
+ if (isEventHandler(attrName) || Object.hasOwnProperty.call(safeToRemoveAttrs, attrName) && (safeToRemoveAttrs[attrName] === null || typeof node.tag === 'string' && safeToRemoveAttrs[attrName].includes(node.tag))) {
183
+ if (typeof attrValue === 'string') {
184
+ if (attrValue === '' || attrValue.trim() === '') {
185
+ delete newAttrs[attrName];
186
+ }
187
+ }
188
+ }
189
+ });
190
+ return newAttrs;
191
+ };
192
+ }
193
+ };
194
+
195
+ export { mod as default };
@@ -0,0 +1,56 @@
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
+ declare const mod: HtmlnanoModule;
55
+
56
+ export { mod as default };
@@ -0,0 +1,56 @@
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
+ declare const mod: HtmlnanoModule;
55
+
56
+ export { mod as default };
@@ -0,0 +1,190 @@
1
+ Object.defineProperty(exports, '__esModule', { value: true });
2
+
3
+ var helpers_js = require('../helpers.js');
4
+
5
+ const startWithWhitespacePattern = /^\s+/;
6
+ const bodyStartTagCantBeOmittedWithFirstChildTags = new Set([
7
+ 'meta',
8
+ 'link',
9
+ 'script',
10
+ 'style'
11
+ ]);
12
+ const tbodyStartTagCantBeOmittedWithPrecededTags = new Set([
13
+ 'tbody',
14
+ 'thead',
15
+ 'tfoot'
16
+ ]);
17
+ const tbodyEndTagCantBeOmittedWithFollowedTags = new Set([
18
+ 'tbody',
19
+ 'tfoot'
20
+ ]);
21
+ function isEmptyTextNode(node) {
22
+ if (typeof node === 'string' && node.trim() === '') {
23
+ return true;
24
+ }
25
+ return false;
26
+ }
27
+ function isEmptyNode(node) {
28
+ if (!node.content) {
29
+ return true;
30
+ }
31
+ if (node.content.length) {
32
+ return !node.content.filter((n)=>typeof n === 'string' && isEmptyTextNode(n) ? false : true).length;
33
+ }
34
+ return true;
35
+ }
36
+ function getFirstChildTag(node, nonEmpty = true) {
37
+ if (node.content && node.content.length) {
38
+ if (nonEmpty) {
39
+ for (const childNode of node.content){
40
+ if (typeof childNode !== 'string') return childNode;
41
+ if (!isEmptyTextNode(childNode)) return childNode;
42
+ }
43
+ } else {
44
+ return node.content[0] || null;
45
+ }
46
+ }
47
+ return null;
48
+ }
49
+ function getPrevNode(tree, currentNodeIndex, nonEmpty = false) {
50
+ if (nonEmpty) {
51
+ for(let i = currentNodeIndex - 1; i >= 0; i--){
52
+ const node = tree[i];
53
+ if (typeof node !== 'string' && node.tag) return node;
54
+ if (!isEmptyTextNode(node)) return node;
55
+ }
56
+ } else {
57
+ return tree[currentNodeIndex - 1] || null;
58
+ }
59
+ return null;
60
+ }
61
+ function getNextNode(tree, currentNodeIndex, nonEmpty = false) {
62
+ if (nonEmpty) {
63
+ for(let i = currentNodeIndex + 1; i < tree.length; i++){
64
+ const node = tree[i];
65
+ if (typeof node !== 'string') return node;
66
+ if (!isEmptyTextNode(node)) return node;
67
+ }
68
+ } else {
69
+ return tree[currentNodeIndex + 1] || null;
70
+ }
71
+ return null;
72
+ }
73
+ function removeOptionalTags(tree) {
74
+ tree.forEach((node, index)=>{
75
+ if (typeof node === 'string') return node;
76
+ if (!node.tag) return node;
77
+ if (node.attrs && Object.keys(node.attrs).length) return node;
78
+ // const prevNode = getPrevNode(tree, index);
79
+ const prevNonEmptyNode = getPrevNode(tree, index, true);
80
+ const nextNode = getNextNode(tree, index);
81
+ const nextNonEmptyNode = getNextNode(tree, index, true);
82
+ const firstChildNode = getFirstChildTag(node, false);
83
+ const firstNonEmptyChildNode = getFirstChildTag(node);
84
+ /**
85
+ * An "html" element's start tag may be omitted if the first thing inside the "html" element is not a comment.
86
+ * An "html" element's end tag may be omitted if the "html" element is not IMMEDIATELY followed by a comment.
87
+ */ if (node.tag === 'html') {
88
+ let isHtmlStartTagCanBeOmitted = true;
89
+ let isHtmlEndTagCanBeOmitted = true;
90
+ if (typeof firstNonEmptyChildNode === 'string' && helpers_js.isComment(firstNonEmptyChildNode)) {
91
+ isHtmlStartTagCanBeOmitted = false;
92
+ }
93
+ if (typeof nextNonEmptyNode === 'string' && helpers_js.isComment(nextNonEmptyNode)) {
94
+ isHtmlEndTagCanBeOmitted = false;
95
+ }
96
+ if (isHtmlStartTagCanBeOmitted && isHtmlEndTagCanBeOmitted) {
97
+ // @ts-expect-error -- deliberately set tag to false
98
+ node.tag = false;
99
+ }
100
+ }
101
+ /**
102
+ * A "head" element's start tag may be omitted if the element is empty, or if the first thing inside the "head" element is an element.
103
+ * A "head" element's end tag may be omitted if the "head" element is not IMMEDIATELY followed by ASCII whitespace or a comment.
104
+ */ if (node.tag === 'head') {
105
+ let isHeadStartTagCanBeOmitted = false;
106
+ let isHeadEndTagCanBeOmitted = true;
107
+ if (isEmptyNode(node) || firstNonEmptyChildNode && typeof firstNonEmptyChildNode === 'object' && firstNonEmptyChildNode.tag) {
108
+ isHeadStartTagCanBeOmitted = true;
109
+ }
110
+ if (nextNode && typeof nextNode === 'string' && startWithWhitespacePattern.test(nextNode) || nextNonEmptyNode && typeof nextNonEmptyNode === 'string' && helpers_js.isComment(nextNode)) {
111
+ isHeadEndTagCanBeOmitted = false;
112
+ }
113
+ if (isHeadStartTagCanBeOmitted && isHeadEndTagCanBeOmitted) {
114
+ // @ts-expect-error -- deliberately set tag to false
115
+ node.tag = false;
116
+ }
117
+ }
118
+ /**
119
+ * A "body" element's start tag may be omitted if the element is empty, or if the first thing inside the "body" element is not ASCII whitespace or a comment, except if the first thing inside the "body" element is a "meta", "link", "script", "style", or "template" element.
120
+ * A "body" element's end tag may be omitted if the "body" element is not IMMEDIATELY followed by a comment.
121
+ */ if (node.tag === 'body') {
122
+ let isBodyStartTagCanBeOmitted = true;
123
+ let isBodyEndTagCanBeOmitted = true;
124
+ if (typeof firstChildNode === 'string' && startWithWhitespacePattern.test(firstChildNode) || typeof firstNonEmptyChildNode === 'string' && helpers_js.isComment(firstNonEmptyChildNode)) {
125
+ isBodyStartTagCanBeOmitted = false;
126
+ }
127
+ if (firstNonEmptyChildNode && typeof firstNonEmptyChildNode === 'object' && firstNonEmptyChildNode.tag && bodyStartTagCantBeOmittedWithFirstChildTags.has(firstNonEmptyChildNode.tag)) {
128
+ isBodyStartTagCanBeOmitted = false;
129
+ }
130
+ if (nextNode && typeof nextNode === 'string' && helpers_js.isComment(nextNode)) {
131
+ isBodyEndTagCanBeOmitted = false;
132
+ }
133
+ if (isBodyStartTagCanBeOmitted && isBodyEndTagCanBeOmitted) {
134
+ // @ts-expect-error -- deliberately set tag to false
135
+ node.tag = false;
136
+ }
137
+ }
138
+ /**
139
+ * A "colgroup" element's start tag may be omitted if the first thing inside the "colgroup" element is a "col" element, and if the element is not IMMEDIATELY preceded by another "colgroup" element. It can't be omitted if the element is empty.
140
+ * A "colgroup" element's end tag may be omitted if the "colgroup" element is not IMMEDIATELY followed by ASCII whitespace or a comment.
141
+ */ if (node.tag === 'colgroup') {
142
+ let isColgroupStartTagCanBeOmitted = false;
143
+ let isColgroupEndTagCanBeOmitted = true;
144
+ if (firstNonEmptyChildNode && typeof firstNonEmptyChildNode === 'object' && firstNonEmptyChildNode.tag && firstNonEmptyChildNode.tag === 'col') {
145
+ isColgroupStartTagCanBeOmitted = true;
146
+ }
147
+ if (prevNonEmptyNode && typeof prevNonEmptyNode === 'object' && prevNonEmptyNode.tag && prevNonEmptyNode.tag === 'colgroup') {
148
+ isColgroupStartTagCanBeOmitted = false;
149
+ }
150
+ if (nextNode && typeof nextNode === 'string' && startWithWhitespacePattern.test(nextNode) || nextNonEmptyNode && typeof nextNonEmptyNode === 'string' && helpers_js.isComment(nextNonEmptyNode)) {
151
+ isColgroupEndTagCanBeOmitted = false;
152
+ }
153
+ if (isColgroupStartTagCanBeOmitted && isColgroupEndTagCanBeOmitted) {
154
+ // @ts-expect-error -- deliberately set tag to false
155
+ node.tag = false;
156
+ }
157
+ }
158
+ /**
159
+ * A "tbody" element's start tag may be omitted if the first thing inside the "tbody" element is a "tr" element, and if the element is not immediately preceded by another "tbody", "thead" or "tfoot" element. It can't be omitted if the element is empty.
160
+ * A "tbody" element's end tag may be omitted if the "tbody" element is not IMMEDIATELY followed by a "tbody" or "tfoot" element.
161
+ */ if (node.tag === 'tbody') {
162
+ let isTbodyStartTagCanBeOmitted = false;
163
+ let isTbodyEndTagCanBeOmitted = true;
164
+ if (firstNonEmptyChildNode && typeof firstNonEmptyChildNode === 'object' && firstNonEmptyChildNode.tag && firstNonEmptyChildNode.tag === 'tr') {
165
+ isTbodyStartTagCanBeOmitted = true;
166
+ }
167
+ if (prevNonEmptyNode && typeof prevNonEmptyNode === 'object' && prevNonEmptyNode.tag && tbodyStartTagCantBeOmittedWithPrecededTags.has(prevNonEmptyNode.tag)) {
168
+ isTbodyStartTagCanBeOmitted = false;
169
+ }
170
+ if (nextNonEmptyNode && typeof nextNonEmptyNode === 'object' && nextNonEmptyNode.tag && tbodyEndTagCantBeOmittedWithFollowedTags.has(nextNonEmptyNode.tag)) {
171
+ isTbodyEndTagCanBeOmitted = false;
172
+ }
173
+ if (isTbodyStartTagCanBeOmitted && isTbodyEndTagCanBeOmitted) {
174
+ // @ts-expect-error -- deliberately set tag to false
175
+ node.tag = false;
176
+ }
177
+ }
178
+ if (node.content && node.content.length) {
179
+ removeOptionalTags(node.content);
180
+ }
181
+ return node;
182
+ });
183
+ return tree;
184
+ }
185
+ // Specification https://html.spec.whatwg.org/multipage/syntax.html#optional-tags
186
+ /** Remove optional tag in the DOM */ const mod = {
187
+ default: removeOptionalTags
188
+ };
189
+
190
+ exports.default = mod;