html-minifier-next 6.0.0 → 6.1.1

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.
@@ -1893,7 +1893,7 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
1893
1893
  cont: !!options.continueOnMinifyError
1894
1894
  });
1895
1895
 
1896
- options.minifyJS = async function (text, inline) {
1896
+ options.minifyJS = async function (text, inline, isModule) {
1897
1897
  const start = text.match(/^\s*<!--.*/);
1898
1898
  const code = start ? text.slice(start[0].length).replace(/\n\s*-->\s*$/, '') : text;
1899
1899
 
@@ -1913,7 +1913,7 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
1913
1913
 
1914
1914
  // For large inputs, use length and content fingerprint to prevent collisions
1915
1915
  jsKey = (code.length > 2048 ? (code.length + '|' + code.slice(0, 50) + code.slice(-50) + '|') : (code + '|'))
1916
- + (inline ? '1' : '0') + '|' + useEngine + '|' + optsSig;
1916
+ + (inline ? '1' : '0') + '|' + (isModule ? 'm' : '') + '|' + useEngine + '|' + optsSig;
1917
1917
 
1918
1918
  const cached = jsMinifyCache.get(jsKey);
1919
1919
  if (cached) {
@@ -1929,7 +1929,8 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
1929
1929
  parse: {
1930
1930
  ...terserOptions.parse,
1931
1931
  bare_returns: inline
1932
- }
1932
+ },
1933
+ ...(isModule ? { module: true } : {}) // Overrides user options: module detection takes precedence for `<script type=module>`
1933
1934
  };
1934
1935
  const terser = await getTerser();
1935
1936
  const result = await terser(code, terserCallOptions);
@@ -1940,7 +1941,8 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
1940
1941
  const result = await swc.minify(code, {
1941
1942
  compress: true,
1942
1943
  mangle: true,
1943
- ...swcOptions, // User options override defaults
1944
+ ...swcOptions,
1945
+ ...(isModule ? { module: true } : {}) // Overrides user options: module detection takes precedence for `<script type=module>`
1944
1946
  });
1945
1947
  return result.code.replace(RE_TRAILING_SEMICOLON, '');
1946
1948
  }
@@ -3068,12 +3070,14 @@ function mergeConsecutiveScripts(html) {
3068
3070
  return match;
3069
3071
  }
3070
3072
 
3071
- // Check `type` compatibility (both must be same, or both default JS)
3072
- const type1 = a1.type || '';
3073
- const type2 = a2.type || '';
3073
+ // Check `type` compatibility (both must be default JS)
3074
+ const type1 = (a1.type || '').toLowerCase();
3075
+ const type2 = (a2.type || '').toLowerCase();
3074
3076
 
3075
- if (DEFAULT_JS_TYPES.has(type1) && DEFAULT_JS_TYPES.has(type2)) ; else if (type1 === type2) ; else {
3076
- // Incompatible types
3077
+ if (DEFAULT_JS_TYPES.has(type1) && DEFAULT_JS_TYPES.has(type2)) ; else {
3078
+ // Non-JS types (modules, JSON, etc.) must not be merged:
3079
+ // Module scripts have per-script lexical scope, and non-JS content (e.g., JSON)
3080
+ // is not concatenable. Even identical non-JS types are incompatible.
3077
3081
  return match;
3078
3082
  }
3079
3083
 
@@ -3887,11 +3891,11 @@ async function minifyHTML(value, options, partialMarkup) {
3887
3891
 
3888
3892
  if (options.minifyJS) {
3889
3893
  options.minifyJS = (function (fn) {
3890
- return function (text, type) {
3894
+ return function (text, inline, isModule) {
3891
3895
  return fn(text.replace(uidPattern, function (match, prefix, index) {
3892
3896
  const chunks = ignoredCustomMarkupChunks[+index];
3893
3897
  return chunks[1] + uidAttr + index + uidAttr + chunks[2];
3894
- }), type);
3898
+ }), inline, isModule);
3895
3899
  };
3896
3900
  })(options.minifyJS);
3897
3901
  }
