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
@@ -0,0 +1,72 @@
1
+ Object.defineProperty(exports, '__esModule', { value: true });
2
+
3
+ const ampBoilerplateAttributes = [
4
+ 'amp-boilerplate',
5
+ 'amp4ads-boilerplate',
6
+ 'amp4email-boilerplate'
7
+ ];
8
+ function isAmpBoilerplate(node) {
9
+ if (!node.attrs) {
10
+ return false;
11
+ }
12
+ for (const attr of ampBoilerplateAttributes){
13
+ if (attr in node.attrs) {
14
+ return true;
15
+ }
16
+ }
17
+ return false;
18
+ }
19
+ function isComment(content) {
20
+ if (typeof content === 'string') {
21
+ return content.trim().startsWith('<!--');
22
+ }
23
+ return false;
24
+ }
25
+ function isConditionalComment(content) {
26
+ const clean = (content || '').trim();
27
+ return clean.startsWith('<!--[if') || clean === '<!--<![endif]-->';
28
+ }
29
+ function isStyleNode(node) {
30
+ return node.tag === 'style' && !isAmpBoilerplate(node) && 'content' in node && node.content && node.content.length > 0;
31
+ }
32
+ function extractCssFromStyleNode(node) {
33
+ return Array.isArray(node.content) ? node.content.join(' ') : node.content;
34
+ }
35
+ function isEventHandler(attributeName) {
36
+ return attributeName && attributeName.slice(0, 2).toLowerCase() === 'on' && attributeName.length >= 5;
37
+ }
38
+ function extractTextContentFromNode(node) {
39
+ if (!node.content) {
40
+ return '';
41
+ }
42
+ if (!Array.isArray(node.content)) {
43
+ return '';
44
+ }
45
+ let content = '';
46
+ for (const child of node.content){
47
+ if (typeof child === 'string') {
48
+ content += child;
49
+ }
50
+ }
51
+ return content;
52
+ }
53
+ async function optionalImport(moduleName) {
54
+ try {
55
+ const module = await import(moduleName);
56
+ return module.default || module;
57
+ } catch (e) {
58
+ if (typeof e === 'object' && e && 'code' in e && (e.code === 'MODULE_NOT_FOUND' || e.code === 'ERR_MODULE_NOT_FOUND')) {
59
+ return null;
60
+ }
61
+ throw e;
62
+ }
63
+ }
64
+
65
+ exports.extractCssFromStyleNode = extractCssFromStyleNode;
66
+ exports.extractTextContentFromNode = extractTextContentFromNode;
67
+ exports.isAmpBoilerplate = isAmpBoilerplate;
68
+ exports.isComment = isComment;
69
+ exports.isConditionalComment = isConditionalComment;
70
+ exports.isEventHandler = isEventHandler;
71
+ exports.isStyleNode = isStyleNode;
72
+ exports.optionalImport = optionalImport;
@@ -0,0 +1,63 @@
1
+ const ampBoilerplateAttributes = [
2
+ 'amp-boilerplate',
3
+ 'amp4ads-boilerplate',
4
+ 'amp4email-boilerplate'
5
+ ];
6
+ function isAmpBoilerplate(node) {
7
+ if (!node.attrs) {
8
+ return false;
9
+ }
10
+ for (const attr of ampBoilerplateAttributes){
11
+ if (attr in node.attrs) {
12
+ return true;
13
+ }
14
+ }
15
+ return false;
16
+ }
17
+ function isComment(content) {
18
+ if (typeof content === 'string') {
19
+ return content.trim().startsWith('<!--');
20
+ }
21
+ return false;
22
+ }
23
+ function isConditionalComment(content) {
24
+ const clean = (content || '').trim();
25
+ return clean.startsWith('<!--[if') || clean === '<!--<![endif]-->';
26
+ }
27
+ function isStyleNode(node) {
28
+ return node.tag === 'style' && !isAmpBoilerplate(node) && 'content' in node && node.content && node.content.length > 0;
29
+ }
30
+ function extractCssFromStyleNode(node) {
31
+ return Array.isArray(node.content) ? node.content.join(' ') : node.content;
32
+ }
33
+ function isEventHandler(attributeName) {
34
+ return attributeName && attributeName.slice(0, 2).toLowerCase() === 'on' && attributeName.length >= 5;
35
+ }
36
+ function extractTextContentFromNode(node) {
37
+ if (!node.content) {
38
+ return '';
39
+ }
40
+ if (!Array.isArray(node.content)) {
41
+ return '';
42
+ }
43
+ let content = '';
44
+ for (const child of node.content){
45
+ if (typeof child === 'string') {
46
+ content += child;
47
+ }
48
+ }
49
+ return content;
50
+ }
51
+ async function optionalImport(moduleName) {
52
+ try {
53
+ const module = await import(moduleName);
54
+ return module.default || module;
55
+ } catch (e) {
56
+ if (typeof e === 'object' && e && 'code' in e && (e.code === 'MODULE_NOT_FOUND' || e.code === 'ERR_MODULE_NOT_FOUND')) {
57
+ return null;
58
+ }
59
+ throw e;
60
+ }
61
+ }
62
+
63
+ export { extractCssFromStyleNode, extractTextContentFromNode, isAmpBoilerplate, isComment, isConditionalComment, isEventHandler, isStyleNode, optionalImport };
package/dist/index.js ADDED
@@ -0,0 +1,223 @@
1
+ Object.defineProperty(exports, '__esModule', { value: true });
2
+
3
+ var posthtml = require('posthtml');
4
+ var cosmiconfig = require('cosmiconfig');
5
+ var safePreset = require('./presets/safe.js');
6
+ var ampSafePreset = require('./presets/ampSafe.js');
7
+ var maxPreset = require('./presets/max.js');
8
+
9
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
+
11
+ var posthtml__default = /*#__PURE__*/_interopDefault(posthtml);
12
+ var safePreset__default = /*#__PURE__*/_interopDefault(safePreset);
13
+ var ampSafePreset__default = /*#__PURE__*/_interopDefault(ampSafePreset);
14
+ var maxPreset__default = /*#__PURE__*/_interopDefault(maxPreset);
15
+
16
+ const presets = {
17
+ safe: safePreset__default.default,
18
+ ampSafe: ampSafePreset__default.default,
19
+ max: maxPreset__default.default
20
+ };
21
+ function loadConfig(options, preset, configPath) {
22
+ const { skipConfigLoading = false, ...rest } = options || {};
23
+ let restConfig = rest;
24
+ if (!skipConfigLoading) {
25
+ const explorer = cosmiconfig.cosmiconfigSync('htmlnano');
26
+ const rc = configPath ? explorer.load(configPath) : explorer.search();
27
+ if (rc) {
28
+ const { preset: presetName } = rc.config;
29
+ if (presetName) {
30
+ if (!preset && presetName in presets) {
31
+ preset = presets[presetName];
32
+ }
33
+ delete rc.config.preset;
34
+ }
35
+ if (!options) {
36
+ restConfig = rc.config;
37
+ }
38
+ }
39
+ }
40
+ return [
41
+ restConfig || {},
42
+ preset || safePreset__default.default
43
+ ];
44
+ }
45
+ const optionalDependencies = {
46
+ minifyCss: [
47
+ 'cssnano',
48
+ 'postcss'
49
+ ],
50
+ minifyJs: [
51
+ 'terser'
52
+ ],
53
+ minifyUrls: [
54
+ 'relateurl',
55
+ 'srcset',
56
+ 'terser'
57
+ ],
58
+ minifySvg: [
59
+ 'svgo'
60
+ ]
61
+ };
62
+ const interop = (imported)=>imported.then((mod)=>mod.default);
63
+ const modules = {
64
+ collapseAttributeWhitespace: ()=>interop(import('./_modules/collapseAttributeWhitespace.js')),
65
+ collapseBooleanAttributes: ()=>interop(import('./_modules/collapseBooleanAttributes.js')),
66
+ collapseWhitespace: ()=>interop(import('./_modules/collapseWhitespace.js')),
67
+ custom: ()=>interop(import('./_modules/custom.js')),
68
+ deduplicateAttributeValues: ()=>interop(import('./_modules/deduplicateAttributeValues.js')),
69
+ // example: () => import('./_modules/example.mjs'),
70
+ mergeScripts: ()=>interop(import('./_modules/mergeScripts.js')),
71
+ mergeStyles: ()=>interop(import('./_modules/mergeStyles.js')),
72
+ minifyConditionalComments: ()=>interop(import('./_modules/minifyConditionalComments.js')),
73
+ minifyCss: ()=>interop(import('./_modules/minifyCss.js')),
74
+ minifyJs: ()=>interop(import('./_modules/minifyJs.js')),
75
+ minifyJson: ()=>interop(import('./_modules/minifyJson.js')),
76
+ minifySvg: ()=>interop(import('./_modules/minifySvg.js')),
77
+ minifyUrls: ()=>interop(import('./_modules/minifyUrls.js')),
78
+ normalizeAttributeValues: ()=>interop(import('./_modules/normalizeAttributeValues.js')),
79
+ removeAttributeQuotes: ()=>interop(import('./_modules/removeAttributeQuotes.js')),
80
+ removeComments: ()=>interop(import('./_modules/removeComments.js')),
81
+ removeEmptyAttributes: ()=>interop(import('./_modules/removeEmptyAttributes.js')),
82
+ removeOptionalTags: ()=>interop(import('./_modules/removeOptionalTags.js')),
83
+ removeRedundantAttributes: ()=>interop(import('./_modules/removeRedundantAttributes.js')),
84
+ removeUnusedCss: ()=>interop(import('./_modules/removeUnusedCss.js')),
85
+ sortAttributes: ()=>interop(import('./_modules/sortAttributes.js')),
86
+ sortAttributesWithLists: ()=>interop(import('./_modules/sortAttributesWithLists.js'))
87
+ };
88
+ function htmlnano(optionsRun = {}, presetRun) {
89
+ // eslint-disable-next-line prefer-const -- re-assign options
90
+ let [options, preset] = loadConfig(optionsRun, presetRun);
91
+ const minifier = async (_tree)=>{
92
+ const tree = _tree;
93
+ const nodeHandlers = [];
94
+ const attrsHandlers = [];
95
+ const contentsHandlers = [];
96
+ options = {
97
+ ...preset,
98
+ ...options
99
+ };
100
+ let promise = Promise.resolve(tree);
101
+ for (const [moduleName, moduleOptions] of Object.entries(options)){
102
+ if (!moduleOptions) {
103
+ continue;
104
+ }
105
+ if (!(moduleName in safePreset__default.default)) {
106
+ throw new Error('Module "' + moduleName + '" is not defined');
107
+ }
108
+ if (moduleName in optionalDependencies) {
109
+ const modules = optionalDependencies[moduleName];
110
+ await Promise.all(modules.map(async (dependency)=>{
111
+ try {
112
+ await import(dependency);
113
+ } catch (e) {
114
+ if (typeof e === 'object' && e !== null && 'code' in e && typeof e.code === 'string') {
115
+ if (e.code === 'MODULE_NOT_FOUND' || e.code === 'ERR_MODULE_NOT_FOUND') {
116
+ if (!options.skipInternalWarnings) {
117
+ console.warn(`You have to install "${dependency}" in order to use htmlnano's "${moduleName}" module`);
118
+ return;
119
+ }
120
+ }
121
+ throw e;
122
+ }
123
+ }
124
+ }));
125
+ }
126
+ const mod = moduleName in modules ? await modules[moduleName]() : await import(`./_modules/${moduleName}.mjs`);
127
+ if (typeof mod.onAttrs === 'function') {
128
+ attrsHandlers.push(mod.onAttrs(options, moduleOptions));
129
+ }
130
+ if (typeof mod.onContent === 'function') {
131
+ contentsHandlers.push(mod.onContent(options, moduleOptions));
132
+ }
133
+ if (typeof mod.onNode === 'function') {
134
+ nodeHandlers.push(mod.onNode(options, moduleOptions));
135
+ }
136
+ if (typeof mod.default === 'function') {
137
+ promise = promise.then(async (tree)=>await mod.default(tree, options, moduleOptions));
138
+ }
139
+ }
140
+ if (attrsHandlers.length + contentsHandlers.length + nodeHandlers.length === 0) {
141
+ return promise;
142
+ }
143
+ return promise.then((tree)=>{
144
+ tree.walk((node)=>{
145
+ if (node) {
146
+ if (node.attrs && typeof node.attrs === 'object') {
147
+ // Convert all attrs' key to lower case
148
+ let newAttrsObj = {};
149
+ Object.entries(node.attrs).forEach(([attrName, attrValue])=>{
150
+ newAttrsObj[attrName.toLowerCase()] = attrValue;
151
+ });
152
+ for (const handler of attrsHandlers){
153
+ newAttrsObj = handler(newAttrsObj, node);
154
+ }
155
+ node.attrs = newAttrsObj;
156
+ }
157
+ if (node.content) {
158
+ node.content = typeof node.content === 'string' ? [
159
+ node.content
160
+ ] : node.content;
161
+ if (Array.isArray(node.content) && node.content.length > 0) {
162
+ for (const handler of contentsHandlers){
163
+ var _node_content;
164
+ const result = handler((_node_content = node.content) != null ? _node_content : [], node);
165
+ node.content = Array.isArray(result) ? result : [
166
+ result
167
+ ];
168
+ }
169
+ }
170
+ }
171
+ for (const handler of nodeHandlers){
172
+ if (handler) {
173
+ node = handler(node);
174
+ }
175
+ }
176
+ }
177
+ return node;
178
+ });
179
+ return tree;
180
+ });
181
+ };
182
+ return minifier;
183
+ }
184
+ function getRequiredOptionalDependencies(optionsRun, presetRun) {
185
+ const [options] = loadConfig(optionsRun, presetRun);
186
+ return Array.from(Object.keys(options).reduce((acc, moduleName)=>{
187
+ if (moduleName in optionalDependencies) {
188
+ const dependencies = optionalDependencies[moduleName];
189
+ // eslint-disable-next-line @typescript-eslint/unbound-method -- thisArg provided by forEach
190
+ dependencies.forEach(acc.add, acc);
191
+ }
192
+ return acc;
193
+ }, new Set()));
194
+ }
195
+ function process(html, options, preset, postHtmlOptions) {
196
+ return posthtml__default.default([
197
+ htmlnano(options, preset)
198
+ ]).process(html, postHtmlOptions);
199
+ }
200
+ // https://github.com/webpack-contrib/html-minimizer-webpack-plugin/blob/faca00f2219514bc671c5942685721f0b5dbaa70/src/utils.js#L74
201
+ function htmlMinimizerWebpackPluginMinify(input, minimizerOptions) {
202
+ const [[, code]] = Object.entries(input);
203
+ return htmlnano.process(code, minimizerOptions, presets.safe).then((result)=>{
204
+ return {
205
+ code: result.html
206
+ };
207
+ });
208
+ }
209
+ htmlnano.presets = presets;
210
+ htmlnano.getRequiredOptionalDependencies = getRequiredOptionalDependencies;
211
+ htmlnano.process = process;
212
+ htmlnano.htmlMinimizerWebpackPluginMinify = htmlMinimizerWebpackPluginMinify;
213
+ htmlnano.loadConfig = loadConfig;
214
+ if (typeof module !== 'undefined') {
215
+ module.exports = htmlnano;
216
+ }
217
+
218
+ exports.default = htmlnano;
219
+ exports.getRequiredOptionalDependencies = getRequiredOptionalDependencies;
220
+ exports.htmlMinimizerWebpackPluginMinify = htmlMinimizerWebpackPluginMinify;
221
+ exports.htmlnano = htmlnano;
222
+ exports.loadConfig = loadConfig;
223
+ exports.process = process;
package/dist/index.mjs ADDED
@@ -0,0 +1,209 @@
1
+ import posthtml from 'posthtml';
2
+ import { cosmiconfigSync } from 'cosmiconfig';
3
+ import safePreset from './presets/safe.mjs';
4
+ import ampSafePreset from './presets/ampSafe.mjs';
5
+ import maxPreset from './presets/max.mjs';
6
+
7
+ const presets = {
8
+ safe: safePreset,
9
+ ampSafe: ampSafePreset,
10
+ max: maxPreset
11
+ };
12
+ function loadConfig(options, preset, configPath) {
13
+ const { skipConfigLoading = false, ...rest } = options || {};
14
+ let restConfig = rest;
15
+ if (!skipConfigLoading) {
16
+ const explorer = cosmiconfigSync('htmlnano');
17
+ const rc = configPath ? explorer.load(configPath) : explorer.search();
18
+ if (rc) {
19
+ const { preset: presetName } = rc.config;
20
+ if (presetName) {
21
+ if (!preset && presetName in presets) {
22
+ preset = presets[presetName];
23
+ }
24
+ delete rc.config.preset;
25
+ }
26
+ if (!options) {
27
+ restConfig = rc.config;
28
+ }
29
+ }
30
+ }
31
+ return [
32
+ restConfig || {},
33
+ preset || safePreset
34
+ ];
35
+ }
36
+ const optionalDependencies = {
37
+ minifyCss: [
38
+ 'cssnano',
39
+ 'postcss'
40
+ ],
41
+ minifyJs: [
42
+ 'terser'
43
+ ],
44
+ minifyUrls: [
45
+ 'relateurl',
46
+ 'srcset',
47
+ 'terser'
48
+ ],
49
+ minifySvg: [
50
+ 'svgo'
51
+ ]
52
+ };
53
+ const interop = (imported)=>imported.then((mod)=>mod.default);
54
+ const modules = {
55
+ collapseAttributeWhitespace: ()=>interop(import('./_modules/collapseAttributeWhitespace.mjs')),
56
+ collapseBooleanAttributes: ()=>interop(import('./_modules/collapseBooleanAttributes.mjs')),
57
+ collapseWhitespace: ()=>interop(import('./_modules/collapseWhitespace.mjs')),
58
+ custom: ()=>interop(import('./_modules/custom.mjs')),
59
+ deduplicateAttributeValues: ()=>interop(import('./_modules/deduplicateAttributeValues.mjs')),
60
+ // example: () => import('./_modules/example.mjs'),
61
+ mergeScripts: ()=>interop(import('./_modules/mergeScripts.mjs')),
62
+ mergeStyles: ()=>interop(import('./_modules/mergeStyles.mjs')),
63
+ minifyConditionalComments: ()=>interop(import('./_modules/minifyConditionalComments.mjs')),
64
+ minifyCss: ()=>interop(import('./_modules/minifyCss.mjs')),
65
+ minifyJs: ()=>interop(import('./_modules/minifyJs.mjs')),
66
+ minifyJson: ()=>interop(import('./_modules/minifyJson.mjs')),
67
+ minifySvg: ()=>interop(import('./_modules/minifySvg.mjs')),
68
+ minifyUrls: ()=>interop(import('./_modules/minifyUrls.mjs')),
69
+ normalizeAttributeValues: ()=>interop(import('./_modules/normalizeAttributeValues.mjs')),
70
+ removeAttributeQuotes: ()=>interop(import('./_modules/removeAttributeQuotes.mjs')),
71
+ removeComments: ()=>interop(import('./_modules/removeComments.mjs')),
72
+ removeEmptyAttributes: ()=>interop(import('./_modules/removeEmptyAttributes.mjs')),
73
+ removeOptionalTags: ()=>interop(import('./_modules/removeOptionalTags.mjs')),
74
+ removeRedundantAttributes: ()=>interop(import('./_modules/removeRedundantAttributes.mjs')),
75
+ removeUnusedCss: ()=>interop(import('./_modules/removeUnusedCss.mjs')),
76
+ sortAttributes: ()=>interop(import('./_modules/sortAttributes.mjs')),
77
+ sortAttributesWithLists: ()=>interop(import('./_modules/sortAttributesWithLists.mjs'))
78
+ };
79
+ function htmlnano(optionsRun = {}, presetRun) {
80
+ // eslint-disable-next-line prefer-const -- re-assign options
81
+ let [options, preset] = loadConfig(optionsRun, presetRun);
82
+ const minifier = async (_tree)=>{
83
+ const tree = _tree;
84
+ const nodeHandlers = [];
85
+ const attrsHandlers = [];
86
+ const contentsHandlers = [];
87
+ options = {
88
+ ...preset,
89
+ ...options
90
+ };
91
+ let promise = Promise.resolve(tree);
92
+ for (const [moduleName, moduleOptions] of Object.entries(options)){
93
+ if (!moduleOptions) {
94
+ continue;
95
+ }
96
+ if (!(moduleName in safePreset)) {
97
+ throw new Error('Module "' + moduleName + '" is not defined');
98
+ }
99
+ if (moduleName in optionalDependencies) {
100
+ const modules = optionalDependencies[moduleName];
101
+ await Promise.all(modules.map(async (dependency)=>{
102
+ try {
103
+ await import(dependency);
104
+ } catch (e) {
105
+ if (typeof e === 'object' && e !== null && 'code' in e && typeof e.code === 'string') {
106
+ if (e.code === 'MODULE_NOT_FOUND' || e.code === 'ERR_MODULE_NOT_FOUND') {
107
+ if (!options.skipInternalWarnings) {
108
+ console.warn(`You have to install "${dependency}" in order to use htmlnano's "${moduleName}" module`);
109
+ return;
110
+ }
111
+ }
112
+ throw e;
113
+ }
114
+ }
115
+ }));
116
+ }
117
+ const mod = moduleName in modules ? await modules[moduleName]() : await import(`./_modules/${moduleName}.mjs`);
118
+ if (typeof mod.onAttrs === 'function') {
119
+ attrsHandlers.push(mod.onAttrs(options, moduleOptions));
120
+ }
121
+ if (typeof mod.onContent === 'function') {
122
+ contentsHandlers.push(mod.onContent(options, moduleOptions));
123
+ }
124
+ if (typeof mod.onNode === 'function') {
125
+ nodeHandlers.push(mod.onNode(options, moduleOptions));
126
+ }
127
+ if (typeof mod.default === 'function') {
128
+ promise = promise.then(async (tree)=>await mod.default(tree, options, moduleOptions));
129
+ }
130
+ }
131
+ if (attrsHandlers.length + contentsHandlers.length + nodeHandlers.length === 0) {
132
+ return promise;
133
+ }
134
+ return promise.then((tree)=>{
135
+ tree.walk((node)=>{
136
+ if (node) {
137
+ if (node.attrs && typeof node.attrs === 'object') {
138
+ // Convert all attrs' key to lower case
139
+ let newAttrsObj = {};
140
+ Object.entries(node.attrs).forEach(([attrName, attrValue])=>{
141
+ newAttrsObj[attrName.toLowerCase()] = attrValue;
142
+ });
143
+ for (const handler of attrsHandlers){
144
+ newAttrsObj = handler(newAttrsObj, node);
145
+ }
146
+ node.attrs = newAttrsObj;
147
+ }
148
+ if (node.content) {
149
+ node.content = typeof node.content === 'string' ? [
150
+ node.content
151
+ ] : node.content;
152
+ if (Array.isArray(node.content) && node.content.length > 0) {
153
+ for (const handler of contentsHandlers){
154
+ var _node_content;
155
+ const result = handler((_node_content = node.content) != null ? _node_content : [], node);
156
+ node.content = Array.isArray(result) ? result : [
157
+ result
158
+ ];
159
+ }
160
+ }
161
+ }
162
+ for (const handler of nodeHandlers){
163
+ if (handler) {
164
+ node = handler(node);
165
+ }
166
+ }
167
+ }
168
+ return node;
169
+ });
170
+ return tree;
171
+ });
172
+ };
173
+ return minifier;
174
+ }
175
+ function getRequiredOptionalDependencies(optionsRun, presetRun) {
176
+ const [options] = loadConfig(optionsRun, presetRun);
177
+ return Array.from(Object.keys(options).reduce((acc, moduleName)=>{
178
+ if (moduleName in optionalDependencies) {
179
+ const dependencies = optionalDependencies[moduleName];
180
+ // eslint-disable-next-line @typescript-eslint/unbound-method -- thisArg provided by forEach
181
+ dependencies.forEach(acc.add, acc);
182
+ }
183
+ return acc;
184
+ }, new Set()));
185
+ }
186
+ function process(html, options, preset, postHtmlOptions) {
187
+ return posthtml([
188
+ htmlnano(options, preset)
189
+ ]).process(html, postHtmlOptions);
190
+ }
191
+ // https://github.com/webpack-contrib/html-minimizer-webpack-plugin/blob/faca00f2219514bc671c5942685721f0b5dbaa70/src/utils.js#L74
192
+ function htmlMinimizerWebpackPluginMinify(input, minimizerOptions) {
193
+ const [[, code]] = Object.entries(input);
194
+ return htmlnano.process(code, minimizerOptions, presets.safe).then((result)=>{
195
+ return {
196
+ code: result.html
197
+ };
198
+ });
199
+ }
200
+ htmlnano.presets = presets;
201
+ htmlnano.getRequiredOptionalDependencies = getRequiredOptionalDependencies;
202
+ htmlnano.process = process;
203
+ htmlnano.htmlMinimizerWebpackPluginMinify = htmlMinimizerWebpackPluginMinify;
204
+ htmlnano.loadConfig = loadConfig;
205
+ if (typeof module !== 'undefined') {
206
+ module.exports = htmlnano;
207
+ }
208
+
209
+ export { htmlnano as default, getRequiredOptionalDependencies, htmlMinimizerWebpackPluginMinify, htmlnano, loadConfig, process };
@@ -0,0 +1,19 @@
1
+ Object.defineProperty(exports, '__esModule', { value: true });
2
+
3
+ var safePreset = require('./safe.js');
4
+
5
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
6
+
7
+ var safePreset__default = /*#__PURE__*/_interopDefault(safePreset);
8
+
9
+ /**
10
+ * A safe preset for AMP pages (https://www.ampproject.org)
11
+ */ var ampSafe = {
12
+ ...safePreset__default.default,
13
+ collapseBooleanAttributes: {
14
+ amphtml: true
15
+ },
16
+ minifyJs: false
17
+ };
18
+
19
+ exports.default = ampSafe;
@@ -2,10 +2,12 @@ import safePreset from './safe.mjs';
2
2
 
