html-minifier-next 5.1.4 → 5.1.6

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.
@@ -1133,10 +1133,14 @@ const isSimpleBoolean = new Set(['allowfullscreen', 'async', 'autofocus', 'autop
1133
1133
 
1134
1134
  const isBooleanValue = new Set(['true', 'false']);
1135
1135
 
1136
- // Attributes where empty value can be collapsed to just the attribute name
1137
- // `crossorigin=""` `crossorigin` (empty string equals anonymous mode)
1138
- // `contenteditable=""` → `contenteditable` (empty string equals `true`)
1139
- const emptyCollapsible = new Set(['crossorigin', 'contenteditable']);
1136
+ // Attributes where certain values can be collapsed to just the attribute name;
1137
+ // maps each attribute name to the set of values that collapse to the bare attribute:
1138
+ // - `crossorigin=""` and `crossorigin="anonymous"` → `crossorigin` (anonymous is the default)
1139
+ // - `contenteditable=""` `contenteditable` (empty string means inherit/true)
1140
+ const collapsibleValues = new Map([
1141
+ ['crossorigin', new Set(['', 'anonymous'])],
1142
+ ['contenteditable', new Set([''])]
1143
+ ]);
1140
1144
 
1141
1145
  // `srcset` elements
1142
1146
 
@@ -1738,19 +1742,21 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
1738
1742
  });
1739
1743
  };
1740
1744
 
1741
- // Apply preset first if specified (so user options can override preset values)
1745
+ // Merge preset with user options so all values go through normalization
1746
+ // User options take precedence over preset values
1747
+ let effectiveInput = inputOptions;
1742
1748
  if (inputOptions.preset) {
1743
1749
  const preset = getPreset(inputOptions.preset);
1744
1750
  if (preset) {
1745
- Object.assign(options, preset);
1751
+ effectiveInput = { ...preset, ...inputOptions };
1746
1752
  } else {
1747
1753
  const available = getPresetNames().join(', ');
1748
1754
  console.warn(`HTML Minifier Next: Unknown preset “${inputOptions.preset}”. Available presets: ${available}`);
1749
1755
  }
1750
1756
  }
1751
1757
 