@@ -4214,6 +4218,9 @@ async function minifyHTML(value, options, partialMarkup) {
4214
4218
  const needsDecode = options.decodeEntities && text && !specialContentElements.has(currentTag) && text.indexOf('&') !== -1;
4215
4219
  const needsProcessScript = specialContentElements.has(currentTag) && (options.processScripts || hasJsonScriptType(currentAttrs));
4216
4220
  const needsMinifyJS = options.minifyJS !== identity && isExecutableScript(currentTag, currentAttrs);
4221
+ const isModuleScript = needsMinifyJS && currentAttrs.some(
4222
+ a => a.name.toLowerCase() === 'type' && (a.value ?? '').trim().toLowerCase() === 'module'
4223
+ );
4217
4224
  const needsMinifyCSS = options.minifyCSS !== identity && isStyleElement(currentTag, currentAttrs);
4218
4225
 
4219
4226
  // Whitespace collapsing phase (sync); captures `prevTag`/`nextTag`/`prevAttrs`/`nextAttrs` from outer scope
@@ -4340,7 +4347,7 @@ async function minifyHTML(value, options, partialMarkup) {
4340
4347
  text = await processScript(text, options, currentAttrs, minifyHTML);
4341
4348
  }
4342
4349
  if (needsMinifyJS) {
4343
- text = await options.minifyJS(text);
4350
+ text = await options.minifyJS(text, false, isModuleScript);
4344
4351
  }
4345
4352
  if (needsMinifyCSS) {
4346
4353
  text = await options.minifyCSS(text);
@@ -1 +1 @@
1
- {"version":3,"file":"htmlminifier.d.ts","sourceRoot":"","sources":["../../src/htmlminifier.js"],"names":[],"mappings":"AAsrDO,8BAJI,MAAM,YACN,eAAe,GACb,OAAO,CAAC,MAAM,CAAC,CAwB3B;;;;;;;;;;;;UA39CS,MAAM;;;;;;;;;;;;;;;;;;mCAaA,MAAM,SAAS,aAAa,EAAE,yBAAyB,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,KAAK,OAAO;;;;;;;+BAM3F,MAAM,GAAG,IAAI,SAAS,aAAa,EAAE,GAAG,SAAS,qBAAqB,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,KAAK,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBA6JtG,OAAO,KAAK,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2HA2BiF,MAAM,SAAS,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM;;;;;;;;;;;;;;;;iBASxG,QAAQ,GAAG,KAAK;gBAAgC,MAAM,WAAW,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM;;;;;;;;;;;eAa/H,MAAM;gBAAY,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM;;;;;;;;;;;;;;;;;mBAiBzE,MAAM,KAAK,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kDA+DF,MAAM,OAAO,MAAM,KAAK,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sCA2EpC,MAAM,SAAS,aAAa,EAAE,KAAK,IAAI;;;;;;;;;wCAQrC,MAAM,KAAK,MAAM;;;;;;;;;;;;;;;;;wBAjnBK,cAAc;0BAAd,cAAc;+BAAd,cAAc"}
1
+ {"version":3,"file":"htmlminifier.d.ts","sourceRoot":"","sources":["../../src/htmlminifier.js"],"names":[],"mappings":"AAyrDO,8BAJI,MAAM,YACN,eAAe,GACb,OAAO,CAAC,MAAM,CAAC,CAwB3B;;;;;;;;;;;;UA99CS,MAAM;;;;;;;;;;;;;;;;;;mCAaA,MAAM,SAAS,aAAa,EAAE,yBAAyB,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,KAAK,OAAO;;;;;;;+BAM3F,MAAM,GAAG,IAAI,SAAS,aAAa,EAAE,GAAG,SAAS,qBAAqB,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,KAAK,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBA6JtG,OAAO,KAAK,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2HA2BiF,MAAM,SAAS,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM;;;;;;;;;;;;;;;;iBASxG,QAAQ,GAAG,KAAK;gBAAgC,MAAM,WAAW,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM;;;;;;;;;;;eAa/H,MAAM;gBAAY,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM;;;;;;;;;;;;;;;;;mBAiBzE,MAAM,KAAK,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kDA+DF,MAAM,OAAO,MAAM,KAAK,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sCA2EpC,MAAM,SAAS,aAAa,EAAE,KAAK,IAAI;;;;;;;;;wCAQrC,MAAM,KAAK,MAAM;;;;;;;;;;;;;;;;;wBAjnBK,cAAc;0BAAd,cAAc;+BAAd,cAAc"}
@@ -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,CA+W3B"}
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,CAiX3B"}
package/package.json CHANGED
@@ -23,7 +23,7 @@
23
23
  "rollup": "^4.60.0",
24
24
  "rollup-plugin-polyfill-node": "^0.13.0",
25
25
  "typescript": "^6.0.2",
26
- "vite": "^8.0.1"
26
+ "vite": "^8.0.5"
27
27
  },
28
28
  "exports": {
29
29
  ".": {
@@ -96,5 +96,5 @@
96
96
  },
97
97
  "type": "module",
98
98
  "types": "./dist/types/htmlminifier.d.ts",
99
- "version": "6.0.0"
99
+ "version": "6.1.1"
100
100
  }
@@ -180,16 +180,16 @@ function mergeConsecutiveScripts(html) {
180
180
  return match;
181
181
  }
182
182
 
183
- // Check `type` compatibility (both must be same, or both default JS)
184
- const type1 = a1.type || '';
185
- const type2 = a2.type || '';
183
+ // Check `type` compatibility (both must be default JS)
184
+ const type1 = (a1.type || '').toLowerCase();
185
+ const type2 = (a2.type || '').toLowerCase();
186
186
 
187
187
  if (DEFAULT_JS_TYPES.has(type1) && DEFAULT_JS_TYPES.has(type2)) {
188
188
  // Both are default JavaScript—compatible
189
- } else if (type1 === type2) {
190
- // Same explicit type—compatible
191
189
  } else {
192
- // Incompatible types
190
+ // Non-JS types (modules, JSON, etc.) must not be merged:
191
+ // Module scripts have per-script lexical scope, and non-JS content (e.g., JSON)
192
+ // is not concatenable. Even identical non-JS types are incompatible.
193
193
  return match;
194
194
  }
195
195
 
@@ -1003,11 +1003,11 @@ async function minifyHTML(value, options, partialMarkup) {
1003
1003
 
1004
1004
  if (options.minifyJS) {
1005
1005
  options.minifyJS = (function (fn) {
1006
- return function (text, type) {
1006
+ return function (text, inline, isModule) {
1007
1007
  return fn(text.replace(uidPattern, function (match, prefix, index) {
1008
1008
  const chunks = ignoredCustomMarkupChunks[+index];
1009
1009
  return chunks[1] + uidAttr + index + uidAttr + chunks[2];
1010
- }), type);
1010
+ }), inline, isModule);
1011
1011
  };
1012
1012
  })(options.minifyJS);
1013
1013
  }