3
3
  /**
4
4
  * A safe preset for AMP pages (https://www.ampproject.org)
5
- */
6
- export default { ...safePreset,
5
+ */ var ampSafe = {
6
+ ...safePreset,
7
7
  collapseBooleanAttributes: {
8
- amphtml: true,
8
+ amphtml: true
9
9
  },
10
- minifyJs: false,
10
+ minifyJs: false
11
11
  };
12
+
13
+ export { ampSafe as default };
@@ -0,0 +1,28 @@
1
+ Object.defineProperty(exports, '__esModule', { value: true });
2
+
3
+ var safePreset = require('./safe.js');
4
+
5
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
6
+
7
+ var safePreset__default = /*#__PURE__*/_interopDefault(safePreset);
8
+
9
+ /**
10
+ * Maximal minification (might break some pages)
11
+ */ var max = {
12
+ ...safePreset__default.default,
13
+ collapseWhitespace: 'all',
14
+ removeComments: 'all',
15
+ removeAttributeQuotes: true,
16
+ removeRedundantAttributes: true,
17
+ mergeScripts: true,
18
+ mergeStyles: true,
19
+ removeUnusedCss: {},
20
+ minifyCss: {
21
+ preset: 'default'
22
+ },
23
+ minifySvg: {},
24
+ minifyConditionalComments: true,
25
+ removeOptionalTags: true
26
+ };
27
+
28
+ exports.default = max;
@@ -2,8 +2,8 @@ import safePreset from './safe.mjs';
2
2
 
3
3
  /**
4
4
  * Maximal minification (might break some pages)
5
- */
6
- export default { ...safePreset,
5
+ */ var max = {
6
+ ...safePreset,
7
7
  collapseWhitespace: 'all',
8
8
  removeComments: 'all',
9
9
  removeAttributeQuotes: true,
@@ -12,9 +12,11 @@ export default { ...safePreset,
12
12
  mergeStyles: true,
13
13
  removeUnusedCss: {},
14
14
  minifyCss: {
15
- preset: 'default',
15
+ preset: 'default'
16
16
  },
17
17
  minifySvg: {},
18
18
  minifyConditionalComments: true,
19
- removeOptionalTags: true,
19
+ removeOptionalTags: true
20
20
  };
21
+
22
+ export { max as default };