1752
- Object.keys(inputOptions).forEach(function (key) {
1753
- const option = inputOptions[key];
1758
+ Object.keys(effectiveInput).forEach(function (key) {
1759
+ const option = effectiveInput[key];
1754
1760
 
1755
1761
  // Skip preset key—it’s already been processed
1756
1762
  if (key === 'preset') {
@@ -2243,7 +2249,7 @@ function isStyleElement(tag, attrs) {
2243
2249
  function isBooleanAttribute(attrName, attrValue) {
2244
2250
  return isSimpleBoolean.has(attrName) ||
2245
2251
  (attrName === 'draggable' && !isBooleanValue.has(attrValue)) ||
2246
- (attrValue === '' && emptyCollapsible.has(attrName));
2252
+ (collapsibleValues.has(attrName) && collapsibleValues.get(attrName).has(attrValue));
2247
2253
  }
2248
2254
 
2249
2255
  const uriTypeAttributes = new Map([
@@ -78,7 +78,7 @@ export const keepScriptsMimetypes: Set<string>;
78
78
  export const jsonScriptTypes: Set<string>;
79
79
  export const isSimpleBoolean: Set<string>;
80
80
  export const isBooleanValue: Set<string>;
81
- export const emptyCollapsible: Set<string>;
81
+ export const collapsibleValues: Map<string, Set<string>>;
82
82
  export const srcsetElements: Set<string>;
83
83
  export const optionalStartTags: Set<string>;
84
84
  export const optionalEndTags: Set<string>;
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/lib/constants.js"],"names":[],"mappings":"AAEA,iCAAoC;AACpC,+BAAkC;AAClC,oCAA2C;AAC3C,2CAAmD;AACnD,wCAA8C;AAC9C,4CAAkD;AAClD,4CAA2C;AAC3C,4CAA0D;AAC1D,2CAA8C;AAC9C,+CAA0D;AAC1D,2CAAmC;AACnC,mCAA4C;AAC5C,wCAAwqB;AACxqB,kCAA0B;AAC1B,sCAAuC;AACvC,yCAA4C;AAC5C,qCAAuD;AAKvD,+DAAgb;AAGhb,+DAA6O;AAG7O,yDAAmF;AAGnF,8CAA8G;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0C9G,qDAWG;AAEH,+CAEG;AAmBH,0CAUG;AAzBH,0CAAwhB;AAExhB,yCAAkD;AAKlD,2CAAqE;AAIrE,yCAAkD;AAuBlD,4CAAiF;AAEjF,0CAAoM;AAEpM,yCAA4F;AAE5F,8CAAkD;AAElD,yCAAiT;AAEjT,0CAA0F;AAE1F,6CAA8D;AAE9D,gDAAqD;AAErD,yCAAuD;AAEvD,+CAAyD;AAEzD,+CAAkE;AAElE,uCAA2C;AAE3C,2CAA2D;AAE3D,0CAAkD;AAElD,wCAA+D;AAE/D,2CAAkD;AAElD,uCAAmxC;AAInxC,sCAEsD;AAItD,iDAA4D"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/lib/constants.js"],"names":[],"mappings":"AAEA,iCAAoC;AACpC,+BAAkC;AAClC,oCAA2C;AAC3C,2CAAmD;AACnD,wCAA8C;AAC9C,4CAAkD;AAClD,4CAA2C;AAC3C,4CAA0D;AAC1D,2CAA8C;AAC9C,+CAA0D;AAC1D,2CAAmC;AACnC,mCAA4C;AAC5C,wCAAwqB;AACxqB,kCAA0B;AAC1B,sCAAuC;AACvC,yCAA4C;AAC5C,qCAAuD;AAKvD,+DAAgb;AAGhb,+DAA6O;AAG7O,yDAAmF;AAGnF,8CAA8G;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0C9G,qDAWG;AAEH,+CAEG;AAuBH,0CAUG;AA7BH,0CAAwhB;AAExhB,yCAAkD;AAMlD,yDAGG;AAIH,yCAAkD;AAuBlD,4CAAiF;AAEjF,0CAAoM;AAEpM,yCAA4F;AAE5F,8CAAkD;AAElD,yCAAiT;AAEjT,0CAA0F;AAE1F,6CAA8D;AAE9D,gDAAqD;AAErD,yCAAuD;AAEvD,+CAAyD;AAEzD,+CAAkE;AAElE,uCAA2C;AAE3C,2CAA2D;AAE3D,0CAAkD;AAElD,wCAA+D;AAE/D,2CAAkD;AAElD,uCAAmxC;AAInxC,sCAEsD;AAItD,iDAA4D"}
@@ -1 +1 @@
1
- {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../../src/lib/options.js"],"names":[],"mappings":"AAYA,6DAUC;AAID;;;;;;;;;;;GAWG;AACH,6CAXW,OAAO,CAAC,eAAe,CAAC,mGAEhC;IAAuB,eAAe;IACf,SAAS;IACT,MAAM;CAA2B,GAK9C,eAAe,CA6W3B"}
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../../src/lib/options.js"],"names":[],"mappings":"AAYA,6DAUC;AAID;;;;;;;;;;;GAWG;AACH,6CAXW,OAAO,CAAC,eAAe,CAAC,mGAEhC;IAAuB,eAAe;IACf,SAAS;IACT,MAAM;CAA2B,GAK9C,eAAe,CA+W3B"}
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "commander": "^14.0.2",
9
9
  "entities": "^7.0.1",
10
10
  "lightningcss": "^1.31.1",
11
- "svgo": "^4.0.0",
11
+ "svgo": "^4.0.1",
12
12
  "terser": "^5.46.0"
13
13
  },
14
14
  "description": "Super-configurable and well-tested web page minifier (enhanced successor of HTML Minifier)",
@@ -20,7 +20,7 @@
20
20
  "@rollup/plugin-node-resolve": "^16.0.3",
21
21
  "@swc/core": "^1.15.11",
22
22
  "eslint": "^10.0.0",
23
- "rollup": "^4.57.1",
23
+ "rollup": "^4.59.0",
24
24
  "rollup-plugin-polyfill-node": "^0.13.0",
25
25
  "typescript": "^5.9.3",
26
26
  "vite": "^7.3.1"
@@ -95,5 +95,5 @@
95
95
  },
96
96
  "type": "module",
97
97
  "types": "./dist/types/htmlminifier.d.ts",
98
- "version": "5.1.4"
98
+ "version": "5.1.6"
99
99
  }
@@ -14,7 +14,7 @@ import {
14
14
  keepScriptsMimetypes,
15
15
  isSimpleBoolean,
16
16
  isBooleanValue,
17
- emptyCollapsible,
17
+ collapsibleValues,
18
18
  srcsetElements,
19
19
  reEmptyAttribute
20
20
  } from './constants.js';
@@ -189,7 +189,7 @@ function isStyleElement(tag, attrs) {
189
189
  function isBooleanAttribute(attrName, attrValue) {
190
190
  return isSimpleBoolean.has(attrName) ||
191
191
  (attrName === 'draggable' && !isBooleanValue.has(attrValue)) ||
192
- (attrValue === '' && emptyCollapsible.has(attrName));
192
+ (collapsibleValues.has(attrName) && collapsibleValues.get(attrName).has(attrValue));
193
193
  }
194
194
 
195
195
  const uriTypeAttributes = new Map([
@@ -95,10 +95,14 @@ const isSimpleBoolean = new Set(['allowfullscreen', 'async', 'autofocus', 'autop
95
95
 
96
96
  const isBooleanValue = new Set(['true', 'false']);
97
97
 
98
- // Attributes where empty value can be collapsed to just the attribute name
99
- // `crossorigin=""` `crossorigin` (empty string equals anonymous mode)
100
- // `contenteditable=""` → `contenteditable` (empty string equals `true`)
101
- const emptyCollapsible = new Set(['crossorigin', 'contenteditable']);
98
+ // Attributes where certain values can be collapsed to just the attribute name;
99
+ // maps each attribute name to the set of values that collapse to the bare attribute:
100
+ // - `crossorigin=""` and `crossorigin="anonymous"` → `crossorigin` (anonymous is the default)
101
+ // - `contenteditable=""` `contenteditable` (empty string means inherit/true)
102
+ const collapsibleValues = new Map([
103
+ ['crossorigin', new Set(['', 'anonymous'])],
104
+ ['contenteditable', new Set([''])]
105
+ ]);
102
106
 
103
107
  // `srcset` elements
104
108
 
@@ -208,7 +212,7 @@ export {
208
212
  // Boolean sets
209
213
  isSimpleBoolean,
210
214
  isBooleanValue,
211
- emptyCollapsible,
215
+ collapsibleValues,
212
216
 
213
217
  // Misc
214
218
  srcsetElements,
@@ -66,19 +66,21 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
66
66
  });
67
67
  };
68
68
 
69
- // Apply preset first if specified (so user options can override preset values)
69
+ // Merge preset with user options so all values go through normalization
70
+ // User options take precedence over preset values
71
+ let effectiveInput = inputOptions;
70
72
  if (inputOptions.preset) {
71
73
  const preset = getPreset(inputOptions.preset);
72
74
  if (preset) {
73
- Object.assign(options, preset);
75
+ effectiveInput = { ...preset, ...inputOptions };
74
76
  } else {
75
77
  const available = getPresetNames().join(', ');
76
78
  console.warn(`HTML Minifier Next: Unknown preset “${inputOptions.preset}”. Available presets: ${available}`);
77
79
  }
78
80
  }
79
81
 
80
- Object.keys(inputOptions).forEach(function (key) {
81
- const option = inputOptions[key];
82
+ Object.keys(effectiveInput).forEach(function (key) {
83
+ const option = effectiveInput[key];
82
84
 
83
85
  // Skip preset key—it’s already been processed
84
86
  if (key === 'preset') {
File without changes