html-minifier-next 4.1.0 → 4.2.0
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
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
HTML Minifier Next (HMN) is a highly **configurable, well-tested, JavaScript-based HTML minifier**.
|
|
6
6
|
|
|
7
|
-
The project has been based on [Terser
|
|
7
|
+
The project has been based on [HTML Minifier Terser](https://github.com/terser/html-minifier-terser), which in turn had been based on [Juriy Zaytsev’s HTML Minifier](https://github.com/kangax/html-minifier) (HMN offers additional features, but is compatible with both). It was set up because as of 2025, both HTML Minifier Terser and HTML Minifier have been unmaintained for some time. As the project seems maintainable [to me, [Jens](https://meiert.com/)]—even more so with community support—, it’s being updated and documented further in this place.
|
|
8
8
|
|
|
9
9
|
## Installation
|
|
10
10
|
|
package/dist/htmlminifier.cjs
CHANGED
|
@@ -2160,7 +2160,7 @@ var htmlminifier = { minify };
|
|
|
2160
2160
|
*
|
|
2161
2161
|
* Default: No limit
|
|
2162
2162
|
*
|
|
2163
|
-
* @prop {boolean | import("lightningcss").TransformOptions<import("lightningcss").CustomAtRules
|
|
2163
|
+
* @prop {boolean | Partial<import("lightningcss").TransformOptions<import("lightningcss").CustomAtRules>> | ((text: string, type?: string) => Promise<string> | string)} [minifyCSS]
|
|
2164
2164
|
* When true, enables CSS minification for inline `<style>` tags or
|
|
2165
2165
|
* `style` attributes. If an object is provided, it is passed to
|
|
2166
2166
|
* [Lightning CSS](https://www.npmjs.com/package/lightningcss)
|
|
@@ -22332,8 +22332,8 @@ function remove_initializers(var_statement) {
|
|
|
22332
22332
|
return decls.length ? make_node(AST_Var, var_statement, { definitions: decls }) : null;
|
|
22333
22333
|
}
|
|
22334
22334
|
|
|
22335
|
-
/** Called on code which
|
|
22336
|
-
function
|
|
22335
|
+
/** Called on code which won't be executed but has an effect outside of itself: `var`, `function` statements, `export`, `import`. */
|
|
22336
|
+
function extract_from_unreachable_code(compressor, stat, target) {
|
|
22337
22337
|
walk(stat, node => {
|
|
22338
22338
|
if (node instanceof AST_Var) {
|
|
22339
22339
|
const no_initializers = remove_initializers(node);
|
|
@@ -22358,7 +22358,8 @@ function trim_unreachable_code(compressor, stat, target) {
|
|
|
22358
22358
|
target.push(node);
|
|
22359
22359
|
return true;
|
|
22360
22360
|
}
|
|
22361
|
-
if (node instanceof AST_Scope) {
|
|
22361
|
+
if (node instanceof AST_Scope || node instanceof AST_Class) {
|
|
22362
|
+
// Do not go into nested scopes
|
|
22362
22363
|
return true;
|
|
22363
22364
|
}
|
|
22364
22365
|
});
|
|
@@ -23382,7 +23383,7 @@ function tighten_body(statements, compressor) {
|
|
|
23382
23383
|
CHANGED = n != len;
|
|
23383
23384
|
if (has_quit)
|
|
23384
23385
|
has_quit.forEach(function (stat) {
|
|
23385
|
-
|
|
23386
|
+
extract_from_unreachable_code(compressor, stat, statements);
|
|
23386
23387
|
});
|
|
23387
23388
|
}
|
|
23388
23389
|
|
|
@@ -24565,6 +24566,11 @@ class Compressor extends TreeWalker {
|
|
|
24565
24566
|
}
|
|
24566
24567
|
}
|
|
24567
24568
|
|
|
24569
|
+
/** True if compressor.self()'s result will be turned into a 32-bit integer.
|
|
24570
|
+
* ex:
|
|
24571
|
+
* ~{expr}
|
|
24572
|
+
* (1, 2, {expr}) | 0
|
|
24573
|
+
**/
|
|
24568
24574
|
in_32_bit_context(other_operand_must_be_number) {
|
|
24569
24575
|
if (!this.option("evaluate")) return false;
|
|
24570
24576
|
var self = this.self();
|
|
@@ -24582,9 +24588,10 @@ class Compressor extends TreeWalker {
|
|
|
24582
24588
|
if (
|
|
24583
24589
|
p instanceof AST_Binary
|
|
24584
24590
|
&& (
|
|
24585
|
-
p.
|
|
24586
|
-
|
|
24587
|
-
|| p.operator == "
|
|
24591
|
+
// Don't talk about p.left. Can change branch taken
|
|
24592
|
+
p.operator == "&&" && p.right === self
|
|
24593
|
+
|| p.operator == "||" && p.right === self
|
|
24594
|
+
|| p.operator == "??" && p.right === self
|
|
24588
24595
|
)
|
|
24589
24596
|
|| p instanceof AST_Conditional && p.condition !== self
|
|
24590
24597
|
|| p.tail_node() === self
|
|
@@ -25187,7 +25194,7 @@ function if_break_in_loop(self, compressor) {
|
|
|
25187
25194
|
body: self.condition
|
|
25188
25195
|
}));
|
|
25189
25196
|
}
|
|
25190
|
-
|
|
25197
|
+
extract_from_unreachable_code(compressor, self.body, body);
|
|
25191
25198
|
return make_node(AST_BlockStatement, self, {
|
|
25192
25199
|
body: body
|
|
25193
25200
|
});
|
|
@@ -25258,7 +25265,7 @@ def_optimize(AST_For, function(self, compressor) {
|
|
|
25258
25265
|
if (cond instanceof AST_Node) cond = self.condition.tail_node().evaluate(compressor);
|
|
25259
25266
|
if (!cond) {
|
|
25260
25267
|
var body = [];
|
|
25261
|
-
|
|
25268
|
+
extract_from_unreachable_code(compressor, self.body, body);
|
|
25262
25269
|
if (self.init instanceof AST_Statement) {
|
|
25263
25270
|
body.push(self.init);
|
|
25264
25271
|
} else if (self.init) {
|
|
@@ -25294,7 +25301,7 @@ def_optimize(AST_If, function(self, compressor) {
|
|
|
25294
25301
|
if (cond instanceof AST_Node) cond = self.condition.tail_node().evaluate(compressor);
|
|
25295
25302
|
if (!cond) {
|
|
25296
25303
|
var body = [];
|
|
25297
|
-
|
|
25304
|
+
extract_from_unreachable_code(compressor, self.body, body);
|
|
25298
25305
|
body.push(make_node(AST_SimpleStatement, self.condition, {
|
|
25299
25306
|
body: self.condition
|
|
25300
25307
|
}));
|
|
@@ -25307,7 +25314,7 @@ def_optimize(AST_If, function(self, compressor) {
|
|
|
25307
25314
|
}));
|
|
25308
25315
|
body.push(self.body);
|
|
25309
25316
|
if (self.alternative) {
|
|
25310
|
-
|
|
25317
|
+
extract_from_unreachable_code(compressor, self.alternative, body);
|
|
25311
25318
|
}
|
|
25312
25319
|
return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
|
|
25313
25320
|
}
|
|
@@ -25435,6 +25442,9 @@ def_optimize(AST_Switch, function(self, compressor) {
|
|
|
25435
25442
|
var body = [];
|
|
25436
25443
|
var default_branch;
|
|
25437
25444
|
var exact_match;
|
|
25445
|
+
// - compress self.body into `body`
|
|
25446
|
+
// - find and deduplicate default branch
|
|
25447
|
+
// - find the exact match (`case 1234` inside `switch(1234)`)
|
|
25438
25448
|
for (var i = 0, len = self.body.length; i < len && !exact_match; i++) {
|
|
25439
25449
|
branch = self.body[i];
|
|
25440
25450
|
if (branch instanceof AST_Default) {
|
|
@@ -25464,6 +25474,7 @@ def_optimize(AST_Switch, function(self, compressor) {
|
|
|
25464
25474
|
}
|
|
25465
25475
|
body.push(branch);
|
|
25466
25476
|
}
|
|
25477
|
+
// i < len if we found an exact_match. eliminate the rest
|
|
25467
25478
|
while (i < len) eliminate_branch(self.body[i++], body[body.length - 1]);
|
|
25468
25479
|
self.body = body;
|
|
25469
25480
|
|
|
@@ -25535,7 +25546,7 @@ def_optimize(AST_Switch, function(self, compressor) {
|
|
|
25535
25546
|
let i = body.length - 1;
|
|
25536
25547
|
for (; i >= 0; i--) {
|
|
25537
25548
|
let bbody = body[i].body;
|
|
25538
|
-
|
|
25549
|
+
while (is_break(bbody[bbody.length - 1], compressor)) bbody.pop();
|
|
25539
25550
|
if (!is_inert_body(body[i])) break;
|
|
25540
25551
|
}
|
|
25541
25552
|
// i now points to the index of a branch that contains a body. By incrementing, it's
|
|
@@ -25551,9 +25562,9 @@ def_optimize(AST_Switch, function(self, compressor) {
|
|
|
25551
25562
|
let branch = body[j];
|
|
25552
25563
|
if (branch === default_or_exact) {
|
|
25553
25564
|
default_or_exact = null;
|
|
25554
|
-
body.pop();
|
|
25565
|
+
eliminate_branch(body.pop());
|
|
25555
25566
|
} else if (!branch.expression.has_side_effects(compressor)) {
|
|
25556
|
-
body.pop();
|
|
25567
|
+
eliminate_branch(body.pop());
|
|
25557
25568
|
} else {
|
|
25558
25569
|
break;
|
|
25559
25570
|
}
|
|
@@ -25667,15 +25678,16 @@ def_optimize(AST_Switch, function(self, compressor) {
|
|
|
25667
25678
|
// and there's a side-effect somewhere. Just let the below paths take care of it.
|
|
25668
25679
|
}
|
|
25669
25680
|
|
|
25681
|
+
// Reintegrate `decl` (var statements)
|
|
25670
25682
|
if (body.length > 0) {
|
|
25671
25683
|
body[0].body = decl.concat(body[0].body);
|
|
25672
25684
|
}
|
|
25673
|
-
|
|
25674
25685
|
if (body.length == 0) {
|
|
25675
25686
|
return make_node(AST_BlockStatement, self, {
|
|
25676
25687
|
body: decl.concat(statement(self.expression))
|
|
25677
25688
|
}).optimize(compressor);
|
|
25678
25689
|
}
|
|
25690
|
+
|
|
25679
25691
|
if (body.length == 1 && !has_nested_break(self)) {
|
|
25680
25692
|
// This is the last case body, and we've already pruned any breaks, so it's
|
|
25681
25693
|
// safe to hoist.
|
|
@@ -25755,7 +25767,7 @@ def_optimize(AST_Switch, function(self, compressor) {
|
|
|
25755
25767
|
if (prev && !aborts(prev)) {
|
|
25756
25768
|
prev.body = prev.body.concat(branch.body);
|
|
25757
25769
|
} else {
|
|
25758
|
-
|
|
25770
|
+
extract_from_unreachable_code(compressor, branch, decl);
|
|
25759
25771
|
}
|
|
25760
25772
|
}
|
|
25761
25773
|
function branches_equivalent(branch, prev, insertBreak) {
|
|
@@ -25809,7 +25821,7 @@ def_optimize(AST_Try, function(self, compressor) {
|
|
|
25809
25821
|
if (compressor.option("dead_code") && self.body.body.every(is_empty)) {
|
|
25810
25822
|
var body = [];
|
|
25811
25823
|
if (self.bcatch) {
|
|
25812
|
-
|
|
25824
|
+
extract_from_unreachable_code(compressor, self.bcatch, body);
|
|
25813
25825
|
}
|
|
25814
25826
|
if (self.bfinally) body.push(...self.bfinally.body);
|
|
25815
25827
|
return make_node(AST_BlockStatement, self, {
|
|
@@ -41201,7 +41213,7 @@ var htmlminifier = { minify };
|
|
|
41201
41213
|
*
|
|
41202
41214
|
* Default: No limit
|
|
41203
41215
|
*
|
|
41204
|
-
* @prop {boolean | import("lightningcss").TransformOptions<import("lightningcss").CustomAtRules
|
|
41216
|
+
* @prop {boolean | Partial<import("lightningcss").TransformOptions<import("lightningcss").CustomAtRules>> | ((text: string, type?: string) => Promise<string> | string)} [minifyCSS]
|
|
41205
41217
|
* When true, enables CSS minification for inline `<style>` tags or
|
|
41206
41218
|
* `style` attributes. If an object is provided, it is passed to
|
|
41207
41219
|
* [Lightning CSS](https://www.npmjs.com/package/lightningcss)
|
|
@@ -197,7 +197,7 @@ export type MinifierOptions = {
|
|
|
197
197
|
*
|
|
198
198
|
* Default: `false`
|
|
199
199
|
*/
|
|
200
|
-
minifyCSS?: boolean | import("lightningcss").TransformOptions<import("lightningcss").CustomAtRules
|
|
200
|
+
minifyCSS?: boolean | Partial<import("lightningcss").TransformOptions<import("lightningcss").CustomAtRules>> | ((text: string, type?: string) => Promise<string> | string);
|
|
201
201
|
/**
|
|
202
202
|
* When true, enables JS minification for `<script>` contents and
|
|
203
203
|
* event handler attributes. If an object is provided, it is passed to
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"htmlminifier.d.ts","sourceRoot":"","sources":["../../src/htmlminifier.js"],"names":[],"mappings":"AAm7CO,8BAJI,MAAM,YACN,eAAe,GACb,OAAO,CAAC,MAAM,CAAC,CAQ3B;;;;;;;;;UAQS,MAAM;YACN,MAAM;YACN,MAAM;mBACN,MAAM;iBACN,MAAM;kBACN,MAAM;;;;;;;;;;;;;4BAQN,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE,qBAAqB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,KAAK,OAAO;;;;;;;wBAMjG,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,SAAS,EAAE,iBAAiB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,KAAK,OAAO;;;;;;;;oBAMhH,OAAO;;;;;;;;gCAOP,OAAO;;;;;;;;kCAOP,OAAO;;;;;;;;yBAOP,OAAO;;;;;;;;2BAOP,OAAO;;;;;;;2BAOP,OAAO;;;;;;;;uBAMP,MAAM,EAAE;;;;;;yBAOR,MAAM;;;;;;yBAKN,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE;;;;;;;4BAKlB,MAAM,EAAE;;;;;;;oCAMR,MAAM;;;;;;;qBAMN,OAAO;;;;;;;YAMP,OAAO;;;;;;;;2BAMP,MAAM,EAAE;;;;;;;;;4BAOR,MAAM,EAAE;;;;;;;+BAQR,OAAO;;;;;;;2BAMP,SAAS,CAAC,MAAM,CAAC;;;;;;uBAMjB,OAAO;;;;;;;;UAKP,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI;;;;;;;;qBAO1B,MAAM;;;;;;;oBAON,MAAM;;;;;;;;;;gBAMN,OAAO,GAAG,OAAO,cAAc,EAAE,gBAAgB,CAAC,OAAO,cAAc,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"htmlminifier.d.ts","sourceRoot":"","sources":["../../src/htmlminifier.js"],"names":[],"mappings":"AAm7CO,8BAJI,MAAM,YACN,eAAe,GACb,OAAO,CAAC,MAAM,CAAC,CAQ3B;;;;;;;;;UAQS,MAAM;YACN,MAAM;YACN,MAAM;mBACN,MAAM;iBACN,MAAM;kBACN,MAAM;;;;;;;;;;;;;4BAQN,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE,qBAAqB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,KAAK,OAAO;;;;;;;wBAMjG,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,SAAS,EAAE,iBAAiB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,KAAK,OAAO;;;;;;;;oBAMhH,OAAO;;;;;;;;gCAOP,OAAO;;;;;;;;kCAOP,OAAO;;;;;;;;yBAOP,OAAO;;;;;;;;2BAOP,OAAO;;;;;;;2BAOP,OAAO;;;;;;;;uBAMP,MAAM,EAAE;;;;;;yBAOR,MAAM;;;;;;yBAKN,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE;;;;;;;4BAKlB,MAAM,EAAE;;;;;;;oCAMR,MAAM;;;;;;;qBAMN,OAAO;;;;;;;YAMP,OAAO;;;;;;;;2BAMP,MAAM,EAAE;;;;;;;;;4BAOR,MAAM,EAAE;;;;;;;+BAQR,OAAO;;;;;;;2BAMP,SAAS,CAAC,MAAM,CAAC;;;;;;uBAMjB,OAAO;;;;;;;;UAKP,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI;;;;;;;;qBAO1B,MAAM;;;;;;;oBAON,MAAM;;;;;;;;;;gBAMN,OAAO,GAAG,OAAO,CAAC,OAAO,cAAc,EAAE,gBAAgB,CAAC,OAAO,cAAc,EAAE,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;;;;;;;;;;eAS9J,OAAO,GAAG,OAAO,QAAQ,EAAE,aAAa,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;;;;;;;;;;iBASzG,OAAO,GAAG,MAAM,GAAG,OAAO,WAAW,EAAE,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;;;;;;;;WAS7F,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM;;;;;;;+BAOxB,OAAO;;;;;;;;yBAMP,OAAO;;;;;;;gCAOP,OAAO;;;;;;;;iCAMP,OAAO;;;;;;;;;;qBAOP,MAAM,EAAE;;;;;;;qBASR,IAAI,GAAG,GAAG;;;;;;;4BAMV,OAAO;;;;;;;;qBAMP,OAAO;;;;;;;;;4BAOP,OAAO,GAAG,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;;;;;;;;0BAQtD,OAAO;;;;;;;;yBAOP,OAAO;;;;;;;;gCAOP,OAAO;;;;;;;iCAOP,OAAO;;;;;;;oCAMP,OAAO;;;;;;;;;;0BAMP,OAAO;;;;;;;;;qBASP,OAAO,GAAG,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,IAAI,CAAC;;;;;;;;;oBAQzD,OAAO,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;;;;;;;;0BAQrC,OAAO;;;;;;;sBAOP,OAAO"}
|
package/package.json
CHANGED
|
@@ -11,17 +11,17 @@
|
|
|
11
11
|
"entities": "^7.0.0",
|
|
12
12
|
"lightningcss": "^1.28.2",
|
|
13
13
|
"relateurl": "^0.2.7",
|
|
14
|
-
"terser": "^5.44.
|
|
14
|
+
"terser": "^5.44.1"
|
|
15
15
|
},
|
|
16
16
|
"description": "Highly configurable, well-tested, JavaScript-based HTML minifier",
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"@commitlint/cli": "^20.1.0",
|
|
19
|
-
"@eslint/js": "^9.
|
|
20
|
-
"@rollup/plugin-commonjs": "^
|
|
19
|
+
"@eslint/js": "^9.39.1",
|
|
20
|
+
"@rollup/plugin-commonjs": "^29.0.0",
|
|
21
21
|
"@rollup/plugin-json": "^6.1.0",
|
|
22
22
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
23
23
|
"@rollup/plugin-terser": "^0.4.4",
|
|
24
|
-
"eslint": "^9.
|
|
24
|
+
"eslint": "^9.39.1",
|
|
25
25
|
"rollup": "^4.52.5",
|
|
26
26
|
"rollup-plugin-polyfill-node": "^0.13.0",
|
|
27
27
|
"typescript": "^5.9.3",
|
|
@@ -84,5 +84,5 @@
|
|
|
84
84
|
"test:watch": "node --test --watch tests/*.spec.js"
|
|
85
85
|
},
|
|
86
86
|
"type": "module",
|
|
87
|
-
"version": "4.
|
|
87
|
+
"version": "4.2.0"
|
|
88
88
|
}
|
package/src/htmlminifier.js
CHANGED
|
@@ -1630,7 +1630,7 @@ export default { minify };
|
|
|
1630
1630
|
*
|
|
1631
1631
|
* Default: No limit
|
|
1632
1632
|
*
|
|
1633
|
-
* @prop {boolean | import("lightningcss").TransformOptions<import("lightningcss").CustomAtRules
|
|
1633
|
+
* @prop {boolean | Partial<import("lightningcss").TransformOptions<import("lightningcss").CustomAtRules>> | ((text: string, type?: string) => Promise<string> | string)} [minifyCSS]
|
|
1634
1634
|
* When true, enables CSS minification for inline `<style>` tags or
|
|
1635
1635
|
* `style` attributes. If an object is provided, it is passed to
|
|
1636
1636
|
* [Lightning CSS](https://www.npmjs.com/package/lightningcss)
|