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
@@ -1,121 +0,0 @@
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: ['th'],
11
- accept: ['input'],
12
- 'accept-charset': ['form'],
13
- charset: ['meta', 'script'],
14
- action: ['form'],
15
- cols: ['textarea'],
16
- colspan: ['td', 'th'],
17
- coords: ['area'],
18
- dirname: ['input', 'textarea'],
19
- dropzone: null,
20
- headers: ['td', 'th'],
21
- form: [
22
- 'button',
23
- 'fieldset',
24
- 'input',
25
- 'keygen',
26
- 'object',
27
- 'output',
28
- 'select',
29
- 'textarea'
30
- ],
31
- formaction: ['button', 'input'],
32
- height: ['canvas', 'embed', 'iframe', 'img', 'input', 'object', 'video'],
33
- high: 'meter',
34
- href: 'link',
35
- list: 'input',
36
- low: 'meter',
37
- manifest: 'html',
38
- max: ['meter', 'progress'],
39
- maxLength: ['input', 'textarea'],
40
- menu: 'button',
41
- min: 'meter',
42
- minLength: ['input', 'textarea'],
43
- name: [
44
- 'button',
45
- 'fieldset',
46
- 'input',
47
- 'keygen',
48
- 'output',
49
- 'select',
50
- 'textarea',
51
- 'form',
52
- 'map',
53
- 'meta',
54
- 'param',
55
- 'slot'
56
- ],
57
- pattern: ['input'],
58
- ping: ['a', 'area'],
59
- placeholder: ['input', 'textarea'],
60
- poster: ['video'],
61
- rel: ['a', 'area', 'link'],
62
- rows: 'textarea',
63
- rowspan: ['td', 'th'],
64
- size: ['input', 'select'],
65
- span: ['col', 'colgroup'],
66
- src: [
67
- 'audio',
68
- 'embed',
69
- 'iframe',
70
- 'img',
71
- 'input',
72
- 'script',
73
- 'source',
74
- 'track',
75
- 'video'
76
- ],
77
- start: 'ol',
78
- tabindex: null,
79
- type: [
80
- 'a',
81
- 'link',
82
- 'button',
83
- 'embed',
84
- 'object',
85
- 'script',
86
- 'source',
87
- 'style',
88
- 'input',
89
- 'menu',
90
- 'menuitem',
91
- 'ol'
92
- ],
93
- value: ['button', 'input', 'li'],
94
- width: ['canvas', 'embed', 'iframe', 'img', 'input', 'object', 'video']
95
- };
96
-
97
- export function onAttrs() {
98
- return (attrs, node) => {
99
- const newAttrs = { ...attrs };
100
- Object.entries(attrs).forEach(([attrName, attrValue]) => {
101
- if (
102
- isEventHandler(attrName)
103
- || (
104
- Object.hasOwnProperty.call(safeToRemoveAttrs, attrName)
105
- && (
106
- safeToRemoveAttrs[attrName] === null
107
- || safeToRemoveAttrs[attrName].includes(node.tag)
108
- )
109
- )
110
- ) {
111
- if (typeof attrValue === 'string') {
112
- if (attrValue === '' || attrValue.trim() === '') {
113
- delete newAttrs[attrName];
114
- }
115
- }
116
- }
117
- });
118
-
119
- return newAttrs;
120
- };
121
- }
@@ -1,183 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = removeOptionalTags;
7
- var _helpers = require("../helpers.cjs");
8
- const startWithWhitespacePattern = /^\s+/;
9
- const bodyStartTagCantBeOmittedWithFirstChildTags = new Set(['meta', 'link', 'script', 'style']);
10
- const tbodyStartTagCantBeOmittedWithPrecededTags = new Set(['tbody', 'thead', 'tfoot']);
11
- const tbodyEndTagCantBeOmittedWithFollowedTags = new Set(['tbody', 'tfoot']);
12
- function isEmptyTextNode(node) {
13
- if (typeof node === 'string' && node.trim() === '') {
14
- return true;
15
- }
16
- return false;
17
- }
18
- function isEmptyNode(node) {
19
- if (!node.content) {
20
- return true;
21
- }
22
- if (node.content.length) {
23
- return !node.content.filter(n => typeof n === 'string' && isEmptyTextNode(n) ? false : true).length;
24
- }
25
- return true;
26
- }
27
- function getFirstChildTag(node, nonEmpty = true) {
28
- if (node.content && node.content.length) {
29
- if (nonEmpty) {
30
- for (const childNode of node.content) {
31
- if (childNode.tag) return childNode;
32
- if (typeof childNode === 'string' && !isEmptyTextNode(childNode)) return childNode;
33
- }
34
- } else {
35
- return node.content[0] || null;
36
- }
37
- }
38
- return null;
39
- }
40
- function getPrevNode(tree, currentNodeIndex, nonEmpty = false) {
41
- if (nonEmpty) {
42
- for (let i = currentNodeIndex - 1; i >= 0; i--) {
43
- const node = tree[i];
44
- if (node.tag) return node;
45
- if (typeof node === 'string' && !isEmptyTextNode(node)) return node;
46
- }
47
- } else {
48
- return tree[currentNodeIndex - 1] || null;
49
- }
50
- return null;
51
- }
52
- function getNextNode(tree, currentNodeIndex, nonEmpty = false) {
53
- if (nonEmpty) {
54
- for (let i = currentNodeIndex + 1; i < tree.length; i++) {
55
- const node = tree[i];
56
- if (node.tag) return node;
57
- if (typeof node === 'string' && !isEmptyTextNode(node)) return node;
58
- }
59
- } else {
60
- return tree[currentNodeIndex + 1] || null;
61
- }
62
- return null;
63
- }
64
-
65
- // Specification https://html.spec.whatwg.org/multipage/syntax.html#optional-tags
66
- /** Remove optional tag in the DOM */
67
- function removeOptionalTags(tree) {
68
- tree.forEach((node, index) => {
69
- if (!node.tag) return node;
70
- if (node.attrs && Object.keys(node.attrs).length) return node;
71
-
72
- // const prevNode = getPrevNode(tree, index);
73
- const prevNonEmptyNode = getPrevNode(tree, index, true);
74
- const nextNode = getNextNode(tree, index);
75
- const nextNonEmptyNode = getNextNode(tree, index, true);
76
- const firstChildNode = getFirstChildTag(node, false);
77
- const firstNonEmptyChildNode = getFirstChildTag(node);
78
-
79
- /**
80
- * An "html" element's start tag may be omitted if the first thing inside the "html" element is not a comment.
81
- * An "html" element's end tag may be omitted if the "html" element is not IMMEDIATELY followed by a comment.
82
- */
83
- if (node.tag === 'html') {
84
- let isHtmlStartTagCanBeOmitted = true;
85
- let isHtmlEndTagCanBeOmitted = true;
86
- if (typeof firstNonEmptyChildNode === 'string' && (0, _helpers.isComment)(firstNonEmptyChildNode)) {
87
- isHtmlStartTagCanBeOmitted = false;
88
- }
89
- if (typeof nextNonEmptyNode === 'string' && (0, _helpers.isComment)(nextNonEmptyNode)) {
90
- isHtmlEndTagCanBeOmitted = false;
91
- }
92
- if (isHtmlStartTagCanBeOmitted && isHtmlEndTagCanBeOmitted) {
93
- node.tag = false;
94
- }
95
- }
96
-
97
- /**
98
- * 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.
99
- * A "head" element's end tag may be omitted if the "head" element is not IMMEDIATELY followed by ASCII whitespace or a comment.
100
- */
101
- if (node.tag === 'head') {
102
- let isHeadStartTagCanBeOmitted = false;
103
- let isHeadEndTagCanBeOmitted = true;
104
- if (isEmptyNode(node) || firstNonEmptyChildNode && firstNonEmptyChildNode.tag) {
105
- isHeadStartTagCanBeOmitted = true;
106
- }
107
- if (nextNode && typeof nextNode === 'string' && startWithWhitespacePattern.test(nextNode) || nextNonEmptyNode && typeof nextNonEmptyNode === 'string' && (0, _helpers.isComment)(nextNode)) {
108
- isHeadEndTagCanBeOmitted = false;
109
- }
110
- if (isHeadStartTagCanBeOmitted && isHeadEndTagCanBeOmitted) {
111
- node.tag = false;
112
- }
113
- }
114
-
115
- /**
116
- * 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.
117
- * A "body" element's end tag may be omitted if the "body" element is not IMMEDIATELY followed by a comment.
118
- */
119
- if (node.tag === 'body') {
120
- let isBodyStartTagCanBeOmitted = true;
121
- let isBodyEndTagCanBeOmitted = true;
122
- if (typeof firstChildNode === 'string' && startWithWhitespacePattern.test(firstChildNode) || typeof firstNonEmptyChildNode === 'string' && (0, _helpers.isComment)(firstNonEmptyChildNode)) {
123
- isBodyStartTagCanBeOmitted = false;
124
- }
125
- if (firstNonEmptyChildNode && firstNonEmptyChildNode.tag && bodyStartTagCantBeOmittedWithFirstChildTags.has(firstNonEmptyChildNode.tag)) {
126
- isBodyStartTagCanBeOmitted = false;
127
- }
128
- if (nextNode && typeof nextNode === 'string' && (0, _helpers.isComment)(nextNode)) {
129
- isBodyEndTagCanBeOmitted = false;
130
- }
131
- if (isBodyStartTagCanBeOmitted && isBodyEndTagCanBeOmitted) {
132
- node.tag = false;
133
- }
134
- }
135
-
136
- /**
137
- * 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.
138
- * A "colgroup" element's end tag may be omitted if the "colgroup" element is not IMMEDIATELY followed by ASCII whitespace or a comment.
139
- */
140
- if (node.tag === 'colgroup') {
141
- let isColgroupStartTagCanBeOmitted = false;
142
- let isColgroupEndTagCanBeOmitted = true;
143
- if (firstNonEmptyChildNode && firstNonEmptyChildNode.tag && firstNonEmptyChildNode.tag === 'col') {
144
- isColgroupStartTagCanBeOmitted = true;
145
- }
146
- if (prevNonEmptyNode && prevNonEmptyNode.tag && prevNonEmptyNode.tag === 'colgroup') {
147
- isColgroupStartTagCanBeOmitted = false;
148
- }
149
- if (nextNode && typeof nextNode === 'string' && startWithWhitespacePattern.test(nextNode) || nextNonEmptyNode && typeof nextNonEmptyNode === 'string' && (0, _helpers.isComment)(nextNonEmptyNode)) {
150
- isColgroupEndTagCanBeOmitted = false;
151
- }
152
- if (isColgroupStartTagCanBeOmitted && isColgroupEndTagCanBeOmitted) {
153
- node.tag = false;
154
- }
155
- }
156
-
157
- /**
158
- * 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.
159
- * A "tbody" element's end tag may be omitted if the "tbody" element is not IMMEDIATELY followed by a "tbody" or "tfoot" element.
160
- */
161
- if (node.tag === 'tbody') {
162
- let isTbodyStartTagCanBeOmitted = false;
163
- let isTbodyEndTagCanBeOmitted = true;
164
- if (firstNonEmptyChildNode && firstNonEmptyChildNode.tag && firstNonEmptyChildNode.tag === 'tr') {
165
- isTbodyStartTagCanBeOmitted = true;
166
- }
167
- if (prevNonEmptyNode && prevNonEmptyNode.tag && tbodyStartTagCantBeOmittedWithPrecededTags.has(prevNonEmptyNode.tag)) {
168
- isTbodyStartTagCanBeOmitted = false;
169
- }
170
- if (nextNonEmptyNode && nextNonEmptyNode.tag && tbodyEndTagCantBeOmittedWithFollowedTags.has(nextNonEmptyNode.tag)) {
171
- isTbodyEndTagCanBeOmitted = false;
172
- }
173
- if (isTbodyStartTagCanBeOmitted && isTbodyEndTagCanBeOmitted) {
174
- node.tag = false;
175
- }
176
- }
177
- if (node.content && node.content.length) {
178
- removeOptionalTags(node.content);
179
- }
180
- return node;
181
- });
182
- return tree;
183
- }
@@ -1,112 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.onAttrs = onAttrs;
7
- exports.redundantScriptTypes = void 0;
8
- // https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types#JavaScript_types
9
- const redundantScriptTypes = exports.redundantScriptTypes = new Set(['application/javascript', 'application/ecmascript', 'application/x-ecmascript', 'application/x-javascript', 'text/javascript', 'text/ecmascript', 'text/javascript1.0', 'text/javascript1.1', 'text/javascript1.2', 'text/javascript1.3', 'text/javascript1.4', 'text/javascript1.5', 'text/jscript', 'text/livescript', 'text/x-ecmascript', 'text/x-javascript']);
10
-
11
- // https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#missing-value-default
12
- const missingValueDefaultAttributes = {
13
- 'form': {
14
- 'method': 'get'
15
- },
16
- input: {
17
- type: 'text'
18
- },
19
- button: {
20
- // https://html.spec.whatwg.org/multipage/form-elements.html#attr-button-type
21
- type: 'submit'
22
- },
23
- 'script': {
24
- 'language': 'javascript',
25
- 'type': attrs => {
26
- for (const [attrName, attrValue] of Object.entries(attrs)) {
27
- if (attrName.toLowerCase() !== 'type') {
28
- continue;
29
- }
30
- return redundantScriptTypes.has(attrValue);
31
- }
32
- return false;
33
- },
34
- // Remove attribute if the function returns false
35
- 'charset': attrs => {
36
- // The charset attribute only really makes sense on “external” SCRIPT elements:
37
- // http://perfectionkills.com/optimizing-html/#8_script_charset
38
- return !attrs.src;
39
- }
40
- },
41
- 'style': {
42
- 'media': 'all',
43
- 'type': 'text/css'
44
- },
45
- 'link': {
46
- media: 'all',
47
- 'type': attrs => {
48
- // https://html.spec.whatwg.org/multipage/links.html#link-type-stylesheet
49
- let isRelStyleSheet = false;
50
- let isTypeTextCSS = false;
51
- if (attrs) {
52
- for (const [attrName, attrValue] of Object.entries(attrs)) {
53
- if (attrName.toLowerCase() === 'rel' && attrValue === 'stylesheet') {
54
- isRelStyleSheet = true;
55
- }
56
- if (attrName.toLowerCase() === 'type' && attrValue === 'text/css') {
57
- isTypeTextCSS = true;
58
- }
59
- }
60
- }
61
-
62
- // Only "text/css" is redudant for link[rel=stylesheet]. Otherwise "type" shouldn't be removed
63
- return isRelStyleSheet && isTypeTextCSS;
64
- }
65
- },
66
- // See: https://html.spec.whatwg.org/#lazy-loading-attributes
67
- img: {
68
- 'loading': 'eager',
69
- // https://html.spec.whatwg.org/multipage/embedded-content.html#dom-img-decoding
70
- decoding: 'auto'
71
- },
72
- iframe: {
73
- 'loading': 'eager'
74
- },
75
- // https://html.spec.whatwg.org/multipage/media.html#htmltrackelement
76
- track: {
77
- kind: 'subtitles'
78
- },
79
- textarea: {
80
- // https://html.spec.whatwg.org/multipage/form-elements.html#dom-textarea-wrap
81
- wrap: 'soft'
82
- },
83
- area: {
84
- // https://html.spec.whatwg.org/multipage/image-maps.html#attr-area-shape
85
- shape: 'rect'
86
- }
87
- };
88
- const tagsHaveMissingValueDefaultAttributes = new Set(Object.keys(missingValueDefaultAttributes));
89
-
90
- /** Removes redundant attributes */
91
- function onAttrs() {
92
- return (attrs, node) => {
93
- if (!node.tag) return attrs;
94
- const newAttrs = attrs;
95
- if (tagsHaveMissingValueDefaultAttributes.has(node.tag)) {
96
- const tagRedundantAttributes = missingValueDefaultAttributes[node.tag];
97
- for (const redundantAttributeName of Object.keys(tagRedundantAttributes)) {
98
- let tagRedundantAttributeValue = tagRedundantAttributes[redundantAttributeName];
99
- let isRemove = false;
100
- if (typeof tagRedundantAttributeValue === 'function') {
101
- isRemove = tagRedundantAttributeValue(attrs);
102
- } else if (attrs[redundantAttributeName] === tagRedundantAttributeValue) {
103
- isRemove = true;
104
- }
105
- if (isRemove) {
106
- delete newAttrs[redundantAttributeName];
107
- }
108
- }
109
- }
110
- return newAttrs;
111
- };
112
- }
@@ -1,113 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = removeUnusedCss;
7
- var _helpers = require("../helpers.cjs");
8
- // These options must be set and shouldn't be overriden to ensure uncss doesn't look at linked stylesheets.
9
- const uncssOptions = {
10
- ignoreSheets: [/\s*/],
11
- stylesheets: []
12
- };
13
- function processStyleNodeUnCSS(html, styleNode, uncssOptions, uncss) {
14
- const css = (0, _helpers.extractCssFromStyleNode)(styleNode);
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
- styleNode.tag = false;
19
- styleNode.content = [];
20
- return;
21
- }
22
- styleNode.content = [css];
23
- });
24
- }
25
- function runUncss(html, css, userOptions, uncss) {
26
- if (typeof userOptions !== 'object') {
27
- userOptions = {};
28
- }
29
- const options = {
30
- ...userOptions,
31
- ...uncssOptions
32
- };
33
- return new Promise((resolve, reject) => {
34
- options.raw = css;
35
- uncss(html, options, (error, output) => {
36
- if (error) {
37
- reject(error);
38
- return;
39
- }
40
- resolve(output);
41
- });
42
- });
43
- }
44
- const purgeFromHtml = function (tree) {
45
- // content is not used as we can directly used the parsed HTML,
46
- // making the process faster
47
- const selectors = [];
48
- tree.walk(node => {
49
- const classes = node.attrs && node.attrs.class && node.attrs.class.split(' ') || [];
50
- const ids = node.attrs && node.attrs.id && node.attrs.id.split(' ') || [];
51
- selectors.push(...classes, ...ids);
52
- node.tag && selectors.push(node.tag);
53
- return node;
54
- });
55
- return () => selectors;
56
- };
57
- function processStyleNodePurgeCSS(tree, styleNode, purgecssOptions, purgecss) {
58
- const css = (0, _helpers.extractCssFromStyleNode)(styleNode);
59
- return runPurgecss(tree, css, purgecssOptions, purgecss).then(css => {
60
- if (css.trim().length === 0) {
61
- styleNode.tag = false;
62
- styleNode.content = [];
63
- return;
64
- }
65
- styleNode.content = [css];
66
- });
67
- }
68
- function runPurgecss(tree, css, userOptions, purgecss) {
69
- if (typeof userOptions !== 'object') {
70
- userOptions = {};
71
- }
72
- const options = {
73
- ...userOptions,
74
- content: [{
75
- raw: tree,
76
- extension: 'html'
77
- }],
78
- css: [{
79
- raw: css,
80
- extension: 'css'
81
- }],
82
- extractors: [{
83
- extractor: purgeFromHtml(tree),
84
- extensions: ['html']
85
- }]
86
- };
87
- return new purgecss.PurgeCSS().purge(options).then(result => {
88
- return result[0].css;
89
- });
90
- }
91
-
92
- /** Remove unused CSS */
93
- async function removeUnusedCss(tree, options, userOptions) {
94
- const promises = [];
95
- const html = userOptions.tool !== 'purgeCSS' && tree.render(tree);
96
- const purgecss = await (0, _helpers.optionalImport)('purgecss');
97
- const uncss = await (0, _helpers.optionalImport)('uncss');
98
- tree.walk(node => {
99
- if ((0, _helpers.isStyleNode)(node)) {
100
- if (userOptions.tool === 'purgeCSS') {
101
- if (purgecss) {
102
- promises.push(processStyleNodePurgeCSS(tree, node, userOptions, purgecss));
103
- }
104
- } else {
105
- if (uncss) {
106
- promises.push(processStyleNodeUnCSS(html, node, userOptions, uncss));
107
- }
108
- }
109
- }
110
- return node;
111
- });
112
- return Promise.all(promises).then(() => tree);
113
- }
@@ -1,122 +0,0 @@
1
- import { isStyleNode, extractCssFromStyleNode, optionalImport } 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: [/\s*/],
6
- stylesheets: [],
7
- };
8
-
9
- function processStyleNodeUnCSS(html, styleNode, uncssOptions, uncss) {
10
- const css = extractCssFromStyleNode(styleNode);
11
-
12
- return runUncss(html, css, uncssOptions, uncss).then(css => {
13
- // uncss may have left some style tags empty
14
- if (css.trim().length === 0) {
15
- styleNode.tag = false;
16
- styleNode.content = [];
17
- return;
18
- }
19
- styleNode.content = [css];
20
- });
21
- }
22
-
23
- function runUncss(html, css, userOptions, uncss) {
24
- if (typeof userOptions !== 'object') {
25
- userOptions = {};
26
- }
27
-
28
- const options = { ...userOptions, ...uncssOptions };
29
- return new Promise((resolve, reject) => {
30
- options.raw = css;
31
- uncss(html, options, (error, output) => {
32
- if (error) {
33
- reject(error);
34
- return;
35
- }
36
- resolve(output);
37
- });
38
- });
39
- }
40
-
41
- const purgeFromHtml = function (tree) {
42
- // content is not used as we can directly used the parsed HTML,
43
- // making the process faster
44
- const selectors = [];
45
-
46
- tree.walk(node => {
47
- const classes = node.attrs && node.attrs.class && node.attrs.class.split(' ') || [];
48
- const ids = node.attrs && node.attrs.id && node.attrs.id.split(' ') || [];
49
- selectors.push(...classes, ...ids);
50
- node.tag && selectors.push(node.tag);
51
- return node;
52
- });
53
-
54
- return () => selectors;
55
- };
56
-
57
- function processStyleNodePurgeCSS(tree, styleNode, purgecssOptions, purgecss) {
58
- const css = extractCssFromStyleNode(styleNode);
59
- return runPurgecss(tree, css, purgecssOptions, purgecss)
60
- .then(css => {
61
- if (css.trim().length === 0) {
62
- styleNode.tag = false;
63
- styleNode.content = [];
64
- return;
65
- }
66
- styleNode.content = [css];
67
- });
68
- }
69
-
70
- function runPurgecss(tree, css, userOptions, purgecss) {
71
- if (typeof userOptions !== 'object') {
72
- userOptions = {};
73
- }
74
-
75
- const options = {
76
- ...userOptions,
77
- content: [{
78
- raw: tree,
79
- extension: 'html'
80
- }],
81
- css: [{
82
- raw: css,
83
- extension: 'css'
84
- }],
85
- extractors: [{
86
- extractor: purgeFromHtml(tree),
87
- extensions: ['html']
88
- }]
89
- };
90
-
91
- return new purgecss.PurgeCSS()
92
- .purge(options)
93
- .then((result) => {
94
- return result[0].css;
95
- });
96
- }
97
-
98
- /** Remove unused CSS */
99
- export default async function removeUnusedCss(tree, options, userOptions) {
100
- const promises = [];
101
- const html = userOptions.tool !== 'purgeCSS' && tree.render(tree);
102
-
103
- const purgecss = await optionalImport('purgecss');
104
- const uncss = await optionalImport('uncss');
105
-
106
- tree.walk(node => {
107
- if (isStyleNode(node)) {
108
- if (userOptions.tool === 'purgeCSS') {
109
- if (purgecss) {
110
- promises.push(processStyleNodePurgeCSS(tree, node, userOptions, purgecss));
111
- }
112
- } else {
113
- if (uncss) {
114
- promises.push(processStyleNodeUnCSS(html, node, userOptions, uncss));
115
- }
116
- }
117
- }
118
- return node;
119
- });
120
-
121
- return Promise.all(promises).then(() => tree);
122
- }