@@ -1330,6 +1330,9 @@ async function minifyHTML(value, options, partialMarkup) {
1330
1330
  const needsDecode = options.decodeEntities && text && !specialContentElements.has(currentTag) && text.indexOf('&') !== -1;
1331
1331
  const needsProcessScript = specialContentElements.has(currentTag) && (options.processScripts || hasJsonScriptType(currentAttrs));
1332
1332
  const needsMinifyJS = options.minifyJS !== identity && isExecutableScript(currentTag, currentAttrs);
1333
+ const isModuleScript = needsMinifyJS && currentAttrs.some(
1334
+ a => a.name.toLowerCase() === 'type' && (a.value ?? '').trim().toLowerCase() === 'module'
1335
+ );
1333
1336
  const needsMinifyCSS = options.minifyCSS !== identity && isStyleElement(currentTag, currentAttrs);
1334
1337
 
1335
1338
  // Whitespace collapsing phase (sync); captures `prevTag`/`nextTag`/`prevAttrs`/`nextAttrs` from outer scope
@@ -1456,7 +1459,7 @@ async function minifyHTML(value, options, partialMarkup) {
1456
1459
  text = await processScript(text, options, currentAttrs, minifyHTML);
1457
1460
  }
1458
1461
  if (needsMinifyJS) {
1459
- text = await options.minifyJS(text);
1462
+ text = await options.minifyJS(text, false, isModuleScript);
1460
1463
  }
1461
1464
  if (needsMinifyCSS) {
1462
1465
  text = await options.minifyCSS(text);
@@ -228,7 +228,7 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
228
228
  cont: !!options.continueOnMinifyError
229
229
  });
230
230
 
231
- options.minifyJS = async function (text, inline) {
231
+ options.minifyJS = async function (text, inline, isModule) {
232
232
  const start = text.match(/^\s*<!--.*/);
233
233
  const code = start ? text.slice(start[0].length).replace(/\n\s*-->\s*$/, '') : text;
234
234
 
@@ -248,7 +248,7 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
248
248
 
249
249
  // For large inputs, use length and content fingerprint to prevent collisions
250
250
  jsKey = (code.length > 2048 ? (code.length + '|' + code.slice(0, 50) + code.slice(-50) + '|') : (code + '|'))
251
- + (inline ? '1' : '0') + '|' + useEngine + '|' + optsSig;
251
+ + (inline ? '1' : '0') + '|' + (isModule ? 'm' : '') + '|' + useEngine + '|' + optsSig;
252
252
 
253
253
  const cached = jsMinifyCache.get(jsKey);
254
254
  if (cached) {
@@ -264,7 +264,8 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
264
264
  parse: {
265
265
  ...terserOptions.parse,
266
266
  bare_returns: inline
267
- }
267
+ },
268
+ ...(isModule ? { module: true } : {}) // Overrides user options: module detection takes precedence for `<script type=module>`
268
269
  };
269
270
  const terser = await getTerser();
270
271
  const result = await terser(code, terserCallOptions);
@@ -275,7 +276,8 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
275
276
  const result = await swc.minify(code, {
276
277
  compress: true,
277
278
  mangle: true,
278
- ...swcOptions, // User options override defaults
279
+ ...swcOptions,
280
+ ...(isModule ? { module: true } : {}) // Overrides user options: module detection takes precedence for `<script type=module>`
279
281
  });
280
282
  return result.code.replace(RE_TRAILING_SEMICOLON, '');
281
283
  }