html-minifier-next 6.2.1 → 6.2.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.
- package/dist/htmlminifier.cjs +35 -8
- package/dist/types/lib/attributes.d.ts.map +1 -1
- package/dist/types/lib/options.d.ts.map +1 -1
- package/dist/types/lib/utils.d.ts +1 -0
- package/dist/types/lib/utils.d.ts.map +1 -1
- package/package.json +7 -7
- package/src/lib/attributes.js +19 -2
- package/src/lib/options.js +7 -8
- package/src/lib/utils.js +12 -0
package/dist/htmlminifier.cjs
CHANGED
|
@@ -43,6 +43,17 @@ class LRU {
|
|
|
43
43
|
delete(key) { this.map.delete(key); }
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
// FNV-1a 32-bit hash for large-input cache keys
|
|
47
|
+
|
|
48
|
+
function hashContent(str) {
|
|
49
|
+
let hash = 2166136261;
|
|
50
|
+
for (let i = 0; i < str.length; i++) {
|
|
51
|
+
hash ^= str.charCodeAt(i);
|
|
52
|
+
hash = Math.imul(hash, 16777619);
|
|
53
|
+
}
|
|
54
|
+
return (hash >>> 0).toString(36);
|
|
55
|
+
}
|
|
56
|
+
|
|
46
57
|
// Unique ID generator
|
|
47
58
|
|
|
48
59
|
function uniqueId(value) {
|
|
@@ -1816,12 +1827,11 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
|
|
|
1816
1827
|
);
|
|
1817
1828
|
}
|
|
1818
1829
|
|
|
1819
|
-
// Cache key:
|
|
1830
|
+
// Cache key: Content + type + options signature; large inputs are hashed to avoid huge Map keys
|
|
1820
1831
|
const inputCSS = wrapCSS(text, type);
|
|
1821
1832
|
const cssSig = stableStringify({ type, opts: lightningCssOptions, cont: !!options.continueOnMinifyError });
|
|
1822
|
-
// For large inputs, use length and content fingerprint (first/last 50 chars) to prevent collisions
|
|
1823
1833
|
const cssKey = inputCSS.length > 2048
|
|
1824
|
-
? (
|
|
1834
|
+
? (hashContent(inputCSS) + '|' + type + '|' + cssSig)
|
|
1825
1835
|
: (inputCSS + '|' + type + '|' + cssSig);
|
|
1826
1836
|
|
|
1827
1837
|
try {
|
|
@@ -1931,8 +1941,8 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
|
|
|
1931
1941
|
// Select pre-computed signature based on engine
|
|
1932
1942
|
const optsSig = useEngine === 'terser' ? terserSig : swcSig;
|
|
1933
1943
|
|
|
1934
|
-
// For large inputs,
|
|
1935
|
-
jsKey = (code.length > 2048 ? (
|
|
1944
|
+
// For large inputs, hash the full content to avoid storing huge strings as Map keys
|
|
1945
|
+
jsKey = (code.length > 2048 ? (hashContent(code) + '|') : (code + '|'))
|
|
1936
1946
|
+ (inline ? '1' : '0') + '|' + (isModule ? 'm' : '') + '|' + useEngine + '|' + optsSig;
|
|
1937
1947
|
|
|
1938
1948
|
const cached = jsMinifyCache.get(jsKey);
|
|
@@ -2044,9 +2054,9 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
|
|
|
2044
2054
|
return svgContent;
|
|
2045
2055
|
}
|
|
2046
2056
|
|
|
2047
|
-
// Cache key
|
|
2057
|
+
// Cache key: Large inputs are hashed to avoid huge Map keys
|
|
2048
2058
|
const svgKey = svgContent.length > 2048
|
|
2049
|
-
? (
|
|
2059
|
+
? (hashContent(svgContent) + '|' + svgSig)
|
|
2050
2060
|
: (svgContent + '|' + svgSig);
|
|
2051
2061
|
|
|
2052
2062
|
try {
|
|
@@ -2093,7 +2103,7 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
|
|
|
2093
2103
|
// Imports
|
|
2094
2104
|
|
|
2095
2105
|
|
|
2096
|
-
// Lazy-load entities
|
|
2106
|
+
// Lazy-load entities (used for `decodeEntities` and event-handler attribute decode before `minifyJS`)
|
|
2097
2107
|
|
|
2098
2108
|
let decodeHTMLStrictPromise;
|
|
2099
2109
|
async function getDecodeHTMLStrict() {
|
|
@@ -2389,6 +2399,23 @@ function cleanAttributeValue(tag, attrName, attrValue, options, attrs, minifyHTM
|
|
|
2389
2399
|
|
|
2390
2400
|
if (isEventAttr) {
|
|
2391
2401
|
attrValue = trimWhitespace(attrValue).replace(/^javascript:\s*/i, '');
|
|
2402
|
+
// Browsers decode attribute values before running event-handler JS—
|
|
2403
|
+
// decode first so the minifier gets valid JavaScript
|
|
2404
|
+
if (!options.decodeEntities && options.minifyJS !== identity && attrValue.indexOf('&') !== -1) {
|
|
2405
|
+
return getDecodeHTMLStrict().then(decode => {
|
|
2406
|
+
const decoded = decode(attrValue);
|
|
2407
|
+
const result = options.minifyJS(decoded, true);
|
|
2408
|
+
const reEncode = v => (v && v.indexOf('&') !== -1) ? v.replace(RE_AMP_ENTITY, '&$1') : v;
|
|
2409
|
+
if (isThenable(result)) {
|
|
2410
|
+
return result.then(reEncode, err => {
|
|
2411
|
+
if (!options.continueOnMinifyError) throw err;
|
|
2412
|
+
options.log && options.log(err);
|
|
2413
|
+
return attrValue;
|
|
2414
|
+
});
|
|
2415
|
+
}
|
|
2416
|
+
return reEncode(result);
|
|
2417
|
+
});
|
|
2418
|
+
}
|
|
2392
2419
|
const result = options.minifyJS(attrValue, true);
|
|
2393
2420
|
if (isThenable(result)) {
|
|
2394
2421
|
return result.catch(err => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attributes.d.ts","sourceRoot":"","sources":["../../../src/lib/attributes.js"],"names":[],"mappings":"AAmCA,mEAOC;AAED,uEAWC;AAED,8DAGC;AAED,4EAOC;AAgCD,mGAuCC;AAED,mEAGC;AAED,qEAGC;AAED,kEAWC;AAED,sEAGC;AAED,8DAWC;AAED,2EAIC;AAmBD,qEAGC;AAgBD,wEAGC;AAED,sEAUC;AAED,2EAEC;AAED,2DAEC;AAED,8DAUC;AAED,uEAUC;AAED,oGASC;AAED,4DAOC;AAUD,
|
|
1
|
+
{"version":3,"file":"attributes.d.ts","sourceRoot":"","sources":["../../../src/lib/attributes.js"],"names":[],"mappings":"AAmCA,mEAOC;AAED,uEAWC;AAED,8DAGC;AAED,4EAOC;AAgCD,mGAuCC;AAED,mEAGC;AAED,qEAGC;AAED,kEAWC;AAED,sEAGC;AAED,8DAWC;AAED,2EAIC;AAmBD,qEAGC;AAgBD,wEAGC;AAED,sEAUC;AAED,2EAEC;AAED,2DAEC;AAED,8DAUC;AAED,uEAUC;AAED,oGASC;AAED,4DAOC;AAUD,iIA6LC;AAwBD,mGAYC;AA0CD,6GAuHC;AAzmBD;;;;;;;GAOG;AACH,mEAHW,OAAO,SAuBjB"}
|
|
@@ -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,
|
|
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,CAgX3B"}
|
|
@@ -7,6 +7,7 @@ export class LRU {
|
|
|
7
7
|
set(key: any, value: any): void;
|
|
8
8
|
delete(key: any): void;
|
|
9
9
|
}
|
|
10
|
+
export function hashContent(str: any): string;
|
|
10
11
|
export function uniqueId(value: any): string;
|
|
11
12
|
export function identity(value: any): any;
|
|
12
13
|
export function isThenable(value: any): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/utils.js"],"names":[],"mappings":"AAEA,+CAUC;AAID;IACE,4BAGC;IAFC,cAAkB;IAClB,mBAAoB;IAEtB,mBAQC;IACD,gCAOC;IACD,uBAAqC;CACtC;AAID,6CAMC;AAID,0CAEC;AAED,gDAEC;AAED,2CAEC;AAID;;;;;;GAMG;AACH,kCALW,MAAM,SACN,MAAM,sBAEJ,OAAO,CAAC,MAAM,CAAC,CAY3B;AAID,6CAUC"}
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/utils.js"],"names":[],"mappings":"AAEA,+CAUC;AAID;IACE,4BAGC;IAFC,cAAkB;IAClB,mBAAoB;IAEtB,mBAQC;IACD,gCAOC;IACD,uBAAqC;CACtC;AAID,8CAOC;AAID,6CAMC;AAID,0CAEC;AAED,gDAEC;AAED,2CAEC;AAID;;;;;;GAMG;AACH,kCALW,MAAM,SACN,MAAM,sBAEJ,OAAO,CAAC,MAAM,CAAC,CAY3B;AAID,6CAUC"}
|
package/package.json
CHANGED
|
@@ -5,25 +5,25 @@
|
|
|
5
5
|
},
|
|
6
6
|
"bugs": "https://github.com/j9t/html-minifier-next/issues",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"commander": "^14.0.
|
|
8
|
+
"commander": "^14.0.3",
|
|
9
9
|
"entities": "^8.0.0",
|
|
10
10
|
"lightningcss": "^1.32.0",
|
|
11
11
|
"svgo": "^4.0.1",
|
|
12
|
-
"terser": "^5.46.
|
|
12
|
+
"terser": "^5.46.2"
|
|
13
13
|
},
|
|
14
14
|
"description": "Super-configurable and well-tested web page minifier (enhanced successor of HTML Minifier)",
|
|
15
15
|
"devDependencies": {
|
|
16
|
-
"@commitlint/cli": "^20.5.
|
|
16
|
+
"@commitlint/cli": "^20.5.3",
|
|
17
17
|
"@eslint/js": "^10.0.1",
|
|
18
18
|
"@rollup/plugin-commonjs": "^29.0.2",
|
|
19
19
|
"@rollup/plugin-json": "^6.1.0",
|
|
20
20
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
21
|
-
"@swc/core": "^1.15.
|
|
22
|
-
"eslint": "^10.
|
|
21
|
+
"@swc/core": "^1.15.32",
|
|
22
|
+
"eslint": "^10.3.0",
|
|
23
23
|
"rollup": "^4.60.2",
|
|
24
24
|
"rollup-plugin-polyfill-node": "^0.13.0",
|
|
25
25
|
"typescript": "^6.0.3",
|
|
26
|
-
"vite": "^8.0.
|
|
26
|
+
"vite": "^8.0.10"
|
|
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.2.
|
|
99
|
+
"version": "6.2.3"
|
|
100
100
|
}
|
package/src/lib/attributes.js
CHANGED
|
@@ -19,9 +19,9 @@ import {
|
|
|
19
19
|
} from './constants.js';
|
|
20
20
|
import { trimWhitespace, collapseWhitespaceAll } from './whitespace.js';
|
|
21
21
|
import { shouldMinifyInnerHTML } from './options.js';
|
|
22
|
-
import { isThenable } from './utils.js';
|
|
22
|
+
import { identity, isThenable } from './utils.js';
|
|
23
23
|
|
|
24
|
-
// Lazy-load entities
|
|
24
|
+
// Lazy-load entities (used for `decodeEntities` and event-handler attribute decode before `minifyJS`)
|
|
25
25
|
|
|
26
26
|
let decodeHTMLStrictPromise;
|
|
27
27
|
async function getDecodeHTMLStrict() {
|
|
@@ -317,6 +317,23 @@ function cleanAttributeValue(tag, attrName, attrValue, options, attrs, minifyHTM
|
|
|
317
317
|
|
|
318
318
|
if (isEventAttr) {
|
|
319
319
|
attrValue = trimWhitespace(attrValue).replace(/^javascript:\s*/i, '');
|
|
320
|
+
// Browsers decode attribute values before running event-handler JS—
|
|
321
|
+
// decode first so the minifier gets valid JavaScript
|
|
322
|
+
if (!options.decodeEntities && options.minifyJS !== identity && attrValue.indexOf('&') !== -1) {
|
|
323
|
+
return getDecodeHTMLStrict().then(decode => {
|
|
324
|
+
const decoded = decode(attrValue);
|
|
325
|
+
const result = options.minifyJS(decoded, true);
|
|
326
|
+
const reEncode = v => (v && v.indexOf('&') !== -1) ? v.replace(RE_AMP_ENTITY, '&$1') : v;
|
|
327
|
+
if (isThenable(result)) {
|
|
328
|
+
return result.then(reEncode, err => {
|
|
329
|
+
if (!options.continueOnMinifyError) throw err;
|
|
330
|
+
options.log && options.log(err);
|
|
331
|
+
return attrValue;
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
return reEncode(result);
|
|
335
|
+
});
|
|
336
|
+
}
|
|
320
337
|
const result = options.minifyJS(attrValue, true);
|
|
321
338
|
if (isThenable(result)) {
|
|
322
339
|
return result.catch(err => {
|
package/src/lib/options.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Imports
|
|
2
2
|
|
|
3
3
|
import { createUrlMinifier } from './urls.js';
|
|
4
|
-
import { LRU, stableStringify, identity, lowercase, replaceAsync, parseRegExp } from './utils.js';
|
|
4
|
+
import { LRU, stableStringify, hashContent, identity, lowercase, replaceAsync, parseRegExp } from './utils.js';
|
|
5
5
|
import { RE_TRAILING_SEMICOLON } from './constants.js';
|
|
6
6
|
import { canCollapseWhitespace, canTrimWhitespace } from './whitespace.js';
|
|
7
7
|
import { wrapCSS, unwrapCSS } from './content.js';
|
|
@@ -131,12 +131,11 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
|
|
|
131
131
|
);
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
// Cache key:
|
|
134
|
+
// Cache key: Content + type + options signature; large inputs are hashed to avoid huge Map keys
|
|
135
135
|
const inputCSS = wrapCSS(text, type);
|
|
136
136
|
const cssSig = stableStringify({ type, opts: lightningCssOptions, cont: !!options.continueOnMinifyError });
|
|
137
|
-
// For large inputs, use length and content fingerprint (first/last 50 chars) to prevent collisions
|
|
138
137
|
const cssKey = inputCSS.length > 2048
|
|
139
|
-
? (
|
|
138
|
+
? (hashContent(inputCSS) + '|' + type + '|' + cssSig)
|
|
140
139
|
: (inputCSS + '|' + type + '|' + cssSig);
|
|
141
140
|
|
|
142
141
|
try {
|
|
@@ -246,8 +245,8 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
|
|
|
246
245
|
// Select pre-computed signature based on engine
|
|
247
246
|
const optsSig = useEngine === 'terser' ? terserSig : swcSig;
|
|
248
247
|
|
|
249
|
-
// For large inputs,
|
|
250
|
-
jsKey = (code.length > 2048 ? (
|
|
248
|
+
// For large inputs, hash the full content to avoid storing huge strings as Map keys
|
|
249
|
+
jsKey = (code.length > 2048 ? (hashContent(code) + '|') : (code + '|'))
|
|
251
250
|
+ (inline ? '1' : '0') + '|' + (isModule ? 'm' : '') + '|' + useEngine + '|' + optsSig;
|
|
252
251
|
|
|
253
252
|
const cached = jsMinifyCache.get(jsKey);
|
|
@@ -359,9 +358,9 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
|
|
|
359
358
|
return svgContent;
|
|
360
359
|
}
|
|
361
360
|
|
|
362
|
-
// Cache key
|
|
361
|
+
// Cache key: Large inputs are hashed to avoid huge Map keys
|
|
363
362
|
const svgKey = svgContent.length > 2048
|
|
364
|
-
? (
|
|
363
|
+
? (hashContent(svgContent) + '|' + svgSig)
|
|
365
364
|
: (svgContent + '|' + svgSig);
|
|
366
365
|
|
|
367
366
|
try {
|
package/src/lib/utils.js
CHANGED
|
@@ -39,6 +39,17 @@ class LRU {
|
|
|
39
39
|
delete(key) { this.map.delete(key); }
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
// FNV-1a 32-bit hash for large-input cache keys
|
|
43
|
+
|
|
44
|
+
function hashContent(str) {
|
|
45
|
+
let hash = 2166136261;
|
|
46
|
+
for (let i = 0; i < str.length; i++) {
|
|
47
|
+
hash ^= str.charCodeAt(i);
|
|
48
|
+
hash = Math.imul(hash, 16777619);
|
|
49
|
+
}
|
|
50
|
+
return (hash >>> 0).toString(36);
|
|
51
|
+
}
|
|
52
|
+
|
|
42
53
|
// Unique ID generator
|
|
43
54
|
|
|
44
55
|
function uniqueId(value) {
|
|
@@ -102,6 +113,7 @@ function parseRegExp(value) {
|
|
|
102
113
|
|
|
103
114
|
export { stableStringify };
|
|
104
115
|
export { LRU };
|
|
116
|
+
export { hashContent };
|
|
105
117
|
export { uniqueId };
|
|
106
118
|
export { identity };
|
|
107
119
|
export { isThenable };
|