html-minifier-next 8.4.3 → 8.4.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.
- package/README.md +2 -0
- package/cli.js +27 -6
- package/dist/types/lib/utils.d.ts +2 -0
- package/dist/types/lib/utils.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/lib/file-pool.js +1 -1
- package/src/lib/utils.js +22 -0
package/README.md
CHANGED
|
@@ -83,6 +83,8 @@ export default {
|
|
|
83
83
|
};
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
+
A module can also hold values JSON cannot express, like regular expressions (e.g., `ignoreCustomFragments: [/\{\{[\s\S]*?\}\}/]`) and functions (for `minifyCSS`, `minifyJS`, and `minifyURLs`, or in custom SVGO plugins for `minifySVG`). As functions cannot be passed to worker threads, a run using them minifies in-process.
|
|
87
|
+
|
|
86
88
|
### Node.js
|
|
87
89
|
|
|
88
90
|
```js
|
package/cli.js
CHANGED
|
@@ -262,6 +262,28 @@ const CONFIG_KEYS_EXTRA = new Set(['$schema', 'preset', 'fileExt', 'ignoreDir'])
|
|
|
262
262
|
// `--config-file` isn’t specified
|
|
263
263
|
const CONFIG_FILES_DEFAULT = ['html-minifier-next.config.json', 'htmlminifier.config.json'];
|
|
264
264
|
|
|
265
|
+
/**
|
|
266
|
+
* Parse a config value—strings as on the command line, anything else as it is, since
|
|
267
|
+
* a JSON round trip would drop what only a module config can hold (functions, regexes)
|
|
268
|
+
* @param {string} key Option definition key
|
|
269
|
+
* @param {string} type Option definition type
|
|
270
|
+
* @param {unknown} value
|
|
271
|
+
*/
|
|
272
|
+
function parseConfigValue(key, type, value) {
|
|
273
|
+
if (typeof value === 'string') return getParser(key, type)(value);
|
|
274
|
+
switch (type) {
|
|
275
|
+
case 'int':
|
|
276
|
+
return getParser(key, type)(String(value));
|
|
277
|
+
// A single value is wrapped as its string form is; `null` and `undefined` leave the option unset
|
|
278
|
+
case 'regexpArray':
|
|
279
|
+
return value == null ? undefined : (Array.isArray(value) ? value : [value]).map(parseRegExp);
|
|
280
|
+
case 'jsonArray':
|
|
281
|
+
return value == null ? undefined : (Array.isArray(value) ? value : [value]);
|
|
282
|
+
default:
|
|
283
|
+
return value;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
265
287
|
/**
|
|
266
288
|
* Normalize and validate config object by applying parsers and transforming values.
|
|
267
289
|
* @param {Record<string, any>} config - Raw config object
|
|
@@ -282,8 +304,7 @@ function normalizeConfig(config) {
|
|
|
282
304
|
Object.entries(optionDefinitions).forEach(function ([key, { type }]) {
|
|
283
305
|
if (key in normalized) {
|
|
284
306
|
if (type !== 'boolean' && type !== 'invertedBoolean') {
|
|
285
|
-
|
|
286
|
-
normalized[key] = getParser(key, type)(typeof value === 'string' ? value : JSON.stringify(value));
|
|
307
|
+
normalized[key] = parseConfigValue(key, type, normalized[key]);
|
|
287
308
|
}
|
|
288
309
|
}
|
|
289
310
|
});
|
|
@@ -554,7 +575,7 @@ program.helpOption('-h, --help', 'Display help for command');
|
|
|
554
575
|
|
|
555
576
|
/**
|
|
556
577
|
* A pool for this run, or `null` where one wouldn’t pay or wouldn’t work—in which case
|
|
557
|
-
* the caller minifies in
|
|
578
|
+
* the caller minifies in-process exactly as before
|
|
558
579
|
* @param {string[]} files
|
|
559
580
|
*/
|
|
560
581
|
async function createPool(files) {
|
|
@@ -564,7 +585,7 @@ program.helpOption('-h, --help', 'Display help for command');
|
|
|
564
585
|
// Whether the run went wide is worth saying, since the default weighs the file
|
|
565
586
|
// count and the bytes there are to share out, neither of which the caller sees
|
|
566
587
|
const inProcess = () => {
|
|
567
|
-
if (isVerbose) console.error('Worker threads: none (minifying in
|
|
588
|
+
if (isVerbose) console.error('Worker threads: none (minifying in-process)');
|
|
568
589
|
return null;
|
|
569
590
|
};
|
|
570
591
|
// `availableParallelism` reports what this process may actually use, which under a
|
|
@@ -594,7 +615,7 @@ program.helpOption('-h, --help', 'Display help for command');
|
|
|
594
615
|
}
|
|
595
616
|
|
|
596
617
|
// `log` is a closure over this process’s console and is rebuilt inside the worker;
|
|
597
|
-
// anything else unclonable (
|
|
618
|
+
// anything else unclonable (such as a function from a module config) stays in-process
|
|
598
619
|
const { log, ...options } = createOptions();
|
|
599
620
|
try {
|
|
600
621
|
structuredClone(options);
|
|
@@ -603,7 +624,7 @@ program.helpOption('-h, --help', 'Display help for command');
|
|
|
603
624
|
}
|
|
604
625
|
|
|
605
626
|
// A pool this small has nothing to share out and still pays for its workers, so an
|
|
606
|
-
// explicit request for them lands in
|
|
627
|
+
// explicit request for them lands in-process as `--workers=1` does
|
|
607
628
|
const poolSize = Math.min(size, fileCount);
|
|
608
629
|
if (poolSize <= 1) {
|
|
609
630
|
return inProcess();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/utils.js"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/utils.js"],"names":[],"mappings":"AAAA;;GAEG;AAkBH;;;;;GAKG;AACH,iBAAS,eAAe,CAAC,GAAG,EAHjB,OAGiB,GAFf,MAAM,CAgBlB;AAID,cAAM,GAAG;IAEA,KAAK;IACL,IAAI;IACJ,IAAI;IACT,mCAAmC;IAC9B,GAAG,EADG,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAJjC,YAAY,KAAK,SAAM,EAMtB;IACD,0BAA0B;IAC1B,GAAG,CAAC,GAAG,EADK,MACL,WAUN;IACD;;;OAGG;IACH,GAAG,CAAC,GAAG,EAHI,MAGJ,EAAE,KAAK,EAFH,OAEG,QAOb;IACD,0BAA0B;IAC1B,MAAM,CAAC,GAAG,EADE,MACF,QAA2B;IACrC,6EAA6E;IAC7E,KAAK,IADS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAGxE;CACF;AAKD,QAAA,MAAM,oBAAoB,QAAc,CAAC;AAIzC,0BAA0B;AAC1B,iBAAS,WAAW,CAAC,GAAG,EADZ,MACY,UAOvB;AAID,4BAA4B;AAC5B,iBAAS,QAAQ,CAAC,KAAK,EADX,MACW,UAMtB;AAID,4BAA4B;AAC5B,iBAAS,QAAQ,CAAC,KAAK,EADX,MACW,UAEtB;AAED;;;GAGG;AACH,iBAAS,UAAU,CAAC,KAAK,EAHd,OAGc,GAFZ,KAAK,IAAI,WAAW,CAAC,GAAG,CAAC,CAIrC;AAED,4BAA4B;AAC5B,iBAAS,SAAS,CAAC,KAAK,EADZ,MACY,UAEvB;AAGD,4BAA4B;AAC5B,iBAAS,SAAS,CAAC,KAAK,EADZ,MACY,UAEvB;AAID;;;;;;GAMG;AACH,iBAAe,YAAY,CAAC,GAAG,EALpB,MAKoB,EAAE,KAAK,EAJ3B,MAI2B,EAAE,OAAO,UAAA,GAFlC,OAAO,CAAC,MAAM,CAAC,CAe3B;AAID,qCAAqC;AACrC,iBAAS,WAAW,CAAC,KAAK,EADd,MAAM,GAAG,MACK,sBAUzB;AAyYD;;;;;;;;;GASG;AACH,iBAAS,QAAQ,CAAC,OAAO,EAJd,MAIc,GAHZ,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,CAqDlC;AAED;;;;;;;;;GASG;AACH,iBAAS,WAAW,CAAC,OAAO,EAHjB,MAGiB,GAFf,MAAM,CAOlB;AAGE,YAA6D,MAAM,GAAzD;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,IAAI,CAAA;CAAC,CAE7D;AAqKD;;;;;GAKG;AACH,iBAAS,sBAAsB,CAAC,OAAO,EAL5B,MAAM,GAAG,MAKmB,GAH1B,MAAM,GAAG,IAAI,CAqBzB;AAED;;;;;;;GAOG;AACH,iBAAS,UAAU,CAAC,IAAI,EALb,MAKa,EAAE,GAAG,EAJlB,MAIkB,EAAE,KAAK,AAHjC,CACA,EADQ,MAGuC,GAFrC,MAAM,CAelB;AAED;;;;;;;;;GASG;AACH,iBAAS,yBAAyB,CAAC,KAAK,EAL7B,MAK6B,EAAE,SAAS,EAJxC,MAIwC,EAAE,KAAK,EAH/C,OAG+C,GAF7C,MAAM,CAYlB;AAID,OAAO,EACL,eAAe,EACf,UAAU,EACV,GAAG,EACH,oBAAoB,EACpB,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,SAAS,EACT,SAAS,EACT,YAAY,EACZ,WAAW,EACX,WAAW,EACX,QAAQ,EACR,sBAAsB,EACtB,yBAAyB,EAC1B,CAAC"}
|
package/package.json
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"eslint": "^10.10.0",
|
|
22
22
|
"globals": "^17.12.0",
|
|
23
23
|
"typescript": "^7.0.2",
|
|
24
|
-
"vite": "^8.
|
|
24
|
+
"vite": "^8.3.0"
|
|
25
25
|
},
|
|
26
26
|
"engines": {
|
|
27
27
|
"node": ">=22.13"
|
|
@@ -95,5 +95,5 @@
|
|
|
95
95
|
},
|
|
96
96
|
"type": "module",
|
|
97
97
|
"types": "dist/types/htmlminifier.d.ts",
|
|
98
|
-
"version": "8.4.
|
|
98
|
+
"version": "8.4.4"
|
|
99
99
|
}
|
package/src/lib/file-pool.js
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* worker runs its own isolate and warms up its own JIT, so the useful worker count tops
|
|
16
16
|
* out well short of the core count.
|
|
17
17
|
*
|
|
18
|
-
* Node-only: cli.js loads this module lazily and minifies in
|
|
18
|
+
* Node-only: cli.js loads this module lazily and minifies in-process wherever worker
|
|
19
19
|
* threads are unavailable or the options can’t cross a structured clone.
|
|
20
20
|
*/
|
|
21
21
|
|
package/src/lib/utils.js
CHANGED
|
@@ -2,13 +2,35 @@
|
|
|
2
2
|
* General utility functions
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
// Functions and other non-plain objects have no structure to compare (closures with the
|
|
6
|
+
// same source can behave differently), so they are told apart by identity
|
|
7
|
+
/** @type {WeakMap<object, number>} */
|
|
8
|
+
const objectIds = new WeakMap();
|
|
9
|
+
let objectIdLast = 0;
|
|
10
|
+
|
|
11
|
+
/** @param {object} obj */
|
|
12
|
+
function objectId(obj) {
|
|
13
|
+
let id = objectIds.get(obj);
|
|
14
|
+
if (id === undefined) {
|
|
15
|
+
id = ++objectIdLast;
|
|
16
|
+
objectIds.set(obj, id);
|
|
17
|
+
}
|
|
18
|
+
return id;
|
|
19
|
+
}
|
|
20
|
+
|
|
5
21
|
/**
|
|
22
|
+
* Stringify with sorted keys, for cache keys—values that can behave differently must not
|
|
23
|
+
* stringify alike, so unquoted markers stand in for what JSON cannot express
|
|
6
24
|
* @param {unknown} obj
|
|
7
25
|
* @returns {string}
|
|
8
26
|
*/
|
|
9
27
|
function stableStringify(obj) {
|
|
28
|
+
if (typeof obj === 'function') return 'function#' + objectId(obj);
|
|
10
29
|
if (obj == null || typeof obj !== 'object') return JSON.stringify(obj);
|
|
30
|
+
if (obj instanceof RegExp) return String(obj);
|
|
11
31
|
if (Array.isArray(obj)) return '[' + obj.map(stableStringify).join(',') + ']';
|
|
32
|
+
const proto = Object.getPrototypeOf(obj);
|
|
33
|
+
if (proto !== Object.prototype && proto !== null) return 'object#' + objectId(obj);
|
|
12
34
|
const keys = Object.keys(obj).sort();
|
|
13
35
|
let out = '{';
|
|
14
36
|
for (let i = 0; i < keys.length; i++) {
|